aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/lowagie/text/pdf/codec/BmpImage.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/lowagie/text/pdf/codec/BmpImage.java')
-rw-r--r--src/main/java/com/lowagie/text/pdf/codec/BmpImage.java1282
1 files changed, 0 insertions, 1282 deletions
diff --git a/src/main/java/com/lowagie/text/pdf/codec/BmpImage.java b/src/main/java/com/lowagie/text/pdf/codec/BmpImage.java
deleted file mode 100644
index f9f80be..0000000
--- a/src/main/java/com/lowagie/text/pdf/codec/BmpImage.java
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * Copyright 2003 by Paulo Soares.
- *
- * The contents of this file are subject to the Mozilla Public License Version 1.1
- * (the "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the License.
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- * Alternatively, the contents of this file may be used under the terms of the
- * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
- * provisions of LGPL are applicable instead of those above. If you wish to
- * allow use of your version of this file only under the terms of the LGPL
- * License and not to allow others to use your version of this file under
- * the MPL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the LGPL.
- * If you do not delete the provisions above, a recipient may use your version
- * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the MPL as stated above or under the terms of the GNU
- * Library General Public License as published by the Free Software Foundation;
- * either version 2 of the License, or 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 Library general Public License for more
- * details.
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- *
- *
- * The original JAI codecs have the following license
- *
- * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * -Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * -Redistribution in binary form must reproduct the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
- * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
- * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
- * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
- * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
- * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
- * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
- * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
- * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that Software is not designed,licensed or intended for use in
- * the design, construction, operation or maintenance of any nuclear facility.
- */
-package com.lowagie.text.pdf.codec;
-
-import com.lowagie.text.pdf.*;
-import com.lowagie.text.*;
-import java.io.*;
-import java.util.HashMap;
-import java.net.URL;
-
-/** Reads a BMP image. All types of BMP can be read.
- * <p>
- * It is based in the JAI codec.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BmpImage {
-
- // BMP variables
- private InputStream inputStream;
- private long bitmapFileSize;
- private long bitmapOffset;
- private long compression;
- private long imageSize;
- private byte palette[];
- private int imageType;
- private int numBands;
- private boolean isBottomUp;
- private int bitsPerPixel;
- private int redMask, greenMask, blueMask, alphaMask;
- public HashMap properties = new HashMap();
- private long xPelsPerMeter;
- private long yPelsPerMeter;
- // BMP Image types
- private static final int VERSION_2_1_BIT = 0;
- private static final int VERSION_2_4_BIT = 1;
- private static final int VERSION_2_8_BIT = 2;
- private static final int VERSION_2_24_BIT = 3;
-
- private static final int VERSION_3_1_BIT = 4;
- private static final int VERSION_3_4_BIT = 5;
- private static final int VERSION_3_8_BIT = 6;
- private static final int VERSION_3_24_BIT = 7;
-
- private static final int VERSION_3_NT_16_BIT = 8;
- private static final int VERSION_3_NT_32_BIT = 9;
-
- private static final int VERSION_4_1_BIT = 10;
- private static final int VERSION_4_4_BIT = 11;
- private static final int VERSION_4_8_BIT = 12;
- private static final int VERSION_4_16_BIT = 13;
- private static final int VERSION_4_24_BIT = 14;
- private static final int VERSION_4_32_BIT = 15;
-
- // Color space types
- private static final int LCS_CALIBRATED_RGB = 0;
- private static final int LCS_sRGB = 1;
- private static final int LCS_CMYK = 2;
-
- // Compression Types
- private static final int BI_RGB = 0;
- private static final int BI_RLE8 = 1;
- private static final int BI_RLE4 = 2;
- private static final int BI_BITFIELDS = 3;
-
- int width;
- int height;
-
- BmpImage(InputStream is, boolean noHeader, int size) throws IOException {
- bitmapFileSize = size;
- bitmapOffset = 0;
- process(is, noHeader);
- }
-
- /** Reads a BMP from an url.
- * @param url the url
- * @throws IOException on error
- * @return the image
- */
- public static Image getImage(URL url) throws IOException {
- InputStream is = null;
- try {
- is = url.openStream();
- Image img = getImage(is);
- img.setUrl(url);
- return img;
- }
- finally {
- if (is != null) {
- is.close();
- }
- }
- }
-
- /** Reads a BMP from a stream. The stream is not closed.
- * @param is the stream
- * @throws IOException on error
- * @return the image
- */
- public static Image getImage(InputStream is) throws IOException {
- return getImage(is, false, 0);
- }
-
- /** Reads a BMP from a stream. The stream is not closed.
- * The BMP may not have a header and be considered as a plain DIB.
- * @param is the stream
- * @param noHeader true to process a plain DIB
- * @param size the size of the DIB. Not used for a BMP
- * @throws IOException on error
- * @return the image
- */
- public static Image getImage(InputStream is, boolean noHeader, int size) throws IOException {
- BmpImage bmp = new BmpImage(is, noHeader, size);
- try {
- Image img = bmp.getImage();
- img.setDpi((int)((double)bmp.xPelsPerMeter * 0.0254), (int)((double)bmp.yPelsPerMeter * 0.0254));
- img.setOriginalType(Image.ORIGINAL_BMP);
- return img;
- }
- catch (BadElementException be) {
- throw new ExceptionConverter(be);
- }
- }
-
- /** Reads a BMP from a file.
- * @param file the file
- * @throws IOException on error
- * @return the image
- */
- public static Image getImage(String file) throws IOException {
- return getImage(Image.toURL(file));
- }
-
- /** Reads a BMP from a byte array.
- * @param data the byte array
- * @throws IOException on error
- * @return the image
- */
- public static Image getImage(byte data[]) throws IOException {
- InputStream is = null;
- try {
- is = new ByteArrayInputStream(data);
- Image img = getImage(is);
- img.setOriginalData(data);
- return img;
- }
- finally {
- if (is != null) {
- is.close();
- }
- }
- }
-
-
- protected void process(InputStream stream, boolean noHeader) throws IOException {
- if (noHeader || stream instanceof BufferedInputStream) {
- inputStream = stream;
- } else {
- inputStream = new BufferedInputStream(stream);
- }
- if (!noHeader) {
- // Start File Header
- if (!(readUnsignedByte(inputStream) == 'B' &&
- readUnsignedByte(inputStream) == 'M')) {
- throw new
- RuntimeException("Invalid magic value for BMP file.");
- }
-
- // Read file size
- bitmapFileSize = readDWord(inputStream);
-
- // Read the two reserved fields
- readWord(inputStream);
- readWord(inputStream);
-
- // Offset to the bitmap from the beginning
- bitmapOffset = readDWord(inputStream);
-
- // End File Header
- }
- // Start BitmapCoreHeader
- long size = readDWord(inputStream);
-
- if (size == 12) {
- width = readWord(inputStream);
- height = readWord(inputStream);
- } else {
- width = readLong(inputStream);
- height = readLong(inputStream);
- }
-
- int planes = readWord(inputStream);
- bitsPerPixel = readWord(inputStream);
-
- properties.put("color_planes", new Integer(planes));
- properties.put("bits_per_pixel", new Integer(bitsPerPixel));
-
- // As BMP always has 3 rgb bands, except for Version 5,
- // which is bgra
- numBands = 3;
- if (bitmapOffset == 0)
- bitmapOffset = size;
- if (size == 12) {
- // Windows 2.x and OS/2 1.x
- properties.put("bmp_version", "BMP v. 2.x");
-
- // Classify the image type
- if (bitsPerPixel == 1) {
- imageType = VERSION_2_1_BIT;
- } else if (bitsPerPixel == 4) {
- imageType = VERSION_2_4_BIT;
- } else if (bitsPerPixel == 8) {
- imageType = VERSION_2_8_BIT;
- } else if (bitsPerPixel == 24) {
- imageType = VERSION_2_24_BIT;
- }
-
- // Read in the palette
- int numberOfEntries = (int)((bitmapOffset-14-size) / 3);
- int sizeOfPalette = numberOfEntries*3;
- if (bitmapOffset == size) {
- switch (imageType) {
- case VERSION_2_1_BIT:
- sizeOfPalette = 2 * 3;
- break;
- case VERSION_2_4_BIT:
- sizeOfPalette = 16 * 3;
- break;
- case VERSION_2_8_BIT:
- sizeOfPalette = 256 * 3;
- break;
- case VERSION_2_24_BIT:
- sizeOfPalette = 0;
- break;
- }
- bitmapOffset = size + sizeOfPalette;
- }
- palette = new byte[sizeOfPalette];
- inputStream.read(palette, 0, sizeOfPalette);
- properties.put("palette", palette);
- } else {
-
- compression = readDWord(inputStream);
- imageSize = readDWord(inputStream);
- xPelsPerMeter = readLong(inputStream);
- yPelsPerMeter = readLong(inputStream);
- long colorsUsed = readDWord(inputStream);
- long colorsImportant = readDWord(inputStream);
-
- switch((int)compression) {
- case BI_RGB:
- properties.put("compression", "BI_RGB");
- break;
-
- case BI_RLE8:
- properties.put("compression", "BI_RLE8");
- break;
-
- case BI_RLE4:
- properties.put("compression", "BI_RLE4");
- break;
-
- case BI_BITFIELDS:
- properties.put("compression", "BI_BITFIELDS");
- break;
- }
-
- properties.put("x_pixels_per_meter", new Long(xPelsPerMeter));
- properties.put("y_pixels_per_meter", new Long(yPelsPerMeter));
- properties.put("colors_used", new Long(colorsUsed));
- properties.put("colors_important", new Long(colorsImportant));
-
- if (size == 40) {
- // Windows 3.x and Windows NT
- switch((int)compression) {
-
- case BI_RGB: // No compression
- case BI_RLE8: // 8-bit RLE compression
- case BI_RLE4: // 4-bit RLE compression
-
- if (bitsPerPixel == 1) {
- imageType = VERSION_3_1_BIT;
- } else if (bitsPerPixel == 4) {
- imageType = VERSION_3_4_BIT;
- } else if (bitsPerPixel == 8) {
- imageType = VERSION_3_8_BIT;
- } else if (bitsPerPixel == 24) {
- imageType = VERSION_3_24_BIT;
- } else if (bitsPerPixel == 16) {
- imageType = VERSION_3_NT_16_BIT;
- redMask = 0x7C00;
- greenMask = 0x3E0;
- blueMask = 0x1F;
- properties.put("red_mask", new Integer(redMask));
- properties.put("green_mask", new Integer(greenMask));
- properties.put("blue_mask", new Integer(blueMask));
- } else if (bitsPerPixel == 32) {
- imageType = VERSION_3_NT_32_BIT;
- redMask = 0x00FF0000;
- greenMask = 0x0000FF00;
- blueMask = 0x000000FF;
- properties.put("red_mask", new Integer(redMask));
- properties.put("green_mask", new Integer(greenMask));
- properties.put("blue_mask", new Integer(blueMask));
- }
-
- // Read in the palette
- int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
- int sizeOfPalette = numberOfEntries*4;
- if (bitmapOffset == size) {
- switch (imageType) {
- case VERSION_3_1_BIT:
- sizeOfPalette = (int)(colorsUsed == 0 ? 2 : colorsUsed) * 4;
- break;
- case VERSION_3_4_BIT:
- sizeOfPalette = (int)(colorsUsed == 0 ? 16 : colorsUsed) * 4;
- break;
- case VERSION_3_8_BIT:
- sizeOfPalette = (int)(colorsUsed == 0 ? 256 : colorsUsed) * 4;
- break;
- default:
- sizeOfPalette = 0;
- break;
- }
- bitmapOffset = size + sizeOfPalette;
- }
- palette = new byte[sizeOfPalette];
- inputStream.read(palette, 0, sizeOfPalette);
- properties.put("palette", palette);
-
- properties.put("bmp_version", "BMP v. 3.x");
- break;
-
- case BI_BITFIELDS:
-
- if (bitsPerPixel == 16) {
- imageType = VERSION_3_NT_16_BIT;
- } else if (bitsPerPixel == 32) {
- imageType = VERSION_3_NT_32_BIT;
- }
-
- // BitsField encoding
- redMask = (int)readDWord(inputStream);
- greenMask = (int)readDWord(inputStream);
- blueMask = (int)readDWord(inputStream);
-
- properties.put("red_mask", new Integer(redMask));
- properties.put("green_mask", new Integer(greenMask));
- properties.put("blue_mask", new Integer(blueMask));
-
- if (colorsUsed != 0) {
- // there is a palette
- sizeOfPalette = (int)colorsUsed*4;
- palette = new byte[sizeOfPalette];
- inputStream.read(palette, 0, sizeOfPalette);
- properties.put("palette", palette);
- }
-
- properties.put("bmp_version", "BMP v. 3.x NT");
- break;
-
- default:
- throw new
- RuntimeException("Invalid compression specified in BMP file.");
- }
- } else if (size == 108) {
- // Windows 4.x BMP
-
- properties.put("bmp_version", "BMP v. 4.x");
-
- // rgb masks, valid only if comp is BI_BITFIELDS
- redMask = (int)readDWord(inputStream);
- greenMask = (int)readDWord(inputStream);
- blueMask = (int)readDWord(inputStream);
- // Only supported for 32bpp BI_RGB argb
- alphaMask = (int)readDWord(inputStream);
- long csType = readDWord(inputStream);
- int redX = readLong(inputStream);
- int redY = readLong(inputStream);
- int redZ = readLong(inputStream);
- int greenX = readLong(inputStream);
- int greenY = readLong(inputStream);
- int greenZ = readLong(inputStream);
- int blueX = readLong(inputStream);
- int blueY = readLong(inputStream);
- int blueZ = readLong(inputStream);
- long gammaRed = readDWord(inputStream);
- long gammaGreen = readDWord(inputStream);
- long gammaBlue = readDWord(inputStream);
-
- if (bitsPerPixel == 1) {
- imageType = VERSION_4_1_BIT;
- } else if (bitsPerPixel == 4) {
- imageType = VERSION_4_4_BIT;
- } else if (bitsPerPixel == 8) {
- imageType = VERSION_4_8_BIT;
- } else if (bitsPerPixel == 16) {
- imageType = VERSION_4_16_BIT;
- if ((int)compression == BI_RGB) {
- redMask = 0x7C00;
- greenMask = 0x3E0;
- blueMask = 0x1F;
- }
- } else if (bitsPerPixel == 24) {
- imageType = VERSION_4_24_BIT;
- } else if (bitsPerPixel == 32) {
- imageType = VERSION_4_32_BIT;
- if ((int)compression == BI_RGB) {
- redMask = 0x00FF0000;
- greenMask = 0x0000FF00;
- blueMask = 0x000000FF;
- }
- }
-
- properties.put("red_mask", new Integer(redMask));
- properties.put("green_mask", new Integer(greenMask));
- properties.put("blue_mask", new Integer(blueMask));
- properties.put("alpha_mask", new Integer(alphaMask));
-
- // Read in the palette
- int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
- int sizeOfPalette = numberOfEntries*4;
- if (bitmapOffset == size) {
- switch (imageType) {
- case VERSION_4_1_BIT:
- sizeOfPalette = (int)(colorsUsed == 0 ? 2 : colorsUsed) * 4;
- break;
- case VERSION_4_4_BIT:
- sizeOfPalette = (int)(colorsUsed == 0 ? 16 : colorsUsed) * 4;
- break;
- case VERSION_4_8_BIT:
- sizeOfPalette = (int)(colorsUsed == 0 ? 256 : colorsUsed) * 4;
- break;
- default:
- sizeOfPalette = 0;
- break;
- }
- bitmapOffset = size + sizeOfPalette;
- }
- palette = new byte[sizeOfPalette];
- inputStream.read(palette, 0, sizeOfPalette);
-
- if (palette != null || palette.length != 0) {
- properties.put("palette", palette);
- }
-
- switch((int)csType) {
- case LCS_CALIBRATED_RGB:
- // All the new fields are valid only for this case
- properties.put("color_space", "LCS_CALIBRATED_RGB");
- properties.put("redX", new Integer(redX));
- properties.put("redY", new Integer(redY));
- properties.put("redZ", new Integer(redZ));
- properties.put("greenX", new Integer(greenX));
- properties.put("greenY", new Integer(greenY));
- properties.put("greenZ", new Integer(greenZ));
- properties.put("blueX", new Integer(blueX));
- properties.put("blueY", new Integer(blueY));
- properties.put("blueZ", new Integer(blueZ));
- properties.put("gamma_red", new Long(gammaRed));
- properties.put("gamma_green", new Long(gammaGreen));
- properties.put("gamma_blue", new Long(gammaBlue));
-
- // break;
- throw new
- RuntimeException("Not implemented yet.");
-
- case LCS_sRGB:
- // Default Windows color space
- properties.put("color_space", "LCS_sRGB");
- break;
-
- case LCS_CMYK:
- properties.put("color_space", "LCS_CMYK");
- // break;
- throw new
- RuntimeException("Not implemented yet.");
- }
-
- } else {
- properties.put("bmp_version", "BMP v. 5.x");
- throw new
- RuntimeException("BMP version 5 not implemented yet.");
- }
- }
-
- if (height > 0) {
- // bottom up image
- isBottomUp = true;
- } else {
- // top down image
- isBottomUp = false;
- height = Math.abs(height);
- }
- // When number of bitsPerPixel is <= 8, we use IndexColorModel.
- if (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8) {
-
- numBands = 1;
-
-
- // Create IndexColorModel from the palette.
- byte r[], g[], b[];
- int sizep;
- if (imageType == VERSION_2_1_BIT ||
- imageType == VERSION_2_4_BIT ||
- imageType == VERSION_2_8_BIT) {
-
- sizep = palette.length/3;
-
- if (sizep > 256) {
- sizep = 256;
- }
-
- int off;
- r = new byte[sizep];
- g = new byte[sizep];
- b = new byte[sizep];
- for (int i=0; i<sizep; i++) {
- off = 3 * i;
- b[i] = palette[off];
- g[i] = palette[off+1];
- r[i] = palette[off+2];
- }
- } else {
- sizep = palette.length/4;
-
- if (sizep > 256) {
- sizep = 256;
- }
-
- int off;
- r = new byte[sizep];
- g = new byte[sizep];
- b = new byte[sizep];
- for (int i=0; i<sizep; i++) {
- off = 4 * i;
- b[i] = palette[off];
- g[i] = palette[off+1];
- r[i] = palette[off+2];
- }
- }
-
- } else if (bitsPerPixel == 16) {
- numBands = 3;
- } else if (bitsPerPixel == 32) {
- numBands = alphaMask == 0 ? 3 : 4;
-
- // The number of bands in the SampleModel is determined by
- // the length of the mask array passed in.
- } else {
- numBands = 3;
- }
- }
-
- private byte[] getPalette(int group) {
- if (palette == null)
- return null;
- byte np[] = new byte[palette.length / group * 3];
- int e = palette.length / group;
- for (int k = 0; k < e; ++k) {
- int src = k * group;
- int dest = k * 3;
- np[dest + 2] = palette[src++];
- np[dest + 1] = palette[src++];
- np[dest] = palette[src];
- }
- return np;
- }
-
- private Image getImage() throws IOException, BadElementException {
- byte bdata[] = null; // buffer for byte data
-
- // if (sampleModel.getDataType() == DataBuffer.TYPE_BYTE)
- // bdata = (byte[])((DataBufferByte)tile.getDataBuffer()).getData();
- // else if (sampleModel.getDataType() == DataBuffer.TYPE_USHORT)
- // sdata = (short[])((DataBufferUShort)tile.getDataBuffer()).getData();
- // else if (sampleModel.getDataType() == DataBuffer.TYPE_INT)
- // idata = (int[])((DataBufferInt)tile.getDataBuffer()).getData();
-
- // There should only be one tile.
- switch(imageType) {
-
- case VERSION_2_1_BIT:
- // no compression
- return read1Bit(3);
-
- case VERSION_2_4_BIT:
- // no compression
- return read4Bit(3);
-
- case VERSION_2_8_BIT:
- // no compression
- return read8Bit(3);
-
- case VERSION_2_24_BIT:
- // no compression
- bdata = new byte[width * height * 3];
- read24Bit(bdata);
- return new ImgRaw(width, height, 3, 8, bdata);
-
- case VERSION_3_1_BIT:
- // 1-bit images cannot be compressed.
- return read1Bit(4);
-
- case VERSION_3_4_BIT:
- switch((int)compression) {
- case BI_RGB:
- return read4Bit(4);
-
- case BI_RLE4:
- return readRLE4();
-
- default:
- throw new
- RuntimeException("Invalid compression specified for BMP file.");
- }
-
- case VERSION_3_8_BIT:
- switch((int)compression) {
- case BI_RGB:
- return read8Bit(4);
-
- case BI_RLE8:
- return readRLE8();
-
- default:
- throw new
- RuntimeException("Invalid compression specified for BMP file.");
- }
-
- case VERSION_3_24_BIT:
- // 24-bit images are not compressed
- bdata = new byte[width * height * 3];
- read24Bit(bdata);
- return new ImgRaw(width, height, 3, 8, bdata);
-
- case VERSION_3_NT_16_BIT:
- return read1632Bit(false);
-
- case VERSION_3_NT_32_BIT:
- return read1632Bit(true);
-
- case VERSION_4_1_BIT:
- return read1Bit(4);
-
- case VERSION_4_4_BIT:
- switch((int)compression) {
-
- case BI_RGB:
- return read4Bit(4);
-
- case BI_RLE4:
- return readRLE4();
-
- default:
- throw new
- RuntimeException("Invalid compression specified for BMP file.");
- }
-
- case VERSION_4_8_BIT:
- switch((int)compression) {
-
- case BI_RGB:
- return read8Bit(4);
-
- case BI_RLE8:
- return readRLE8();
-
- default:
- throw new
- RuntimeException("Invalid compression specified for BMP file.");
- }
-
- case VERSION_4_16_BIT:
- return read1632Bit(false);
-
- case VERSION_4_24_BIT:
- bdata = new byte[width * height * 3];
- read24Bit(bdata);
- return new ImgRaw(width, height, 3, 8, bdata);
-
- case VERSION_4_32_BIT:
- return read1632Bit(true);
- }
- return null;
- }
-
- private Image indexedModel(byte bdata[], int bpc, int paletteEntries) throws BadElementException {
- Image img = new ImgRaw(width, height, 1, bpc, bdata);
- PdfArray colorspace = new PdfArray();
- colorspace.add(PdfName.INDEXED);
- colorspace.add(PdfName.DEVICERGB);
- byte np[] = getPalette(paletteEntries);
- int len = np.length;
- colorspace.add(new PdfNumber(len / 3 - 1));
- colorspace.add(new PdfString(np));
- PdfDictionary ad = new PdfDictionary();
- ad.put(PdfName.COLORSPACE, colorspace);
- img.setAdditional(ad);
- return img;
- }
-
- // Deal with 1 Bit images using IndexColorModels
- private Image read1Bit(int paletteEntries) throws IOException, BadElementException {
- byte bdata[] = new byte[((width + 7) / 8) * height];
- int padding = 0;
- int bytesPerScanline = (int)Math.ceil((double)width/8.0);
-
- int remainder = bytesPerScanline % 4;
- if (remainder != 0) {
- padding = 4 - remainder;
- }
-
- int imSize = (bytesPerScanline + padding) * height;
-
- // Read till we have the whole image
- byte values[] = new byte[imSize];
- int bytesRead = 0;
- while (bytesRead < imSize) {
- bytesRead += inputStream.read(values, bytesRead,
- imSize - bytesRead);
- }
-
- if (isBottomUp) {
-
- // Convert the bottom up image to a top down format by copying
- // one scanline from the bottom to the top at a time.
-
- for (int i=0; i<height; i++) {
- System.arraycopy(values,
- imSize - (i+1)*(bytesPerScanline + padding),
- bdata,
- i*bytesPerScanline, bytesPerScanline);
- }
- } else {
-
- for (int i=0; i<height; i++) {
- System.arraycopy(values,
- i * (bytesPerScanline + padding),
- bdata,
- i * bytesPerScanline,
- bytesPerScanline);
- }
- }
- return indexedModel(bdata, 1, paletteEntries);
- }
-
- // Method to read a 4 bit BMP image data
- private Image read4Bit(int paletteEntries) throws IOException, BadElementException {
- byte bdata[] = new byte[((width + 1) / 2) * height];
-
- // Padding bytes at the end of each scanline
- int padding = 0;
-
- int bytesPerScanline = (int)Math.ceil((double)width/2.0);
- int remainder = bytesPerScanline % 4;
- if (remainder != 0) {
- padding = 4 - remainder;
- }
-
- int imSize = (bytesPerScanline + padding) * height;
-
- // Read till we have the whole image
- byte values[] = new byte[imSize];
- int bytesRead = 0;
- while (bytesRead < imSize) {
- bytesRead += inputStream.read(values, bytesRead,
- imSize - bytesRead);
- }
-
- if (isBottomUp) {
-
- // Convert the bottom up image to a top down format by copying
- // one scanline from the bottom to the top at a time.
- for (int i=0; i<height; i++) {
- System.arraycopy(values,
- imSize - (i+1)*(bytesPerScanline + padding),
- bdata,
- i*bytesPerScanline,
- bytesPerScanline);
- }
- } else {
- for (int i=0; i<height; i++) {
- System.arraycopy(values,
- i * (bytesPerScanline + padding),
- bdata,
- i * bytesPerScanline,
- bytesPerScanline);
- }
- }
- return indexedModel(bdata, 4, paletteEntries);
- }
-
- // Method to read 8 bit BMP image data
- private Image read8Bit(int paletteEntries) throws IOException, BadElementException {
- byte bdata[] = new byte[width * height];
- // Padding bytes at the end of each scanline
- int padding = 0;
-
- // width * bitsPerPixel should be divisible by 32
- int bitsPerScanline = width * 8;
- if ( bitsPerScanline%32 != 0) {
- padding = (bitsPerScanline/32 + 1)*32 - bitsPerScanline;
- padding = (int)Math.ceil(padding/8.0);
- }
-
- int imSize = (width + padding) * height;
-
- // Read till we have the whole image
- byte values[] = new byte[imSize];
- int bytesRead = 0;
- while (bytesRead < imSize) {
- bytesRead += inputStream.read(values, bytesRead, imSize - bytesRead);
- }
-
- if (isBottomUp) {
-
- // Convert the bottom up image to a top down format by copying
- // one scanline from the bottom to the top at a time.
- for (int i=0; i<height; i++) {
- System.arraycopy(values,
- imSize - (i+1) * (width + padding),
- bdata,
- i * width,
- width);
- }
- } else {
- for (int i=0; i<height; i++) {
- System.arraycopy(values,
- i * (width + padding),
- bdata,
- i * width,
- width);
- }
- }
- return indexedModel(bdata, 8, paletteEntries);
- }
-
- // Method to read 24 bit BMP image data
- private void read24Bit(byte[] bdata) {
- // Padding bytes at the end of each scanline
- int padding = 0;
-
- // width * bitsPerPixel should be divisible by 32
- int bitsPerScanline = width * 24;
- if ( bitsPerScanline%32 != 0) {
- padding = (bitsPerScanline/32 + 1)*32 - bitsPerScanline;
- padding = (int)Math.ceil(padding/8.0);
- }
-
-
- int imSize = ((width * 3 + 3) / 4 * 4) * height;
- // Read till we have the whole image
- byte values[] = new byte[imSize];
- try {
- int bytesRead = 0;
- while (bytesRead < imSize) {
- int r = inputStream.read(values, bytesRead,
- imSize - bytesRead);
- if (r < 0)
- break;
- bytesRead += r;
- }
- } catch (IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
-
- int l=0, count;
-
- if (isBottomUp) {
- int max = width*height*3-1;
-
- count = -padding;
- for (int i=0; i<height; i++) {
- l = max - (i+1)*width*3 + 1;
- count += padding;
- for (int j=0; j<width; j++) {
- bdata[l + 2] = values[count++];
- bdata[l + 1] = values[count++];
- bdata[l] = values[count++];
- l += 3;
- }
- }
- } else {
- count = -padding;
- for (int i=0; i<height; i++) {
- count += padding;
- for (int j=0; j<width; j++) {
- bdata[l + 2] = values[count++];
- bdata[l + 1] = values[count++];
- bdata[l] = values[count++];
- l += 3;
- }
- }
- }
- }
-
- private int findMask(int mask) {
- int k = 0;
- for (; k < 32; ++k) {
- if ((mask & 1) == 1)
- break;
- mask >>>= 1;
- }
- return mask;
- }
-
- private int findShift(int mask) {
- int k = 0;
- for (; k < 32; ++k) {
- if ((mask & 1) == 1)
- break;
- mask >>>= 1;
- }
- return k;
- }
-
- private Image read1632Bit(boolean is32) throws IOException, BadElementException {
-
- int red_mask = findMask(redMask);
- int red_shift = findShift(redMask);
- int red_factor = red_mask + 1;
- int green_mask = findMask(greenMask);
- int green_shift = findShift(greenMask);
- int green_factor = green_mask + 1;
- int blue_mask = findMask(blueMask);
- int blue_shift = findShift(blueMask);
- int blue_factor = blue_mask + 1;
- byte bdata[] = new byte[width * height * 3];
- // Padding bytes at the end of each scanline
- int padding = 0;
-
- if (!is32) {
- // width * bitsPerPixel should be divisible by 32
- int bitsPerScanline = width * 16;
- if ( bitsPerScanline%32 != 0) {
- padding = (bitsPerScanline/32 + 1)*32 - bitsPerScanline;
- padding = (int)Math.ceil(padding/8.0);
- }
- }
-
- int imSize = (int)imageSize;
- if (imSize == 0) {
- imSize = (int)(bitmapFileSize - bitmapOffset);
- }
-
- int l=0;
- int v;
- if (isBottomUp) {
- for (int i=height - 1; i >= 0; --i) {
- l = width * 3 * i;
- for (int j=0; j<width; j++) {
- if (is32)
- v = (int)readDWord(inputStream);
- else
- v = readWord(inputStream);
- bdata[l++] = (byte)(((v >>> red_shift) & red_mask) * 256 / red_factor);
- bdata[l++] = (byte)(((v >>> green_shift) & green_mask) * 256 / green_factor);
- bdata[l++] = (byte)(((v >>> blue_shift) & blue_mask) * 256 / blue_factor);
- }
- for (int m=0; m<padding; m++) {
- inputStream.read();
- }
- }
- } else {
- for (int i=0; i<height; i++) {
- for (int j=0; j<width; j++) {
- if (is32)
- v = (int)readDWord(inputStream);
- else
- v = readWord(inputStream);
- bdata[l++] = (byte)(((v >>> red_shift) & red_mask) * 256 / red_factor);
- bdata[l++] = (byte)(((v >>> green_shift) & green_mask) * 256 / green_factor);
- bdata[l++] = (byte)(((v >>> blue_shift) & blue_mask) * 256 / blue_factor);
- }
- for (int m=0; m<padding; m++) {
- inputStream.read();
- }
- }
- }
- return new ImgRaw(width, height, 3, 8, bdata);
- }
-
- private Image readRLE8() throws IOException, BadElementException {
-
- // If imageSize field is not provided, calculate it.
- int imSize = (int)imageSize;
- if (imSize == 0) {
- imSize = (int)(bitmapFileSize - bitmapOffset);
- }
-
- // Read till we have the whole image
- byte values[] = new byte[imSize];
- int bytesRead = 0;
- while (bytesRead < imSize) {
- bytesRead += inputStream.read(values, bytesRead,
- imSize - bytesRead);
- }
-
- // Since data is compressed, decompress it
- byte val[] = decodeRLE(true, values);
-
- // Uncompressed data does not have any padding
- imSize = width * height;
-
- if (isBottomUp) {
-
- // Convert the bottom up image to a top down format by copying
- // one scanline from the bottom to the top at a time.
- // int bytesPerScanline = (int)Math.ceil((double)width/8.0);
- byte temp[] = new byte[val.length];
- int bytesPerScanline = width;
- for (int i=0; i<height; i++) {
- System.arraycopy(val,
- imSize - (i+1)*(bytesPerScanline),
- temp,
- i*bytesPerScanline, bytesPerScanline);
- }
- val = temp;
- }
- return indexedModel(val, 8, 4);
- }
-
- private Image readRLE4() throws IOException, BadElementException {
-
- // If imageSize field is not specified, calculate it.
- int imSize = (int)imageSize;
- if (imSize == 0) {
- imSize = (int)(bitmapFileSize - bitmapOffset);
- }
-
- // Read till we have the whole image
- byte values[] = new byte[imSize];
- int bytesRead = 0;
- while (bytesRead < imSize) {
- bytesRead += inputStream.read(values, bytesRead,
- imSize - bytesRead);
- }
-
- // Decompress the RLE4 compressed data.
- byte val[] = decodeRLE(false, values);
-
- // Invert it as it is bottom up format.
- if (isBottomUp) {
-
- byte inverted[] = val;
- val = new byte[width * height];
- int l = 0, index, lineEnd;
-
- for (int i = height-1; i >= 0; i--) {
- index = i * width;
- lineEnd = l + width;
- while(l != lineEnd) {
- val[l++] = inverted[index++];
- }
- }
- }
- int stride = ((width + 1) / 2);
- byte bdata[] = new byte[stride * height];
- int ptr = 0;
- int sh = 0;
- for (int h = 0; h < height; ++h) {
- for (int w = 0; w < width; ++w) {
- if ((w & 1) == 0)
- bdata[sh + w / 2] = (byte)(val[ptr++] << 4);
- else
- bdata[sh + w / 2] |= (byte)(val[ptr++] & 0x0f);
- }
- sh += stride;
- }
- return indexedModel(bdata, 4, 4);
- }
-
- private byte[] decodeRLE(boolean is8, byte values[]) {
- byte val[] = new byte[width * height];
- try {
- int ptr = 0;
- int x = 0;
- int q = 0;
- for (int y = 0; y < height && ptr < values.length;) {
- int count = values[ptr++] & 0xff;
- if (count != 0) {
- // encoded mode
- int bt = values[ptr++] & 0xff;
- if (is8) {
- for (int i = count; i != 0; --i) {
- val[q++] = (byte)bt;
- }
- }
- else {
- for (int i = 0; i < count; ++i) {
- val[q++] = (byte)((i & 1) == 1 ? (bt & 0x0f) : ((bt >>> 4) & 0x0f));
- }
- }
- x += count;
- }
- else {
- // escape mode
- count = values[ptr++] & 0xff;
- if (count == 1)
- break;
- switch (count) {
- case 0:
- x = 0;
- ++y;
- q = y * width;
- break;
- case 2:
- // delta mode
- x += values[ptr++] & 0xff;
- y += values[ptr++] & 0xff;
- q = y * width + x;
- break;
- default:
- // absolute mode
- if (is8) {
- for (int i = count; i != 0; --i)
- val[q++] = (byte)(values[ptr++] & 0xff);
- }
- else {
- int bt = 0;
- for (int i = 0; i < count; ++i) {
- if ((i & 1) == 0)
- bt = values[ptr++] & 0xff;
- val[q++] = (byte)((i & 1) == 1 ? (bt & 0x0f) : ((bt >>> 4) & 0x0f));
- }
- }
- x += count;
- // read pad byte
- if (is8) {
- if ((count & 1) == 1)
- ++ptr;
- }
- else {
- if ((count & 3) == 1 || (count & 3) == 2)
- ++ptr;
- }
- break;
- }
- }
- }
- }
- catch (Exception e) {
- //empty on purpose
- }
-
- return val;
- }
-
- // Windows defined data type reading methods - everything is little endian
-
- // Unsigned 8 bits
- private int readUnsignedByte(InputStream stream) throws IOException {
- return (stream.read() & 0xff);
- }
-
- // Unsigned 2 bytes
- private int readUnsignedShort(InputStream stream) throws IOException {
- int b1 = readUnsignedByte(stream);
- int b2 = readUnsignedByte(stream);
- return ((b2 << 8) | b1) & 0xffff;
- }
-
- // Signed 16 bits
- private int readShort(InputStream stream) throws IOException {
- int b1 = readUnsignedByte(stream);
- int b2 = readUnsignedByte(stream);
- return (b2 << 8) | b1;
- }
-
- // Unsigned 16 bits
- private int readWord(InputStream stream) throws IOException {
- return readUnsignedShort(stream);
- }
-
- // Unsigned 4 bytes
- private long readUnsignedInt(InputStream stream) throws IOException {
- int b1 = readUnsignedByte(stream);
- int b2 = readUnsignedByte(stream);
- int b3 = readUnsignedByte(stream);
- int b4 = readUnsignedByte(stream);
- long l = (long)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
- return l & 0xffffffff;
- }
-
- // Signed 4 bytes
- private int readInt(InputStream stream) throws IOException {
- int b1 = readUnsignedByte(stream);
- int b2 = readUnsignedByte(stream);
- int b3 = readUnsignedByte(stream);
- int b4 = readUnsignedByte(stream);
- return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
- }
-
- // Unsigned 4 bytes
- private long readDWord(InputStream stream) throws IOException {
- return readUnsignedInt(stream);
- }
-
- // 32 bit signed value
- private int readLong(InputStream stream) throws IOException {
- return readInt(stream);
- }
-}