-/* $RCSfile$\r
- * $Author: nicove $\r
- * $Date: 2007-03-30 12:26:16 -0500 (Fri, 30 Mar 2007) $\r
- * $Revision: 7275 $\r
- *\r
- * Copyright (C) 2002-2005 The Jmol Development Team\r
- *\r
- * Contact: jmol-developers@lists.sf.net\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-package javajs.img;\r
-\r
-import java.io.BufferedInputStream;\r
-import java.io.IOException;\r
-\r
-import javajs.util.Rdr;\r
-\r
-/**\r
- * src: http://www.javaworld.com/article/2077542/learn-java/java-tip-43--how-to-\r
- * read-8--and-24-bit-microsoft-windows-bitmaps-in-java-applications.html\r
- *\r
- * see also: http://en.wikipedia.org/wiki/BMP_file_format\r
- * \r
- * Modified by Bob Hanson hansonr@stolaf.edu\r
- * \r
- * @author Bob Hanson (hansonr@stolaf.edu)\r
- * \r
- */\r
-public class BMPDecoder {\r
-\r
- public BMPDecoder() {\r
- // for reflection\r
- }\r
- \r
- private BufferedInputStream bis;\r
-\r
- /**\r
- * original comment:\r
- * \r
- * loadbitmap() method converted from Windows C code. Reads only uncompressed\r
- * 24- and 8-bit images. Tested with images saved using Microsoft Paint in\r
- * Windows 95. If the image is not a 24- or 8-bit image, the program refuses\r
- * to even try. I guess one could include 4-bit images by masking the byte by\r
- * first 1100 and then 0011. I am not really interested in such images. If a\r
- * compressed image is attempted, the routine will probably fail by generating\r
- * an IOException. Look for variable ncompression to be different from 0 to\r
- * indicate compression is present.\r
- * \r
- * @param bytes\r
- * @return [image byte array, width, height]\r
- */\r
- public Object[] decodeWindowsBMP(byte[] bytes) {\r
- try {\r
- bis = Rdr.getBIS(bytes);\r
- temp = new byte[4];\r
- // read BITMAPFILEHEADER\r
- if (readByte() != 'B' || readByte() != 'M')\r
- return null;\r
- readInt(); // file size; ignored\r
- readShort(); // reserved\r
- readShort(); // reserved\r
- readInt(); // ptr to pixel array; ignored\r
- int imageWidth, imageHeight, bitsPerPixel, nColors = 0, imageSize = 0;\r
- // read BITMAP header\r
- int headerSize = readInt();\r
- switch (headerSize) {\r
- case 12:\r
- // BITMAPCOREHEADER\r
- imageWidth = readShort();\r
- imageHeight = readShort();\r
- readShort(); // planes\r
- bitsPerPixel = readShort();\r
- break;\r
- case 40:\r
- // BITMAPINFOHEADER\r
- imageWidth = readInt();\r
- imageHeight = readInt();\r
- readShort(); // planes\r
- bitsPerPixel = readShort();\r
- int ncompression = readInt();\r
- if (ncompression != 0) {\r
- System.out.println("BMP Compression is :" + ncompression\r
- + " -- aborting");\r
- return null;\r
- }\r
- imageSize = readInt();\r
- readInt(); // hres\r
- readInt(); // vres\r
- nColors = readInt();\r
- readInt(); // colors used\r
- break;\r
- default:\r
- System.out.println("BMP Header unrecognized, length=" + headerSize\r
- + " -- aborting");\r
- return null;\r
- }\r
- boolean isYReversed = (imageHeight < 0);\r
- if (isYReversed)\r
- imageHeight = -imageHeight;\r
- int nPixels = imageHeight * imageWidth;\r
- int bytesPerPixel = bitsPerPixel / 8;\r
- nColors = (nColors > 0 ? nColors : 1 << bitsPerPixel);\r
- int npad = (bytesPerPixel == 4 ? 0\r
- : imageSize == 0 ? 4 - (imageWidth % 4) : (imageSize / imageHeight)\r
- - imageWidth * bytesPerPixel) % 4;\r
- int[] palette;\r
- int[] buf = new int[nPixels];\r
- int dpt = (isYReversed ? imageWidth : -imageWidth);\r
- int pt0 = (isYReversed ? 0 : nPixels + dpt);\r
- int pt1 = (isYReversed ? nPixels : dpt);\r
- switch (bitsPerPixel) {\r
- case 32:\r
- case 24:\r
- for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))\r
- for (int i = 0; i < imageWidth; i++)\r
- buf[pt + i] = readColor(bytesPerPixel);\r
- break;\r
- case 8:\r
- palette = new int[nColors];\r
- for (int i = 0; i < nColors; i++)\r
- palette[i] = readColor(4);\r
- for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))\r
- for (int i = 0; i < imageWidth; i++)\r
- buf[pt + i] = palette[readByte()];\r
- break;\r
- case 4:\r
- npad = (4 - (((imageWidth + 1) / 2) % 4)) % 4;\r
- palette = new int[nColors];\r
- for (int i = 0; i < nColors; i++)\r
- palette[i] = readColor(4);\r
- int b4 = 0;\r
- for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))\r
- for (int i = 0, shift = 4; i < imageWidth; i++, shift = 4 - shift)\r
- buf[pt + i] = palette[((shift == 4 ? (b4 = readByte()) : b4) >> shift) & 0xF];\r
- break;\r
- case 1:\r
- int color1 = readColor(3);\r
- int color2 = readColor(3);\r
- npad = (4 - (((imageWidth + 7) / 8) % 4)) % 4;\r
- int b = 0;\r
- for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))\r
- for (int i = 0, bpt = -1; i < imageWidth; i++, bpt--) {\r
- if (bpt < 0) {\r
- b = readByte();\r
- bpt = 7;\r
- }\r
- buf[pt + i] = ((b & (1 << bpt)) == 0 ? color1 : color2);\r
- }\r
- break;\r
- case 64:\r
- case 2:\r
- default:\r
- System.out\r
- .println("Not a 32-, 24-, 8-, 4-, or 1-bit Windows Bitmap, aborting...");\r
- return null;\r
- }\r
- return new Object[] { buf, Integer.valueOf(imageWidth),\r
- Integer.valueOf(imageHeight) };\r
- } catch (Exception e) {\r
- System.out.println("Caught exception in loadbitmap!");\r
- }\r
- return null;\r
- }\r
-\r
- private boolean pad(int npad) throws IOException {\r
- for (int i = 0; i < npad; i++)\r
- readByte();\r
- return true;\r
- }\r
-\r
- private byte[] temp;\r
- \r
- private int readColor(int n) throws IOException {\r
- bis.read(temp, 0, n);\r
- return 0xff << 24 | ((temp[2] & 0xff) << 16)\r
- | ((temp[1] & 0xff) << 8) | temp[0] & 0xff;\r
- }\r
-\r
- private int readInt() throws IOException {\r
- bis.read(temp, 0, 4);\r
- return ((temp[3] & 0xff) << 24) | ((temp[2] & 0xff) << 16)\r
- | ((temp[1] & 0xff) << 8) | temp[0] & 0xff;\r
- }\r
-\r
- private int readShort() throws IOException {\r
- bis.read(temp, 0, 2);\r
- return ((temp[1] & 0xff) << 8) | temp[0] & 0xff;\r
- }\r
-\r
- private int readByte() throws IOException {\r
- bis.read(temp, 0, 1);\r
- return temp[0] & 0xff;\r
- }\r
-\r
-}\r
+/* $RCSfile$
+ * $Author: nicove $
+ * $Date: 2007-03-30 12:26:16 -0500 (Fri, 30 Mar 2007) $
+ * $Revision: 7275 $
+ *
+ * Copyright (C) 2002-2005 The Jmol Development Team
+ *
+ * Contact: jmol-developers@lists.sf.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package javajs.img;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+
+import javajs.util.Rdr;
+
+/**
+ * src: http://www.javaworld.com/article/2077542/learn-java/java-tip-43--how-to-
+ * read-8--and-24-bit-microsoft-windows-bitmaps-in-java-applications.html
+ *
+ * see also: http://en.wikipedia.org/wiki/BMP_file_format
+ *
+ * Modified by Bob Hanson hansonr@stolaf.edu
+ *
+ * @author Bob Hanson (hansonr@stolaf.edu)
+ *
+ */
+public class BMPDecoder {
+
+ public BMPDecoder() {
+ // for reflection
+ }
+
+ private BufferedInputStream bis;
+
+ /**
+ * original comment:
+ *
+ * loadbitmap() method converted from Windows C code. Reads only uncompressed
+ * 24- and 8-bit images. Tested with images saved using Microsoft Paint in
+ * Windows 95. If the image is not a 24- or 8-bit image, the program refuses
+ * to even try. I guess one could include 4-bit images by masking the byte by
+ * first 1100 and then 0011. I am not really interested in such images. If a
+ * compressed image is attempted, the routine will probably fail by generating
+ * an IOException. Look for variable ncompression to be different from 0 to
+ * indicate compression is present.
+ *
+ * @param bytes
+ * @return [image byte array, width, height]
+ */
+ public Object[] decodeWindowsBMP(byte[] bytes) {
+ try {
+ bis = Rdr.getBIS(bytes);
+ temp = new byte[4];
+ // read BITMAPFILEHEADER
+ if (readByte() != 'B' || readByte() != 'M')
+ return null;
+ readInt(); // file size; ignored
+ readShort(); // reserved
+ readShort(); // reserved
+ readInt(); // ptr to pixel array; ignored
+ int imageWidth, imageHeight, bitsPerPixel, nColors = 0, imageSize = 0;
+ // read BITMAP header
+ int headerSize = readInt();
+ switch (headerSize) {
+ case 12:
+ // BITMAPCOREHEADER
+ imageWidth = readShort();
+ imageHeight = readShort();
+ readShort(); // planes
+ bitsPerPixel = readShort();
+ break;
+ case 40:
+ // BITMAPINFOHEADER
+ imageWidth = readInt();
+ imageHeight = readInt();
+ readShort(); // planes
+ bitsPerPixel = readShort();
+ int ncompression = readInt();
+ if (ncompression != 0) {
+ System.out.println("BMP Compression is :" + ncompression
+ + " -- aborting");
+ return null;
+ }
+ imageSize = readInt();
+ readInt(); // hres
+ readInt(); // vres
+ nColors = readInt();
+ readInt(); // colors used
+ break;
+ default:
+ System.out.println("BMP Header unrecognized, length=" + headerSize
+ + " -- aborting");
+ return null;
+ }
+ boolean isYReversed = (imageHeight < 0);
+ if (isYReversed)
+ imageHeight = -imageHeight;
+ int nPixels = imageHeight * imageWidth;
+ int bytesPerPixel = bitsPerPixel / 8;
+ nColors = (nColors > 0 ? nColors : 1 << bitsPerPixel);
+ int npad = (bytesPerPixel == 4 ? 0
+ : imageSize == 0 ? 4 - (imageWidth % 4) : (imageSize / imageHeight)
+ - imageWidth * bytesPerPixel) % 4;
+ int[] palette;
+ int[] buf = new int[nPixels];
+ int dpt = (isYReversed ? imageWidth : -imageWidth);
+ int pt0 = (isYReversed ? 0 : nPixels + dpt);
+ int pt1 = (isYReversed ? nPixels : dpt);
+ switch (bitsPerPixel) {
+ case 32:
+ case 24:
+ for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))
+ for (int i = 0; i < imageWidth; i++)
+ buf[pt + i] = readColor(bytesPerPixel);
+ break;
+ case 8:
+ palette = new int[nColors];
+ for (int i = 0; i < nColors; i++)
+ palette[i] = readColor(4);
+ for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))
+ for (int i = 0; i < imageWidth; i++)
+ buf[pt + i] = palette[readByte()];
+ break;
+ case 4:
+ npad = (4 - (((imageWidth + 1) / 2) % 4)) % 4;
+ palette = new int[nColors];
+ for (int i = 0; i < nColors; i++)
+ palette[i] = readColor(4);
+ int b4 = 0;
+ for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))
+ for (int i = 0, shift = 4; i < imageWidth; i++, shift = 4 - shift)
+ buf[pt + i] = palette[((shift == 4 ? (b4 = readByte()) : b4) >> shift) & 0xF];
+ break;
+ case 1:
+ int color1 = readColor(3);
+ int color2 = readColor(3);
+ npad = (4 - (((imageWidth + 7) / 8) % 4)) % 4;
+ int b = 0;
+ for (int pt = pt0; pt != pt1; pt += dpt, pad(npad))
+ for (int i = 0, bpt = -1; i < imageWidth; i++, bpt--) {
+ if (bpt < 0) {
+ b = readByte();
+ bpt = 7;
+ }
+ buf[pt + i] = ((b & (1 << bpt)) == 0 ? color1 : color2);
+ }
+ break;
+ case 64:
+ case 2:
+ default:
+ System.out
+ .println("Not a 32-, 24-, 8-, 4-, or 1-bit Windows Bitmap, aborting...");
+ return null;
+ }
+ return new Object[] { buf, Integer.valueOf(imageWidth),
+ Integer.valueOf(imageHeight) };
+ } catch (Exception e) {
+ System.out.println("Caught exception in loadbitmap!");
+ }
+ return null;
+ }
+
+ private boolean pad(int npad) throws IOException {
+ for (int i = 0; i < npad; i++)
+ readByte();
+ return true;
+ }
+
+ private byte[] temp;
+
+ private int readColor(int n) throws IOException {
+ bis.read(temp, 0, n);
+ return 0xff << 24 | ((temp[2] & 0xff) << 16)
+ | ((temp[1] & 0xff) << 8) | temp[0] & 0xff;
+ }
+
+ private int readInt() throws IOException {
+ bis.read(temp, 0, 4);
+ return ((temp[3] & 0xff) << 24) | ((temp[2] & 0xff) << 16)
+ | ((temp[1] & 0xff) << 8) | temp[0] & 0xff;
+ }
+
+ private int readShort() throws IOException {
+ bis.read(temp, 0, 2);
+ return ((temp[1] & 0xff) << 8) | temp[0] & 0xff;
+ }
+
+ private int readByte() throws IOException {
+ bis.read(temp, 0, 1);
+ return temp[0] & 0xff;
+ }
+
+}