You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2010/09/10 18:33:42 UTC
svn commit: r995859 [16/30] - in
/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan: ./ color/
common/ common/byteSources/ common/mylzw/ formats/bmp/
formats/bmp/pixelparsers/ formats/bmp/writers/ formats/gif/ formats/ico/
formats/jpeg/ f...
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngWriter.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngWriter.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngWriter.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngWriter.java Fri Sep 10 16:33:35 2010
@@ -36,592 +36,592 @@ import org.apache.sanselan.util.UnicodeU
public class PngWriter implements PngConstants
{
- private final boolean verbose;
+ private final boolean verbose;
- public PngWriter(boolean verbose)
- {
- this.verbose = verbose;
- }
-
- public PngWriter(Map params)
- {
- this.verbose = ParamMap.getParamBoolean(params, PARAM_KEY_VERBOSE,
- false);
- }
-
- /*
- * 1. IHDR: image header, which is the first chunk in a PNG datastream. 2.
- * PLTE: palette table associated with indexed PNG images. 3. IDAT: image
- * data chunks. 4. IEND: image trailer, which is the last chunk in a PNG
- * datastream.
- *
- * The remaining 14 chunk types are termed ancillary chunk types, which
- * encoders may generate and decoders may interpret.
- *
- * 1. Transparency information: tRNS (see 11.3.2: Transparency information).
- * 2. Colour space information: cHRM, gAMA, iCCP, sBIT, sRGB (see 11.3.3:
- * Colour space information). 3. Textual information: iTXt, tEXt, zTXt (see
- * 11.3.4: Textual information). 4. Miscellaneous information: bKGD, hIST,
- * pHYs, sPLT (see 11.3.5: Miscellaneous information). 5. Time information:
- * tIME (see 11.3.6: Time stamp information).
- */
-
- private final void writeInt(OutputStream os, int value) throws IOException
- {
- os.write(0xff & (value >> 24));
- os.write(0xff & (value >> 16));
- os.write(0xff & (value >> 8));
- os.write(0xff & (value >> 0));
- }
-
- private final void writeChunk(OutputStream os, byte chunkType[],
- byte data[]) throws IOException
- {
- int dataLength = data == null ? 0 : data.length;
- writeInt(os, dataLength);
- os.write(chunkType);
- if (data != null)
- os.write(data);
-
- // Debug.debug("writeChunk chunkType", chunkType);
- // Debug.debug("writeChunk data", data);
-
- {
- PngCrc png_crc = new PngCrc();
-
- long crc1 = png_crc.start_partial_crc(chunkType, chunkType.length);
- long crc2 = data == null ? crc1 : png_crc.continue_partial_crc(
- crc1, data, data.length);
- int crc = (int) png_crc.finish_partial_crc(crc2);
-
- // Debug.debug("crc1", crc1 + " (" + Long.toHexString(crc1)
- // + ")");
- // Debug.debug("crc2", crc2 + " (" + Long.toHexString(crc2)
- // + ")");
- // Debug.debug("crc3", crc + " (" + Integer.toHexString(crc)
- // + ")");
-
- writeInt(os, crc);
- }
- }
-
- private static class ImageHeader
- {
- public final int width;
- public final int height;
- public final byte bit_depth;
- public final byte colorType;
- public final byte compressionMethod;
- public final byte filterMethod;
- public final byte interlaceMethod;
-
- public ImageHeader(int width, int height, byte bit_depth,
- byte colorType, byte compressionMethod, byte filterMethod,
- byte interlaceMethod)
- {
- this.width = width;
- this.height = height;
- this.bit_depth = bit_depth;
- this.colorType = colorType;
- this.compressionMethod = compressionMethod;
- this.filterMethod = filterMethod;
- this.interlaceMethod = interlaceMethod;
- }
-
- }
-
- private void writeChunkIHDR(OutputStream os, ImageHeader value)
- throws IOException
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- writeInt(baos, value.width);
- writeInt(baos, value.height);
- baos.write(0xff & value.bit_depth);
- baos.write(0xff & value.colorType);
- baos.write(0xff & value.compressionMethod);
- baos.write(0xff & value.filterMethod);
- baos.write(0xff & value.interlaceMethod);
-
- // Debug.debug("baos", baos.toByteArray());
-
- writeChunk(os, IHDR_CHUNK_TYPE, baos.toByteArray());
- }
-
- private void writeChunkiTXt(OutputStream os, PngText.iTXt text)
- throws IOException, ImageWriteException
- {
- if (!UnicodeUtils.isValidISO_8859_1(text.keyword))
- throw new ImageWriteException(
- "Png tEXt chunk keyword is not ISO-8859-1: " + text.keyword);
- if (!UnicodeUtils.isValidISO_8859_1(text.languageTag))
- throw new ImageWriteException(
- "Png tEXt chunk language tag is not ISO-8859-1: "
- + text.languageTag);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- // keyword
- baos.write(text.keyword.getBytes("ISO-8859-1"));
- baos.write(0);
-
- baos.write(1); // compressed flag, true
- baos.write(COMPRESSION_DEFLATE_INFLATE); // compression method
-
- // language tag
- baos.write(text.languageTag.getBytes("ISO-8859-1"));
- baos.write(0);
-
- // translated keyword
- baos.write(text.translatedKeyword.getBytes("utf-8"));
- baos.write(0);
-
- baos.write(new ZLibUtils().deflate(text.text.getBytes("utf-8")));
-
- writeChunk(os, iTXt_CHUNK_TYPE, baos.toByteArray());
- }
-
- private void writeChunkzTXt(OutputStream os, PngText.zTXt text)
- throws IOException, ImageWriteException
- {
- if (!UnicodeUtils.isValidISO_8859_1(text.keyword))
- throw new ImageWriteException(
- "Png zTXt chunk keyword is not ISO-8859-1: " + text.keyword);
- if (!UnicodeUtils.isValidISO_8859_1(text.text))
- throw new ImageWriteException(
- "Png zTXt chunk text is not ISO-8859-1: " + text.text);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- // keyword
- baos.write(text.keyword.getBytes("ISO-8859-1"));
- baos.write(0);
-
- // compression method
- baos.write(PngConstants.COMPRESSION_DEFLATE_INFLATE);
-
- // text
- baos
- .write(new ZLibUtils().deflate(text.text
- .getBytes("ISO-8859-1")));
-
- writeChunk(os, zTXt_CHUNK_TYPE, baos.toByteArray());
- }
-
- private void writeChunktEXt(OutputStream os, PngText.tEXt text)
- throws IOException, ImageWriteException
- {
- if (!UnicodeUtils.isValidISO_8859_1(text.keyword))
- throw new ImageWriteException(
- "Png tEXt chunk keyword is not ISO-8859-1: " + text.keyword);
- if (!UnicodeUtils.isValidISO_8859_1(text.text))
- throw new ImageWriteException(
- "Png tEXt chunk text is not ISO-8859-1: " + text.text);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- // keyword
- baos.write(text.keyword.getBytes("ISO-8859-1"));
- baos.write(0);
-
- // text
- baos.write(text.text.getBytes("ISO-8859-1"));
-
- writeChunk(os, tEXt_CHUNK_TYPE, baos.toByteArray());
- }
-
- private void writeChunkXmpiTXt(OutputStream os, String xmpXml)
- throws IOException
- {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- // keyword
- baos.write(XMP_KEYWORD.getBytes("ISO-8859-1"));
- baos.write(0);
-
- baos.write(1); // compressed flag, true
- baos.write(COMPRESSION_DEFLATE_INFLATE); // compression method
-
- baos.write(0); // language tag (ignore). TODO
-
- // translated keyword
- baos.write(XMP_KEYWORD.getBytes("utf-8"));
- baos.write(0);
-
- baos.write(new ZLibUtils().deflate(xmpXml.getBytes("utf-8")));
-
- writeChunk(os, iTXt_CHUNK_TYPE, baos.toByteArray());
- }
-
- private void writeChunkPLTE(OutputStream os, Palette palette)
- throws IOException
- {
- int length = palette.length();
- byte bytes[] = new byte[length * 3];
-
- // Debug.debug("length", length);
- for (int i = 0; i < length; i++)
- {
- int rgb = palette.getEntry(i);
- int index = i * 3;
- // Debug.debug("index", index);
- bytes[index + 0] = (byte) (0xff & (rgb >> 16));
- bytes[index + 1] = (byte) (0xff & (rgb >> 8));
- bytes[index + 2] = (byte) (0xff & (rgb >> 0));
- }
-
- writeChunk(os, PLTE_CHUNK_TYPE, bytes);
- }
-
- private void writeChunkIEND(OutputStream os) throws IOException
- {
- writeChunk(os, IEND_CHUNK_TYPE, null);
- }
-
- private void writeChunkIDAT(OutputStream os, byte bytes[])
- throws IOException
- {
- writeChunk(os, IDAT_CHUNK_TYPE, bytes);
- }
-
- private byte getColourType(boolean hasAlpha, boolean isGrayscale)
- {
- byte result;
-
- boolean index = false; // charles
-
- if (index)
- result = COLOR_TYPE_INDEXED_COLOR;
- else if (isGrayscale)
- {
- if (hasAlpha)
- result = COLOR_TYPE_GREYSCALE_WITH_ALPHA;
- else
- result = COLOR_TYPE_GREYSCALE;
- } else if (hasAlpha)
- result = COLOR_TYPE_TRUE_COLOR_WITH_ALPHA;
- else
- result = COLOR_TYPE_TRUE_COLOR;
-
- return result;
- }
-
- private byte getBitDepth(final byte colorType, Map params)
- {
- byte result = 8;
-
- Object o = params.get(PARAM_KEY_PNG_BIT_DEPTH);
- if (o != null && o instanceof Number)
- {
- int value = ((Number) o).intValue();
- switch (value)
- {
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- result = (byte) value;
- break;
- default:
- }
- switch (colorType)
- {
- case COLOR_TYPE_GREYSCALE:
- break;
- case COLOR_TYPE_INDEXED_COLOR:
- result = (byte) Math.min(8, result);
- break;
- case COLOR_TYPE_GREYSCALE_WITH_ALPHA:
- case COLOR_TYPE_TRUE_COLOR:
- case COLOR_TYPE_TRUE_COLOR_WITH_ALPHA:
- result = (byte) Math.max(8, result);
- break;
- default:
- }
- }
-
- return result;
- }
-
- /*
- * between two chunk types indicates alternatives. Table 5.3 Chunk
- * ordering rules Critical chunks (shall appear in this order, except PLTE
- * is optional) Chunk name Multiple allowed Ordering constraints IHDR No
- * Shall be first PLTE No Before first IDAT IDAT Yes Multiple IDAT chunks
- * shall be consecutive IEND No Shall be last Ancillary chunks (need not
- * appear in this order) Chunk name Multiple allowed Ordering constraints
- * cHRM No Before PLTE and IDAT gAMA No Before PLTE and IDAT iCCP No Before
- * PLTE and IDAT. If the iCCP chunk is present, the sRGB chunk should not be
- * present. sBIT No Before PLTE and IDAT sRGB No Before PLTE and IDAT. If
- * the sRGB chunk is present, the iCCP chunk should not be present. bKGD No
- * After PLTE; before IDAT hIST No After PLTE; before IDAT tRNS No After
- * PLTE; before IDAT pHYs No Before IDAT sPLT Yes Before IDAT tIME No None
- * iTXt Yes None tEXt Yes None zTXt Yes None
- */
-
- public void writeImage(BufferedImage src, OutputStream os, Map params)
- throws ImageWriteException, IOException
- {
- // make copy of params; we'll clear keys as we consume them.
- params = new HashMap(params);
-
- // clear format key.
- if (params.containsKey(PARAM_KEY_FORMAT))
- params.remove(PARAM_KEY_FORMAT);
- // clear verbose key.
- if (params.containsKey(PARAM_KEY_VERBOSE))
- params.remove(PARAM_KEY_VERBOSE);
-
- Map rawParams = new HashMap(params);
- if (params.containsKey(PARAM_KEY_PNG_FORCE_TRUE_COLOR))
- params.remove(PARAM_KEY_PNG_FORCE_TRUE_COLOR);
- if (params.containsKey(PARAM_KEY_PNG_FORCE_INDEXED_COLOR))
- params.remove(PARAM_KEY_PNG_FORCE_INDEXED_COLOR);
- if (params.containsKey(PARAM_KEY_PNG_BIT_DEPTH))
- params.remove(PARAM_KEY_PNG_BIT_DEPTH);
- if (params.containsKey(PARAM_KEY_XMP_XML))
- params.remove(PARAM_KEY_XMP_XML);
- if (params.containsKey(PARAM_KEY_PNG_TEXT_CHUNKS))
- params.remove(PARAM_KEY_PNG_TEXT_CHUNKS);
- if (params.size() > 0)
- {
- Object firstKey = params.keySet().iterator().next();
- throw new ImageWriteException("Unknown parameter: " + firstKey);
- }
- params = rawParams;
-
- int width = src.getWidth();
- int height = src.getHeight();
-
- boolean hasAlpha = new PaletteFactory().hasTransparency(src);
- if (verbose)
- Debug.debug("hasAlpha", hasAlpha);
- // int transparency = new PaletteFactory().getTransparency(src);
-
- boolean isGrayscale = new PaletteFactory().isGrayscale(src);
- if (verbose)
- Debug.debug("isGrayscale", isGrayscale);
-
- byte colorType;
- {
- boolean forceIndexedColor = ParamMap.getParamBoolean(params,
- PARAM_KEY_PNG_FORCE_INDEXED_COLOR, false);
- boolean forceTrueColor = ParamMap.getParamBoolean(params,
- PARAM_KEY_PNG_FORCE_TRUE_COLOR, false);
-
- if (forceIndexedColor && forceTrueColor)
- throw new ImageWriteException(
- "Params: Cannot force both indexed and true color modes");
- else if (forceIndexedColor)
- {
- colorType = COLOR_TYPE_INDEXED_COLOR;
- } else if (forceTrueColor)
- {
- colorType = (byte) (hasAlpha ? COLOR_TYPE_TRUE_COLOR_WITH_ALPHA
- : COLOR_TYPE_TRUE_COLOR);
- isGrayscale = false;
- } else
- colorType = getColourType(hasAlpha, isGrayscale);
- if (verbose)
- Debug.debug("colorType", colorType);
- }
-
- byte bitDepth = getBitDepth(colorType, params);
- if (verbose)
- Debug.debug("bit_depth", bitDepth);
-
- int sampleDepth;
- if (colorType == COLOR_TYPE_INDEXED_COLOR)
- sampleDepth = 8;
- else
- sampleDepth = bitDepth;
- if (verbose)
- Debug.debug("sample_depth", sampleDepth);
-
- {
- os.write(PNG_Signature);
- }
- {
- // IHDR must be first
-
- byte compressionMethod = COMPRESSION_TYPE_INFLATE_DEFLATE;
- byte filterMethod = FILTER_METHOD_ADAPTIVE;
- byte interlaceMethod = INTERLACE_METHOD_NONE;
-
- ImageHeader imageHeader = new ImageHeader(width, height, bitDepth,
- colorType, compressionMethod, filterMethod, interlaceMethod);
-
- writeChunkIHDR(os, imageHeader);
- }
-
- {
- // sRGB No Before PLTE and IDAT. If the sRGB chunk is present, the
- // iCCP chunk should not be present.
-
- // charles
- }
-
- Palette palette = null;
- if (colorType == COLOR_TYPE_INDEXED_COLOR)
- {
- // PLTE No Before first IDAT
-
- int max_colors = hasAlpha ? 255 : 256;
-
- palette = new MedianCutQuantizer(true).process(src, max_colors,
- verbose);
- // Palette palette2 = new PaletteFactory().makePaletteSimple(src,
- // max_colors);
-
- // palette.dump();
-
- writeChunkPLTE(os, palette);
- }
-
- if (params.containsKey(PARAM_KEY_XMP_XML))
- {
- String xmpXml = (String) params.get(PARAM_KEY_XMP_XML);
- writeChunkXmpiTXt(os, xmpXml);
- }
-
- if (params.containsKey(PARAM_KEY_PNG_TEXT_CHUNKS))
- {
- List outputTexts = (List) params.get(PARAM_KEY_PNG_TEXT_CHUNKS);
- for (int i = 0; i < outputTexts.size(); i++)
- {
- PngText text = (PngText) outputTexts.get(i);
- if (text instanceof PngText.tEXt)
- writeChunktEXt(os, (PngText.tEXt) text);
- else if (text instanceof PngText.zTXt)
- writeChunkzTXt(os, (PngText.zTXt) text);
- else if (text instanceof PngText.iTXt)
- writeChunkiTXt(os, (PngText.iTXt) text);
- else
- throw new ImageWriteException(
- "Unknown text to embed in PNG: " + text);
- }
- }
-
- {
- // Debug.debug("writing IDAT");
-
- // IDAT Yes Multiple IDAT chunks shall be consecutive
-
- byte uncompressed[];
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- boolean useAlpha = colorType == COLOR_TYPE_GREYSCALE_WITH_ALPHA
- || colorType == COLOR_TYPE_TRUE_COLOR_WITH_ALPHA;
-
- int row[] = new int[width];
- for (int y = 0; y < height; y++)
- {
- // Debug.debug("y", y + "/" + height);
- src.getRGB(0, y, width, 1, row, 0, width);
-
- byte filter_type = FILTER_TYPE_NONE;
- baos.write(filter_type);
- for (int x = 0; x < width; x++)
- {
- int argb = row[x];
-
- if (palette != null)
- {
- int index = palette.getPaletteIndex(argb);
- baos.write(0xff & index);
- } else
- {
- int alpha = 0xff & (argb >> 24);
- int red = 0xff & (argb >> 16);
- int green = 0xff & (argb >> 8);
- int blue = 0xff & (argb >> 0);
-
- if (isGrayscale)
- {
- int gray = (red + green + blue) / 3;
- // if(y==0)
- // {
- // Debug.debug("gray: " + x + ", " + y +
- // " argb: 0x"
- // + Integer.toHexString(argb) + " gray: 0x"
- // + Integer.toHexString(gray));
- // // Debug.debug(x + ", " + y + " gray", gray);
- // // Debug.debug(x + ", " + y + " gray", gray);
- // Debug.debug(x + ", " + y + " gray", gray +
- // " " + Integer.toHexString(gray));
- // Debug.debug();
- // }
- baos.write(gray);
- } else
- {
- baos.write(red);
- baos.write(green);
- baos.write(blue);
- }
- if (useAlpha)
- baos.write(alpha);
- }
- }
- }
- uncompressed = baos.toByteArray();
- }
-
- // Debug.debug("uncompressed", uncompressed.length);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- DeflaterOutputStream dos = new DeflaterOutputStream(baos);
- int chunk_size = 256 * 1024;
- for (int index = 0; index < uncompressed.length; index += chunk_size)
- {
- int end = Math.min(uncompressed.length, index + chunk_size);
- int length = end - index;
-
- dos.write(uncompressed, index, length);
- dos.flush();
- baos.flush();
-
- byte compressed[] = baos.toByteArray();
- baos.reset();
- if (compressed.length > 0)
- {
- // Debug.debug("compressed", compressed.length);
- writeChunkIDAT(os, compressed);
- }
-
- }
- {
- dos.finish();
- byte compressed[] = baos.toByteArray();
- if (compressed.length > 0)
- {
- // Debug.debug("compressed final", compressed.length);
- writeChunkIDAT(os, compressed);
- }
- }
- }
-
- {
- // IEND No Shall be last
-
- writeChunkIEND(os);
- }
-
- /*
- * Ancillary chunks (need not appear in this order) Chunk name Multiple
- * allowed Ordering constraints cHRM No Before PLTE and IDAT gAMA No
- * Before PLTE and IDAT iCCP No Before PLTE and IDAT. If the iCCP chunk
- * is present, the sRGB chunk should not be present. sBIT No Before PLTE
- * and IDAT sRGB No Before PLTE and IDAT. If the sRGB chunk is present,
- * the iCCP chunk should not be present. bKGD No After PLTE; before IDAT
- * hIST No After PLTE; before IDAT tRNS No After PLTE; before IDAT pHYs
- * No Before IDAT sPLT Yes Before IDAT tIME No None iTXt Yes None tEXt
- * Yes None zTXt Yes None
- */
-
- os.close();
- } // todo: filter types
- // proper colour types
- // srgb, etc.
+ public PngWriter(boolean verbose)
+ {
+ this.verbose = verbose;
+ }
+
+ public PngWriter(Map params)
+ {
+ this.verbose = ParamMap.getParamBoolean(params, PARAM_KEY_VERBOSE,
+ false);
+ }
+
+ /*
+ * 1. IHDR: image header, which is the first chunk in a PNG datastream. 2.
+ * PLTE: palette table associated with indexed PNG images. 3. IDAT: image
+ * data chunks. 4. IEND: image trailer, which is the last chunk in a PNG
+ * datastream.
+ *
+ * The remaining 14 chunk types are termed ancillary chunk types, which
+ * encoders may generate and decoders may interpret.
+ *
+ * 1. Transparency information: tRNS (see 11.3.2: Transparency information).
+ * 2. Colour space information: cHRM, gAMA, iCCP, sBIT, sRGB (see 11.3.3:
+ * Colour space information). 3. Textual information: iTXt, tEXt, zTXt (see
+ * 11.3.4: Textual information). 4. Miscellaneous information: bKGD, hIST,
+ * pHYs, sPLT (see 11.3.5: Miscellaneous information). 5. Time information:
+ * tIME (see 11.3.6: Time stamp information).
+ */
+
+ private final void writeInt(OutputStream os, int value) throws IOException
+ {
+ os.write(0xff & (value >> 24));
+ os.write(0xff & (value >> 16));
+ os.write(0xff & (value >> 8));
+ os.write(0xff & (value >> 0));
+ }
+
+ private final void writeChunk(OutputStream os, byte chunkType[],
+ byte data[]) throws IOException
+ {
+ int dataLength = data == null ? 0 : data.length;
+ writeInt(os, dataLength);
+ os.write(chunkType);
+ if (data != null)
+ os.write(data);
+
+ // Debug.debug("writeChunk chunkType", chunkType);
+ // Debug.debug("writeChunk data", data);
+
+ {
+ PngCrc png_crc = new PngCrc();
+
+ long crc1 = png_crc.start_partial_crc(chunkType, chunkType.length);
+ long crc2 = data == null ? crc1 : png_crc.continue_partial_crc(
+ crc1, data, data.length);
+ int crc = (int) png_crc.finish_partial_crc(crc2);
+
+ // Debug.debug("crc1", crc1 + " (" + Long.toHexString(crc1)
+ // + ")");
+ // Debug.debug("crc2", crc2 + " (" + Long.toHexString(crc2)
+ // + ")");
+ // Debug.debug("crc3", crc + " (" + Integer.toHexString(crc)
+ // + ")");
+
+ writeInt(os, crc);
+ }
+ }
+
+ private static class ImageHeader
+ {
+ public final int width;
+ public final int height;
+ public final byte bit_depth;
+ public final byte colorType;
+ public final byte compressionMethod;
+ public final byte filterMethod;
+ public final byte interlaceMethod;
+
+ public ImageHeader(int width, int height, byte bit_depth,
+ byte colorType, byte compressionMethod, byte filterMethod,
+ byte interlaceMethod)
+ {
+ this.width = width;
+ this.height = height;
+ this.bit_depth = bit_depth;
+ this.colorType = colorType;
+ this.compressionMethod = compressionMethod;
+ this.filterMethod = filterMethod;
+ this.interlaceMethod = interlaceMethod;
+ }
+
+ }
+
+ private void writeChunkIHDR(OutputStream os, ImageHeader value)
+ throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writeInt(baos, value.width);
+ writeInt(baos, value.height);
+ baos.write(0xff & value.bit_depth);
+ baos.write(0xff & value.colorType);
+ baos.write(0xff & value.compressionMethod);
+ baos.write(0xff & value.filterMethod);
+ baos.write(0xff & value.interlaceMethod);
+
+ // Debug.debug("baos", baos.toByteArray());
+
+ writeChunk(os, IHDR_CHUNK_TYPE, baos.toByteArray());
+ }
+
+ private void writeChunkiTXt(OutputStream os, PngText.iTXt text)
+ throws IOException, ImageWriteException
+ {
+ if (!UnicodeUtils.isValidISO_8859_1(text.keyword))
+ throw new ImageWriteException(
+ "Png tEXt chunk keyword is not ISO-8859-1: " + text.keyword);
+ if (!UnicodeUtils.isValidISO_8859_1(text.languageTag))
+ throw new ImageWriteException(
+ "Png tEXt chunk language tag is not ISO-8859-1: "
+ + text.languageTag);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // keyword
+ baos.write(text.keyword.getBytes("ISO-8859-1"));
+ baos.write(0);
+
+ baos.write(1); // compressed flag, true
+ baos.write(COMPRESSION_DEFLATE_INFLATE); // compression method
+
+ // language tag
+ baos.write(text.languageTag.getBytes("ISO-8859-1"));
+ baos.write(0);
+
+ // translated keyword
+ baos.write(text.translatedKeyword.getBytes("utf-8"));
+ baos.write(0);
+
+ baos.write(new ZLibUtils().deflate(text.text.getBytes("utf-8")));
+
+ writeChunk(os, iTXt_CHUNK_TYPE, baos.toByteArray());
+ }
+
+ private void writeChunkzTXt(OutputStream os, PngText.zTXt text)
+ throws IOException, ImageWriteException
+ {
+ if (!UnicodeUtils.isValidISO_8859_1(text.keyword))
+ throw new ImageWriteException(
+ "Png zTXt chunk keyword is not ISO-8859-1: " + text.keyword);
+ if (!UnicodeUtils.isValidISO_8859_1(text.text))
+ throw new ImageWriteException(
+ "Png zTXt chunk text is not ISO-8859-1: " + text.text);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // keyword
+ baos.write(text.keyword.getBytes("ISO-8859-1"));
+ baos.write(0);
+
+ // compression method
+ baos.write(PngConstants.COMPRESSION_DEFLATE_INFLATE);
+
+ // text
+ baos
+ .write(new ZLibUtils().deflate(text.text
+ .getBytes("ISO-8859-1")));
+
+ writeChunk(os, zTXt_CHUNK_TYPE, baos.toByteArray());
+ }
+
+ private void writeChunktEXt(OutputStream os, PngText.tEXt text)
+ throws IOException, ImageWriteException
+ {
+ if (!UnicodeUtils.isValidISO_8859_1(text.keyword))
+ throw new ImageWriteException(
+ "Png tEXt chunk keyword is not ISO-8859-1: " + text.keyword);
+ if (!UnicodeUtils.isValidISO_8859_1(text.text))
+ throw new ImageWriteException(
+ "Png tEXt chunk text is not ISO-8859-1: " + text.text);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // keyword
+ baos.write(text.keyword.getBytes("ISO-8859-1"));
+ baos.write(0);
+
+ // text
+ baos.write(text.text.getBytes("ISO-8859-1"));
+
+ writeChunk(os, tEXt_CHUNK_TYPE, baos.toByteArray());
+ }
+
+ private void writeChunkXmpiTXt(OutputStream os, String xmpXml)
+ throws IOException
+ {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // keyword
+ baos.write(XMP_KEYWORD.getBytes("ISO-8859-1"));
+ baos.write(0);
+
+ baos.write(1); // compressed flag, true
+ baos.write(COMPRESSION_DEFLATE_INFLATE); // compression method
+
+ baos.write(0); // language tag (ignore). TODO
+
+ // translated keyword
+ baos.write(XMP_KEYWORD.getBytes("utf-8"));
+ baos.write(0);
+
+ baos.write(new ZLibUtils().deflate(xmpXml.getBytes("utf-8")));
+
+ writeChunk(os, iTXt_CHUNK_TYPE, baos.toByteArray());
+ }
+
+ private void writeChunkPLTE(OutputStream os, Palette palette)
+ throws IOException
+ {
+ int length = palette.length();
+ byte bytes[] = new byte[length * 3];
+
+ // Debug.debug("length", length);
+ for (int i = 0; i < length; i++)
+ {
+ int rgb = palette.getEntry(i);
+ int index = i * 3;
+ // Debug.debug("index", index);
+ bytes[index + 0] = (byte) (0xff & (rgb >> 16));
+ bytes[index + 1] = (byte) (0xff & (rgb >> 8));
+ bytes[index + 2] = (byte) (0xff & (rgb >> 0));
+ }
+
+ writeChunk(os, PLTE_CHUNK_TYPE, bytes);
+ }
+
+ private void writeChunkIEND(OutputStream os) throws IOException
+ {
+ writeChunk(os, IEND_CHUNK_TYPE, null);
+ }
+
+ private void writeChunkIDAT(OutputStream os, byte bytes[])
+ throws IOException
+ {
+ writeChunk(os, IDAT_CHUNK_TYPE, bytes);
+ }
+
+ private byte getColourType(boolean hasAlpha, boolean isGrayscale)
+ {
+ byte result;
+
+ boolean index = false; // charles
+
+ if (index)
+ result = COLOR_TYPE_INDEXED_COLOR;
+ else if (isGrayscale)
+ {
+ if (hasAlpha)
+ result = COLOR_TYPE_GREYSCALE_WITH_ALPHA;
+ else
+ result = COLOR_TYPE_GREYSCALE;
+ } else if (hasAlpha)
+ result = COLOR_TYPE_TRUE_COLOR_WITH_ALPHA;
+ else
+ result = COLOR_TYPE_TRUE_COLOR;
+
+ return result;
+ }
+
+ private byte getBitDepth(final byte colorType, Map params)
+ {
+ byte result = 8;
+
+ Object o = params.get(PARAM_KEY_PNG_BIT_DEPTH);
+ if (o != null && o instanceof Number)
+ {
+ int value = ((Number) o).intValue();
+ switch (value)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ result = (byte) value;
+ break;
+ default:
+ }
+ switch (colorType)
+ {
+ case COLOR_TYPE_GREYSCALE:
+ break;
+ case COLOR_TYPE_INDEXED_COLOR:
+ result = (byte) Math.min(8, result);
+ break;
+ case COLOR_TYPE_GREYSCALE_WITH_ALPHA:
+ case COLOR_TYPE_TRUE_COLOR:
+ case COLOR_TYPE_TRUE_COLOR_WITH_ALPHA:
+ result = (byte) Math.max(8, result);
+ break;
+ default:
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ * between two chunk types indicates alternatives. Table 5.3 Chunk
+ * ordering rules Critical chunks (shall appear in this order, except PLTE
+ * is optional) Chunk name Multiple allowed Ordering constraints IHDR No
+ * Shall be first PLTE No Before first IDAT IDAT Yes Multiple IDAT chunks
+ * shall be consecutive IEND No Shall be last Ancillary chunks (need not
+ * appear in this order) Chunk name Multiple allowed Ordering constraints
+ * cHRM No Before PLTE and IDAT gAMA No Before PLTE and IDAT iCCP No Before
+ * PLTE and IDAT. If the iCCP chunk is present, the sRGB chunk should not be
+ * present. sBIT No Before PLTE and IDAT sRGB No Before PLTE and IDAT. If
+ * the sRGB chunk is present, the iCCP chunk should not be present. bKGD No
+ * After PLTE; before IDAT hIST No After PLTE; before IDAT tRNS No After
+ * PLTE; before IDAT pHYs No Before IDAT sPLT Yes Before IDAT tIME No None
+ * iTXt Yes None tEXt Yes None zTXt Yes None
+ */
+
+ public void writeImage(BufferedImage src, OutputStream os, Map params)
+ throws ImageWriteException, IOException
+ {
+ // make copy of params; we'll clear keys as we consume them.
+ params = new HashMap(params);
+
+ // clear format key.
+ if (params.containsKey(PARAM_KEY_FORMAT))
+ params.remove(PARAM_KEY_FORMAT);
+ // clear verbose key.
+ if (params.containsKey(PARAM_KEY_VERBOSE))
+ params.remove(PARAM_KEY_VERBOSE);
+
+ Map rawParams = new HashMap(params);
+ if (params.containsKey(PARAM_KEY_PNG_FORCE_TRUE_COLOR))
+ params.remove(PARAM_KEY_PNG_FORCE_TRUE_COLOR);
+ if (params.containsKey(PARAM_KEY_PNG_FORCE_INDEXED_COLOR))
+ params.remove(PARAM_KEY_PNG_FORCE_INDEXED_COLOR);
+ if (params.containsKey(PARAM_KEY_PNG_BIT_DEPTH))
+ params.remove(PARAM_KEY_PNG_BIT_DEPTH);
+ if (params.containsKey(PARAM_KEY_XMP_XML))
+ params.remove(PARAM_KEY_XMP_XML);
+ if (params.containsKey(PARAM_KEY_PNG_TEXT_CHUNKS))
+ params.remove(PARAM_KEY_PNG_TEXT_CHUNKS);
+ if (params.size() > 0)
+ {
+ Object firstKey = params.keySet().iterator().next();
+ throw new ImageWriteException("Unknown parameter: " + firstKey);
+ }
+ params = rawParams;
+
+ int width = src.getWidth();
+ int height = src.getHeight();
+
+ boolean hasAlpha = new PaletteFactory().hasTransparency(src);
+ if (verbose)
+ Debug.debug("hasAlpha", hasAlpha);
+ // int transparency = new PaletteFactory().getTransparency(src);
+
+ boolean isGrayscale = new PaletteFactory().isGrayscale(src);
+ if (verbose)
+ Debug.debug("isGrayscale", isGrayscale);
+
+ byte colorType;
+ {
+ boolean forceIndexedColor = ParamMap.getParamBoolean(params,
+ PARAM_KEY_PNG_FORCE_INDEXED_COLOR, false);
+ boolean forceTrueColor = ParamMap.getParamBoolean(params,
+ PARAM_KEY_PNG_FORCE_TRUE_COLOR, false);
+
+ if (forceIndexedColor && forceTrueColor)
+ throw new ImageWriteException(
+ "Params: Cannot force both indexed and true color modes");
+ else if (forceIndexedColor)
+ {
+ colorType = COLOR_TYPE_INDEXED_COLOR;
+ } else if (forceTrueColor)
+ {
+ colorType = (byte) (hasAlpha ? COLOR_TYPE_TRUE_COLOR_WITH_ALPHA
+ : COLOR_TYPE_TRUE_COLOR);
+ isGrayscale = false;
+ } else
+ colorType = getColourType(hasAlpha, isGrayscale);
+ if (verbose)
+ Debug.debug("colorType", colorType);
+ }
+
+ byte bitDepth = getBitDepth(colorType, params);
+ if (verbose)
+ Debug.debug("bit_depth", bitDepth);
+
+ int sampleDepth;
+ if (colorType == COLOR_TYPE_INDEXED_COLOR)
+ sampleDepth = 8;
+ else
+ sampleDepth = bitDepth;
+ if (verbose)
+ Debug.debug("sample_depth", sampleDepth);
+
+ {
+ os.write(PNG_Signature);
+ }
+ {
+ // IHDR must be first
+
+ byte compressionMethod = COMPRESSION_TYPE_INFLATE_DEFLATE;
+ byte filterMethod = FILTER_METHOD_ADAPTIVE;
+ byte interlaceMethod = INTERLACE_METHOD_NONE;
+
+ ImageHeader imageHeader = new ImageHeader(width, height, bitDepth,
+ colorType, compressionMethod, filterMethod, interlaceMethod);
+
+ writeChunkIHDR(os, imageHeader);
+ }
+
+ {
+ // sRGB No Before PLTE and IDAT. If the sRGB chunk is present, the
+ // iCCP chunk should not be present.
+
+ // charles
+ }
+
+ Palette palette = null;
+ if (colorType == COLOR_TYPE_INDEXED_COLOR)
+ {
+ // PLTE No Before first IDAT
+
+ int max_colors = hasAlpha ? 255 : 256;
+
+ palette = new MedianCutQuantizer(true).process(src, max_colors,
+ verbose);
+ // Palette palette2 = new PaletteFactory().makePaletteSimple(src,
+ // max_colors);
+
+ // palette.dump();
+
+ writeChunkPLTE(os, palette);
+ }
+
+ if (params.containsKey(PARAM_KEY_XMP_XML))
+ {
+ String xmpXml = (String) params.get(PARAM_KEY_XMP_XML);
+ writeChunkXmpiTXt(os, xmpXml);
+ }
+
+ if (params.containsKey(PARAM_KEY_PNG_TEXT_CHUNKS))
+ {
+ List outputTexts = (List) params.get(PARAM_KEY_PNG_TEXT_CHUNKS);
+ for (int i = 0; i < outputTexts.size(); i++)
+ {
+ PngText text = (PngText) outputTexts.get(i);
+ if (text instanceof PngText.tEXt)
+ writeChunktEXt(os, (PngText.tEXt) text);
+ else if (text instanceof PngText.zTXt)
+ writeChunkzTXt(os, (PngText.zTXt) text);
+ else if (text instanceof PngText.iTXt)
+ writeChunkiTXt(os, (PngText.iTXt) text);
+ else
+ throw new ImageWriteException(
+ "Unknown text to embed in PNG: " + text);
+ }
+ }
+
+ {
+ // Debug.debug("writing IDAT");
+
+ // IDAT Yes Multiple IDAT chunks shall be consecutive
+
+ byte uncompressed[];
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ boolean useAlpha = colorType == COLOR_TYPE_GREYSCALE_WITH_ALPHA
+ || colorType == COLOR_TYPE_TRUE_COLOR_WITH_ALPHA;
+
+ int row[] = new int[width];
+ for (int y = 0; y < height; y++)
+ {
+ // Debug.debug("y", y + "/" + height);
+ src.getRGB(0, y, width, 1, row, 0, width);
+
+ byte filter_type = FILTER_TYPE_NONE;
+ baos.write(filter_type);
+ for (int x = 0; x < width; x++)
+ {
+ int argb = row[x];
+
+ if (palette != null)
+ {
+ int index = palette.getPaletteIndex(argb);
+ baos.write(0xff & index);
+ } else
+ {
+ int alpha = 0xff & (argb >> 24);
+ int red = 0xff & (argb >> 16);
+ int green = 0xff & (argb >> 8);
+ int blue = 0xff & (argb >> 0);
+
+ if (isGrayscale)
+ {
+ int gray = (red + green + blue) / 3;
+ // if(y==0)
+ // {
+ // Debug.debug("gray: " + x + ", " + y +
+ // " argb: 0x"
+ // + Integer.toHexString(argb) + " gray: 0x"
+ // + Integer.toHexString(gray));
+ // // Debug.debug(x + ", " + y + " gray", gray);
+ // // Debug.debug(x + ", " + y + " gray", gray);
+ // Debug.debug(x + ", " + y + " gray", gray +
+ // " " + Integer.toHexString(gray));
+ // Debug.debug();
+ // }
+ baos.write(gray);
+ } else
+ {
+ baos.write(red);
+ baos.write(green);
+ baos.write(blue);
+ }
+ if (useAlpha)
+ baos.write(alpha);
+ }
+ }
+ }
+ uncompressed = baos.toByteArray();
+ }
+
+ // Debug.debug("uncompressed", uncompressed.length);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DeflaterOutputStream dos = new DeflaterOutputStream(baos);
+ int chunk_size = 256 * 1024;
+ for (int index = 0; index < uncompressed.length; index += chunk_size)
+ {
+ int end = Math.min(uncompressed.length, index + chunk_size);
+ int length = end - index;
+
+ dos.write(uncompressed, index, length);
+ dos.flush();
+ baos.flush();
+
+ byte compressed[] = baos.toByteArray();
+ baos.reset();
+ if (compressed.length > 0)
+ {
+ // Debug.debug("compressed", compressed.length);
+ writeChunkIDAT(os, compressed);
+ }
+
+ }
+ {
+ dos.finish();
+ byte compressed[] = baos.toByteArray();
+ if (compressed.length > 0)
+ {
+ // Debug.debug("compressed final", compressed.length);
+ writeChunkIDAT(os, compressed);
+ }
+ }
+ }
+
+ {
+ // IEND No Shall be last
+
+ writeChunkIEND(os);
+ }
+
+ /*
+ * Ancillary chunks (need not appear in this order) Chunk name Multiple
+ * allowed Ordering constraints cHRM No Before PLTE and IDAT gAMA No
+ * Before PLTE and IDAT iCCP No Before PLTE and IDAT. If the iCCP chunk
+ * is present, the sRGB chunk should not be present. sBIT No Before PLTE
+ * and IDAT sRGB No Before PLTE and IDAT. If the sRGB chunk is present,
+ * the iCCP chunk should not be present. bKGD No After PLTE; before IDAT
+ * hIST No After PLTE; before IDAT tRNS No After PLTE; before IDAT pHYs
+ * No Before IDAT sPLT Yes Before IDAT tIME No None iTXt Yes None tEXt
+ * Yes None zTXt Yes None
+ */
+
+ os.close();
+ } // todo: filter types
+ // proper colour types
+ // srgb, etc.
}
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediter.java Fri Sep 10 16:33:35 2010
@@ -33,215 +33,215 @@ import org.apache.sanselan.formats.trans
public abstract class ScanExpediter extends BinaryFileParser
{
- protected final int width;
- protected final int height;
- protected final InputStream is;
- protected final BufferedImage bi;
- protected final int colorType;
- protected final int bitDepth;
- protected final int bytesPerPixel;
- protected final int bitsPerPixel;
- protected final PNGChunkPLTE pngChunkPLTE;
- protected final GammaCorrection gammaCorrection;
- protected final TransparencyFilter transparencyFilter;
-
- public ScanExpediter(int width, int height, InputStream is,
- BufferedImage bi, int color_type, int bitDepth, int bitsPerPixel,
- PNGChunkPLTE pngChunkPLTE, GammaCorrection gammaCorrection,
- TransparencyFilter transparencyFilter)
-
- {
- this.width = width;
- this.height = height;
- this.is = is;
- this.bi = bi;
- this.colorType = color_type;
- this.bitDepth = bitDepth;
- this.bytesPerPixel = this.getBitsToBytesRoundingUp(bitsPerPixel);
- this.bitsPerPixel = bitsPerPixel;
- this.pngChunkPLTE = pngChunkPLTE;
- this.gammaCorrection = gammaCorrection;
- this.transparencyFilter = transparencyFilter;
- }
-
- protected int getBitsToBytesRoundingUp(int bits)
- {
- int bytes = bits / 8;
- if ((bits % 8 > 0))
- bytes++;
- return bytes;
- }
-
- protected final int getPixelARGB(int alpha, int red, int green, int blue)
- {
- int rgb = ((0xff & alpha) << 24) | ((0xff & red) << 16)
- | ((0xff & green) << 8) | ((0xff & blue) << 0);
-
- return rgb;
- }
-
- protected final int getPixelRGB(int red, int green, int blue)
- {
- return getPixelARGB(0xff, red, green, blue);
- }
-
- public abstract void drive() throws ImageReadException, IOException;
-
- protected int getRGB(BitParser bitParser, int pixelIndexInScanline)
- throws ImageReadException, IOException
- {
-
- switch (colorType)
- {
- case 0: // 1,2,4,8,16 Each pixel is a grayscale sample.
- {
- int sample = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
-
- if (gammaCorrection != null)
- {
- sample = gammaCorrection.correctSample(sample);
- }
-
- int rgb = getPixelRGB(sample, sample, sample);
-
- if (transparencyFilter != null)
- rgb = transparencyFilter.filter(rgb, sample);
-
- return rgb;
-
- }
- case 2: // 8,16 Each pixel is an R,G,B triple.
- {
- int red = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
- int green = bitParser.getSampleAsByte(pixelIndexInScanline, 1);
- int blue = bitParser.getSampleAsByte(pixelIndexInScanline, 2);
-
- int rgb = getPixelRGB(red, green, blue);
-
- if (transparencyFilter != null)
- rgb = transparencyFilter.filter(rgb, -1);
-
- if (gammaCorrection != null)
- {
- int alpha = (0xff000000 & rgb) >> 24; // make sure to preserve
- // transparency
- red = gammaCorrection.correctSample(red);
- green = gammaCorrection.correctSample(green);
- blue = gammaCorrection.correctSample(blue);
- rgb = getPixelARGB(alpha, red, green, blue);
- }
-
- return rgb;
- }
- //
- case 3: // 1,2,4,8 Each pixel is a palette index;
- // a PLTE chunk must appear.
- {
- int index = bitParser.getSample(pixelIndexInScanline, 0);
-
- int rgb = pngChunkPLTE.getRGB(index);
-
- if (transparencyFilter != null)
- rgb = transparencyFilter.filter(rgb, index);
-
- return rgb;
- }
- case 4: // 8,16 Each pixel is a grayscale sample,
- // followed by an alpha sample.
- {
- int sample = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
- int alpha = bitParser.getSampleAsByte(pixelIndexInScanline, 1);
-
- if (gammaCorrection != null)
- sample = gammaCorrection.correctSample(sample);
-
- int rgb = getPixelARGB(alpha, sample, sample, sample);
- return rgb;
-
- }
- case 6: // 8,16 Each pixel is an R,G,B triple,
- {
- int red = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
- int green = bitParser.getSampleAsByte(pixelIndexInScanline, 1);
- int blue = bitParser.getSampleAsByte(pixelIndexInScanline, 2);
- int alpha = bitParser.getSampleAsByte(pixelIndexInScanline, 3);
-
- if (gammaCorrection != null)
- {
- red = gammaCorrection.correctSample(red);
- green = gammaCorrection.correctSample(green);
- blue = gammaCorrection.correctSample(blue);
- }
-
- int rgb = getPixelARGB(alpha, red, green, blue);
- return rgb;
- }
- default:
- throw new ImageReadException("PNG: unknown color type: "
- + colorType);
- }
- }
-
- protected ScanlineFilter getScanlineFilter(int filter_type,
- int BytesPerPixel) throws ImageReadException, IOException
- {
- ScanlineFilter filter;
-
- switch (filter_type)
- {
- case 0: // None
- filter = new ScanlineFilterNone();
- break;
-
- case 1: // Sub
- filter = new ScanlineFilterSub(BytesPerPixel);
- break;
-
- case 2: // Up
- filter = new ScanlineFilterUp(BytesPerPixel);
- break;
-
- case 3: // Average
- filter = new ScanlineFilterAverage(BytesPerPixel);
- break;
-
- case 4: // Paeth
- filter = new ScanlineFilterPaeth(BytesPerPixel);
- break;
-
- default:
- throw new ImageReadException("PNG: unknown filter_type: "
- + filter_type);
-
- }
-
- return filter;
- }
-
- protected byte[] unfilterScanline(int filter_type, byte src[], byte prev[],
- int BytesPerPixel) throws ImageReadException, IOException
- {
- ScanlineFilter filter = getScanlineFilter(filter_type, BytesPerPixel);
-
- byte dst[] = new byte[src.length];
- filter.unfilter(src, dst, prev);
- return dst;
- }
-
- protected byte[] getNextScanline(InputStream is, int length, byte prev[],
- int BytesPerPixel) throws ImageReadException, IOException
- {
- int filterType = is.read();
- if (filterType < 0)
- throw new ImageReadException("PNG: missing filter type");
+ protected final int width;
+ protected final int height;
+ protected final InputStream is;
+ protected final BufferedImage bi;
+ protected final int colorType;
+ protected final int bitDepth;
+ protected final int bytesPerPixel;
+ protected final int bitsPerPixel;
+ protected final PNGChunkPLTE pngChunkPLTE;
+ protected final GammaCorrection gammaCorrection;
+ protected final TransparencyFilter transparencyFilter;
+
+ public ScanExpediter(int width, int height, InputStream is,
+ BufferedImage bi, int color_type, int bitDepth, int bitsPerPixel,
+ PNGChunkPLTE pngChunkPLTE, GammaCorrection gammaCorrection,
+ TransparencyFilter transparencyFilter)
+
+ {
+ this.width = width;
+ this.height = height;
+ this.is = is;
+ this.bi = bi;
+ this.colorType = color_type;
+ this.bitDepth = bitDepth;
+ this.bytesPerPixel = this.getBitsToBytesRoundingUp(bitsPerPixel);
+ this.bitsPerPixel = bitsPerPixel;
+ this.pngChunkPLTE = pngChunkPLTE;
+ this.gammaCorrection = gammaCorrection;
+ this.transparencyFilter = transparencyFilter;
+ }
+
+ protected int getBitsToBytesRoundingUp(int bits)
+ {
+ int bytes = bits / 8;
+ if ((bits % 8 > 0))
+ bytes++;
+ return bytes;
+ }
+
+ protected final int getPixelARGB(int alpha, int red, int green, int blue)
+ {
+ int rgb = ((0xff & alpha) << 24) | ((0xff & red) << 16)
+ | ((0xff & green) << 8) | ((0xff & blue) << 0);
+
+ return rgb;
+ }
+
+ protected final int getPixelRGB(int red, int green, int blue)
+ {
+ return getPixelARGB(0xff, red, green, blue);
+ }
+
+ public abstract void drive() throws ImageReadException, IOException;
+
+ protected int getRGB(BitParser bitParser, int pixelIndexInScanline)
+ throws ImageReadException, IOException
+ {
+
+ switch (colorType)
+ {
+ case 0: // 1,2,4,8,16 Each pixel is a grayscale sample.
+ {
+ int sample = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
+
+ if (gammaCorrection != null)
+ {
+ sample = gammaCorrection.correctSample(sample);
+ }
+
+ int rgb = getPixelRGB(sample, sample, sample);
+
+ if (transparencyFilter != null)
+ rgb = transparencyFilter.filter(rgb, sample);
+
+ return rgb;
+
+ }
+ case 2: // 8,16 Each pixel is an R,G,B triple.
+ {
+ int red = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
+ int green = bitParser.getSampleAsByte(pixelIndexInScanline, 1);
+ int blue = bitParser.getSampleAsByte(pixelIndexInScanline, 2);
+
+ int rgb = getPixelRGB(red, green, blue);
+
+ if (transparencyFilter != null)
+ rgb = transparencyFilter.filter(rgb, -1);
+
+ if (gammaCorrection != null)
+ {
+ int alpha = (0xff000000 & rgb) >> 24; // make sure to preserve
+ // transparency
+ red = gammaCorrection.correctSample(red);
+ green = gammaCorrection.correctSample(green);
+ blue = gammaCorrection.correctSample(blue);
+ rgb = getPixelARGB(alpha, red, green, blue);
+ }
+
+ return rgb;
+ }
+ //
+ case 3: // 1,2,4,8 Each pixel is a palette index;
+ // a PLTE chunk must appear.
+ {
+ int index = bitParser.getSample(pixelIndexInScanline, 0);
+
+ int rgb = pngChunkPLTE.getRGB(index);
+
+ if (transparencyFilter != null)
+ rgb = transparencyFilter.filter(rgb, index);
+
+ return rgb;
+ }
+ case 4: // 8,16 Each pixel is a grayscale sample,
+ // followed by an alpha sample.
+ {
+ int sample = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
+ int alpha = bitParser.getSampleAsByte(pixelIndexInScanline, 1);
+
+ if (gammaCorrection != null)
+ sample = gammaCorrection.correctSample(sample);
+
+ int rgb = getPixelARGB(alpha, sample, sample, sample);
+ return rgb;
+
+ }
+ case 6: // 8,16 Each pixel is an R,G,B triple,
+ {
+ int red = bitParser.getSampleAsByte(pixelIndexInScanline, 0);
+ int green = bitParser.getSampleAsByte(pixelIndexInScanline, 1);
+ int blue = bitParser.getSampleAsByte(pixelIndexInScanline, 2);
+ int alpha = bitParser.getSampleAsByte(pixelIndexInScanline, 3);
+
+ if (gammaCorrection != null)
+ {
+ red = gammaCorrection.correctSample(red);
+ green = gammaCorrection.correctSample(green);
+ blue = gammaCorrection.correctSample(blue);
+ }
+
+ int rgb = getPixelARGB(alpha, red, green, blue);
+ return rgb;
+ }
+ default:
+ throw new ImageReadException("PNG: unknown color type: "
+ + colorType);
+ }
+ }
+
+ protected ScanlineFilter getScanlineFilter(int filter_type,
+ int BytesPerPixel) throws ImageReadException, IOException
+ {
+ ScanlineFilter filter;
+
+ switch (filter_type)
+ {
+ case 0: // None
+ filter = new ScanlineFilterNone();
+ break;
+
+ case 1: // Sub
+ filter = new ScanlineFilterSub(BytesPerPixel);
+ break;
+
+ case 2: // Up
+ filter = new ScanlineFilterUp(BytesPerPixel);
+ break;
+
+ case 3: // Average
+ filter = new ScanlineFilterAverage(BytesPerPixel);
+ break;
+
+ case 4: // Paeth
+ filter = new ScanlineFilterPaeth(BytesPerPixel);
+ break;
+
+ default:
+ throw new ImageReadException("PNG: unknown filter_type: "
+ + filter_type);
+
+ }
+
+ return filter;
+ }
+
+ protected byte[] unfilterScanline(int filter_type, byte src[], byte prev[],
+ int BytesPerPixel) throws ImageReadException, IOException
+ {
+ ScanlineFilter filter = getScanlineFilter(filter_type, BytesPerPixel);
+
+ byte dst[] = new byte[src.length];
+ filter.unfilter(src, dst, prev);
+ return dst;
+ }
+
+ protected byte[] getNextScanline(InputStream is, int length, byte prev[],
+ int BytesPerPixel) throws ImageReadException, IOException
+ {
+ int filterType = is.read();
+ if (filterType < 0)
+ throw new ImageReadException("PNG: missing filter type");
- byte scanline[] = this.readByteArray("scanline", length, is,
- "PNG: missing image data");
+ byte scanline[] = this.readByteArray("scanline", length, is,
+ "PNG: missing image data");
- byte unfiltered[] = unfilterScanline(filterType, scanline, prev,
- BytesPerPixel);
+ byte unfiltered[] = unfilterScanline(filterType, scanline, prev,
+ BytesPerPixel);
- return unfiltered;
- }
+ return unfiltered;
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterInterlaced.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterInterlaced.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterInterlaced.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterInterlaced.java Fri Sep 10 16:33:35 2010
@@ -26,97 +26,97 @@ import org.apache.sanselan.formats.trans
public class ScanExpediterInterlaced extends ScanExpediter
{
- public ScanExpediterInterlaced(int width, int height, InputStream is,
- BufferedImage bi, int color_type, int BitDepth, int bits_per_pixel,
- PNGChunkPLTE fPNGChunkPLTE, GammaCorrection fGammaCorrection,
- TransparencyFilter fTransparencyFilter)
-
- {
- super(width, height, is, bi, color_type, BitDepth, bits_per_pixel,
- fPNGChunkPLTE, fGammaCorrection, fTransparencyFilter);
- }
-
- private void visit(int x, int y, BufferedImage bi, BitParser fBitParser,
- int color_type, int pixel_index_in_scanline,
- PNGChunkPLTE fPNGChunkPLTE, GammaCorrection fGammaCorrection)
- throws ImageReadException, IOException
- {
- int rgb = getRGB(fBitParser,
- // color_type,
- pixel_index_in_scanline
- // ,
- // fPNGChunkPLTE, fGammaCorrection
- );
-
- bi.setRGB(x, y, rgb);
-
- // buffer.setElem(y * width +x , rgb);
-
- }
-
- public static final int Starting_Row[] = {
- 0, 0, 4, 0, 2, 0, 1
- };
- public static final int Starting_Col[] = {
- 0, 4, 0, 2, 0, 1, 0
- };
- public static final int Row_Increment[] = {
- 8, 8, 8, 4, 4, 2, 2
- };
- public static final int Col_Increment[] = {
- 8, 8, 4, 4, 2, 2, 1
- };
- public static final int Block_Height[] = {
- 8, 8, 4, 4, 2, 2, 1
- };
- public static final int Block_Width[] = {
- 8, 4, 4, 2, 2, 1, 1
- };
-
- public void drive() throws ImageReadException, IOException
- {
-
- int pass = 1;
- while (pass <= 7)
- {
- byte prev[] = null;
-
- int y = Starting_Row[pass - 1];
- // int y_stride = Row_Increment[pass - 1];
- boolean rows_in_pass = (y < height);
- while (y < height)
- {
- int x = Starting_Col[pass - 1];
- int pixel_index_in_scanline = 0;
-
- if (x < width)
- {
- // only get data if there are pixels in this scanline/pass
- int ColumnsInRow = 1 + ((width - Starting_Col[pass - 1] - 1) / Col_Increment[pass - 1]);
- int bitsPerScanLine = bitsPerPixel * ColumnsInRow;
- int pixel_bytes_per_scan_line = getBitsToBytesRoundingUp(bitsPerScanLine);
-
- byte unfiltered[] = getNextScanline(is,
- pixel_bytes_per_scan_line, prev, bytesPerPixel);
-
- prev = unfiltered;
-
- BitParser fBitParser = new BitParser(unfiltered,
- bitsPerPixel, bitDepth);
-
- while (x < width)
- {
- visit(x, y, bi, fBitParser, colorType,
- pixel_index_in_scanline, pngChunkPLTE,
- gammaCorrection);
-
- x = x + Col_Increment[pass - 1];
- pixel_index_in_scanline++;
- }
- }
- y = y + Row_Increment[pass - 1];
- }
- pass = pass + 1;
- }
- }
+ public ScanExpediterInterlaced(int width, int height, InputStream is,
+ BufferedImage bi, int color_type, int BitDepth, int bits_per_pixel,
+ PNGChunkPLTE fPNGChunkPLTE, GammaCorrection fGammaCorrection,
+ TransparencyFilter fTransparencyFilter)
+
+ {
+ super(width, height, is, bi, color_type, BitDepth, bits_per_pixel,
+ fPNGChunkPLTE, fGammaCorrection, fTransparencyFilter);
+ }
+
+ private void visit(int x, int y, BufferedImage bi, BitParser fBitParser,
+ int color_type, int pixel_index_in_scanline,
+ PNGChunkPLTE fPNGChunkPLTE, GammaCorrection fGammaCorrection)
+ throws ImageReadException, IOException
+ {
+ int rgb = getRGB(fBitParser,
+ // color_type,
+ pixel_index_in_scanline
+ // ,
+ // fPNGChunkPLTE, fGammaCorrection
+ );
+
+ bi.setRGB(x, y, rgb);
+
+ // buffer.setElem(y * width +x , rgb);
+
+ }
+
+ public static final int Starting_Row[] = {
+ 0, 0, 4, 0, 2, 0, 1
+ };
+ public static final int Starting_Col[] = {
+ 0, 4, 0, 2, 0, 1, 0
+ };
+ public static final int Row_Increment[] = {
+ 8, 8, 8, 4, 4, 2, 2
+ };
+ public static final int Col_Increment[] = {
+ 8, 8, 4, 4, 2, 2, 1
+ };
+ public static final int Block_Height[] = {
+ 8, 8, 4, 4, 2, 2, 1
+ };
+ public static final int Block_Width[] = {
+ 8, 4, 4, 2, 2, 1, 1
+ };
+
+ public void drive() throws ImageReadException, IOException
+ {
+
+ int pass = 1;
+ while (pass <= 7)
+ {
+ byte prev[] = null;
+
+ int y = Starting_Row[pass - 1];
+ // int y_stride = Row_Increment[pass - 1];
+ boolean rows_in_pass = (y < height);
+ while (y < height)
+ {
+ int x = Starting_Col[pass - 1];
+ int pixel_index_in_scanline = 0;
+
+ if (x < width)
+ {
+ // only get data if there are pixels in this scanline/pass
+ int ColumnsInRow = 1 + ((width - Starting_Col[pass - 1] - 1) / Col_Increment[pass - 1]);
+ int bitsPerScanLine = bitsPerPixel * ColumnsInRow;
+ int pixel_bytes_per_scan_line = getBitsToBytesRoundingUp(bitsPerScanLine);
+
+ byte unfiltered[] = getNextScanline(is,
+ pixel_bytes_per_scan_line, prev, bytesPerPixel);
+
+ prev = unfiltered;
+
+ BitParser fBitParser = new BitParser(unfiltered,
+ bitsPerPixel, bitDepth);
+
+ while (x < width)
+ {
+ visit(x, y, bi, fBitParser, colorType,
+ pixel_index_in_scanline, pngChunkPLTE,
+ gammaCorrection);
+
+ x = x + Col_Increment[pass - 1];
+ pixel_index_in_scanline++;
+ }
+ }
+ y = y + Row_Increment[pass - 1];
+ }
+ pass = pass + 1;
+ }
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterSimple.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterSimple.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterSimple.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/ScanExpediterSimple.java Fri Sep 10 16:33:35 2010
@@ -26,39 +26,39 @@ import org.apache.sanselan.formats.trans
public class ScanExpediterSimple extends ScanExpediter
{
- public ScanExpediterSimple(int width, int height, InputStream is,
- BufferedImage bi, int color_type, int BitDepth, int bitsPerPixel,
- PNGChunkPLTE pngChunkPLTE, GammaCorrection gammaCorrection,
- TransparencyFilter transparencyFilter)
-
- {
- super(width, height, is, bi, color_type, BitDepth, bitsPerPixel,
- pngChunkPLTE, gammaCorrection, transparencyFilter);
- }
-
- public void drive() throws ImageReadException, IOException
- {
- int bitsPerScanLine = bitsPerPixel * width;
- int pixelBytesPerScanLine = getBitsToBytesRoundingUp(bitsPerScanLine);
- byte prev[] = null;
-
- for (int y = 0; y < height; y++)
- {
- byte unfiltered[] = getNextScanline(is, pixelBytesPerScanLine,
- prev, bytesPerPixel);
-
- prev = unfiltered;
-
- BitParser bitParser = new BitParser(unfiltered, bitsPerPixel,
- bitDepth);
-
- for (int x = 0; x < width; x++)
- {
- int rgb = getRGB(bitParser, x);
-
- bi.setRGB(x, y, rgb);
- }
- }
+ public ScanExpediterSimple(int width, int height, InputStream is,
+ BufferedImage bi, int color_type, int BitDepth, int bitsPerPixel,
+ PNGChunkPLTE pngChunkPLTE, GammaCorrection gammaCorrection,
+ TransparencyFilter transparencyFilter)
+
+ {
+ super(width, height, is, bi, color_type, BitDepth, bitsPerPixel,
+ pngChunkPLTE, gammaCorrection, transparencyFilter);
+ }
+
+ public void drive() throws ImageReadException, IOException
+ {
+ int bitsPerScanLine = bitsPerPixel * width;
+ int pixelBytesPerScanLine = getBitsToBytesRoundingUp(bitsPerScanLine);
+ byte prev[] = null;
+
+ for (int y = 0; y < height; y++)
+ {
+ byte unfiltered[] = getNextScanline(is, pixelBytesPerScanLine,
+ prev, bytesPerPixel);
+
+ prev = unfiltered;
+
+ BitParser bitParser = new BitParser(unfiltered, bitsPerPixel,
+ bitDepth);
+
+ for (int x = 0; x < width; x++)
+ {
+ int rgb = getRGB(bitParser, x);
+
+ bi.setRGB(x, y, rgb);
+ }
+ }
- }
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunk.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunk.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunk.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunk.java Fri Sep 10 16:33:35 2010
@@ -22,41 +22,41 @@ import org.apache.sanselan.common.Binary
public class PNGChunk extends BinaryFileParser
{
- public final int length;
- public final int chunkType;
- public final int crc;
- public final byte bytes[];
-
- public final boolean propertyBits[];
- public final boolean ancillary, isPrivate, reserved, safeToCopy;
-
- public PNGChunk(int Length, int ChunkType, int CRC, byte bytes[])
- {
- this.length = Length;
- this.chunkType = ChunkType;
- this.crc = CRC;
- this.bytes = bytes;
-
- propertyBits = new boolean[4];
- int shift = 24;
- for (int i = 0; i < 4; i++)
- {
- int theByte = 0xff & (ChunkType >> shift);
- shift -= 8;
- int theMask = 1 << 5;
- propertyBits[i] = ((theByte & theMask) > 0);
- }
-
- ancillary = propertyBits[0];
- isPrivate = propertyBits[1];
- reserved = propertyBits[2];
- safeToCopy = propertyBits[3];
- }
-
- protected ByteArrayInputStream getDataStream()
- {
- ByteArrayInputStream is = new ByteArrayInputStream(bytes);
- return is;
- }
+ public final int length;
+ public final int chunkType;
+ public final int crc;
+ public final byte bytes[];
+
+ public final boolean propertyBits[];
+ public final boolean ancillary, isPrivate, reserved, safeToCopy;
+
+ public PNGChunk(int Length, int ChunkType, int CRC, byte bytes[])
+ {
+ this.length = Length;
+ this.chunkType = ChunkType;
+ this.crc = CRC;
+ this.bytes = bytes;
+
+ propertyBits = new boolean[4];
+ int shift = 24;
+ for (int i = 0; i < 4; i++)
+ {
+ int theByte = 0xff & (ChunkType >> shift);
+ shift -= 8;
+ int theMask = 1 << 5;
+ propertyBits[i] = ((theByte & theMask) > 0);
+ }
+
+ ancillary = propertyBits[0];
+ isPrivate = propertyBits[1];
+ reserved = propertyBits[2];
+ safeToCopy = propertyBits[3];
+ }
+
+ protected ByteArrayInputStream getDataStream()
+ {
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ return is;
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIDAT.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIDAT.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIDAT.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIDAT.java Fri Sep 10 16:33:35 2010
@@ -20,9 +20,9 @@ import java.io.IOException;
public class PNGChunkIDAT extends PNGChunk
{
- public PNGChunkIDAT(int Length, int ChunkType, int CRC, byte bytes[])
- throws IOException
- {
- super(Length, ChunkType, CRC, bytes);
- }
+ public PNGChunkIDAT(int Length, int ChunkType, int CRC, byte bytes[])
+ throws IOException
+ {
+ super(Length, ChunkType, CRC, bytes);
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIHDR.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIHDR.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIHDR.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkIHDR.java Fri Sep 10 16:33:35 2010
@@ -23,31 +23,31 @@ import org.apache.sanselan.ImageReadExce
public class PNGChunkIHDR extends PNGChunk
{
- public final int width;
- public final int height;
- public final int bitDepth;
- public final int colorType;
- public final int compressionMethod;
- public final int filterMethod;
- public final int interlaceMethod;
+ public final int width;
+ public final int height;
+ public final int bitDepth;
+ public final int colorType;
+ public final int compressionMethod;
+ public final int filterMethod;
+ public final int interlaceMethod;
- public PNGChunkIHDR(int Length, int ChunkType, int CRC, byte bytes[])
- throws ImageReadException, IOException
- {
- super(Length, ChunkType, CRC, bytes);
+ public PNGChunkIHDR(int Length, int ChunkType, int CRC, byte bytes[])
+ throws ImageReadException, IOException
+ {
+ super(Length, ChunkType, CRC, bytes);
- ByteArrayInputStream is = new ByteArrayInputStream(bytes);
- width = read4Bytes("Width", is, "Not a Valid Png File: IHDR Corrupt");
- height = read4Bytes("Height", is, "Not a Valid Png File: IHDR Corrupt");
- bitDepth = readByte("BitDepth", is,
- "Not a Valid Png File: IHDR Corrupt");
- colorType = readByte("ColorType", is,
- "Not a Valid Png File: IHDR Corrupt");
- compressionMethod = readByte("CompressionMethod", is,
- "Not a Valid Png File: IHDR Corrupt");
- filterMethod = readByte("FilterMethod", is,
- "Not a Valid Png File: IHDR Corrupt");
- interlaceMethod = readByte("InterlaceMethod", is,
- "Not a Valid Png File: IHDR Corrupt");
- }
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ width = read4Bytes("Width", is, "Not a Valid Png File: IHDR Corrupt");
+ height = read4Bytes("Height", is, "Not a Valid Png File: IHDR Corrupt");
+ bitDepth = readByte("BitDepth", is,
+ "Not a Valid Png File: IHDR Corrupt");
+ colorType = readByte("ColorType", is,
+ "Not a Valid Png File: IHDR Corrupt");
+ compressionMethod = readByte("CompressionMethod", is,
+ "Not a Valid Png File: IHDR Corrupt");
+ filterMethod = readByte("FilterMethod", is,
+ "Not a Valid Png File: IHDR Corrupt");
+ interlaceMethod = readByte("InterlaceMethod", is,
+ "Not a Valid Png File: IHDR Corrupt");
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkPLTE.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkPLTE.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkPLTE.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkPLTE.java Fri Sep 10 16:33:35 2010
@@ -24,58 +24,58 @@ import org.apache.sanselan.formats.png.G
public class PNGChunkPLTE extends PNGChunk
{
- public final int rgb[];
+ public final int rgb[];
- public PNGChunkPLTE(int length, int ChunkType, int CRC, byte bytes[])
- throws ImageReadException, IOException
- {
- super(length, ChunkType, CRC, bytes);
-
- ByteArrayInputStream is = new ByteArrayInputStream(bytes);
-
- if ((length % 3) != 0)
- throw new ImageReadException("PLTE: wrong length: " + length);
-
- int count = length / 3;
-
- rgb = new int[count];
-
- for (int i = 0; i < count; i++)
- {
- int red = readByte("red[" + i + "]", is,
- "Not a Valid Png File: PLTE Corrupt");
- int green = readByte("green[" + i + "]", is,
- "Not a Valid Png File: PLTE Corrupt");
- int blue = readByte("blue[" + i + "]", is,
- "Not a Valid Png File: PLTE Corrupt");
- rgb[i] = 0xff000000 | ((0xff & red) << 16) | ((0xff & green) << 8)
- | ((0xff & blue) << 0);
- }
- }
-
- public int getRGB(int index) throws ImageReadException, IOException
- {
- if ((index < 0) || (index >= rgb.length))
- throw new ImageReadException("PNG: unknown Palette reference: "
- + index);
- return rgb[index];
- }
-
- // public void printPalette() {
- // Debug.debug();
- // Debug.debug("palette");
- // for (int i = 0; i < rgb.length; i++) {
- // Debug.debug("\t" + "palette[" + i + "];", rgb[i] + " (0x"
- // + Integer.toHexString(rgb[i]) + ")");
- //
- // }
- // Debug.debug();
- // }
-
- public void correct(GammaCorrection gammaCorrection)
- {
- for (int i = 0; i < rgb.length; i++)
- rgb[i] = gammaCorrection.correctARGB(rgb[i]);
- }
+ public PNGChunkPLTE(int length, int ChunkType, int CRC, byte bytes[])
+ throws ImageReadException, IOException
+ {
+ super(length, ChunkType, CRC, bytes);
+
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+
+ if ((length % 3) != 0)
+ throw new ImageReadException("PLTE: wrong length: " + length);
+
+ int count = length / 3;
+
+ rgb = new int[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ int red = readByte("red[" + i + "]", is,
+ "Not a Valid Png File: PLTE Corrupt");
+ int green = readByte("green[" + i + "]", is,
+ "Not a Valid Png File: PLTE Corrupt");
+ int blue = readByte("blue[" + i + "]", is,
+ "Not a Valid Png File: PLTE Corrupt");
+ rgb[i] = 0xff000000 | ((0xff & red) << 16) | ((0xff & green) << 8)
+ | ((0xff & blue) << 0);
+ }
+ }
+
+ public int getRGB(int index) throws ImageReadException, IOException
+ {
+ if ((index < 0) || (index >= rgb.length))
+ throw new ImageReadException("PNG: unknown Palette reference: "
+ + index);
+ return rgb[index];
+ }
+
+ // public void printPalette() {
+ // Debug.debug();
+ // Debug.debug("palette");
+ // for (int i = 0; i < rgb.length; i++) {
+ // Debug.debug("\t" + "palette[" + i + "];", rgb[i] + " (0x"
+ // + Integer.toHexString(rgb[i]) + ")");
+ //
+ // }
+ // Debug.debug();
+ // }
+
+ public void correct(GammaCorrection gammaCorrection)
+ {
+ for (int i = 0; i < rgb.length; i++)
+ rgb[i] = gammaCorrection.correctARGB(rgb[i]);
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkgAMA.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkgAMA.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkgAMA.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkgAMA.java Fri Sep 10 16:33:35 2010
@@ -23,20 +23,20 @@ import org.apache.sanselan.ImageReadExce
public class PNGChunkgAMA extends PNGChunk
{
- public final int Gamma;
+ public final int Gamma;
- public PNGChunkgAMA(int Length, int ChunkType, int CRC, byte bytes[])
- throws ImageReadException, IOException
- {
- super(Length, ChunkType, CRC, bytes);
+ public PNGChunkgAMA(int Length, int ChunkType, int CRC, byte bytes[])
+ throws ImageReadException, IOException
+ {
+ super(Length, ChunkType, CRC, bytes);
- ByteArrayInputStream is = new ByteArrayInputStream(bytes);
- Gamma = read4Bytes("Gamma", is, "Not a Valid Png File: gAMA Corrupt");
- }
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ Gamma = read4Bytes("Gamma", is, "Not a Valid Png File: gAMA Corrupt");
+ }
- public double getGamma()
- {
- return 1.0 / (Gamma / 100000.0);
- }
+ public double getGamma()
+ {
+ return 1.0 / (Gamma / 100000.0);
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiCCP.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiCCP.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiCCP.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiCCP.java Fri Sep 10 16:33:35 2010
@@ -23,57 +23,57 @@ import org.apache.sanselan.common.ZLibUt
public class PNGChunkiCCP extends PNGChunk
{
- // private final PngImageParser parser;
- public final String ProfileName;
- public final int CompressionMethod;
- public final byte CompressedProfile[];
- public final byte UncompressedProfile[];
-
- public PNGChunkiCCP(
- // PngImageParser parser,
- int Length, int ChunkType, int CRC, byte bytes[])
- throws ImageReadException, IOException
- {
- super(Length, ChunkType, CRC, bytes);
- // this.parser = parser;
-
- {
- int index = findNull(bytes);
- if (index < 0)
- throw new ImageReadException("PNGChunkiCCP: No Profile Name");
- byte name_bytes[] = new byte[index];
- System.arraycopy(bytes, 0, name_bytes, 0, index);
- ProfileName = new String(name_bytes);
-
- CompressionMethod = bytes[index + 1];
-
- int CompressedProfileLength = bytes.length - (index + 1 + 1);
- CompressedProfile = new byte[CompressedProfileLength];
- System.arraycopy(bytes, index + 1 + 1, CompressedProfile, 0,
- CompressedProfileLength);
-
- if (getDebug())
- {
- System.out.println("ProfileName: " + ProfileName);
- System.out.println("ProfileName.length(): "
- + ProfileName.length());
- System.out.println("CompressionMethod: " + CompressionMethod);
- System.out.println("CompressedProfileLength: "
- + CompressedProfileLength);
- System.out.println("bytes.length: " + bytes.length);
- }
-
- UncompressedProfile = new ZLibUtils()
- .inflate(CompressedProfile);
-
- if (getDebug())
- {
- System.out.println("UncompressedProfile: "
- + ((UncompressedProfile == null) ? "null" : ""
- + bytes.length));
- }
+ // private final PngImageParser parser;
+ public final String ProfileName;
+ public final int CompressionMethod;
+ public final byte CompressedProfile[];
+ public final byte UncompressedProfile[];
+
+ public PNGChunkiCCP(
+ // PngImageParser parser,
+ int Length, int ChunkType, int CRC, byte bytes[])
+ throws ImageReadException, IOException
+ {
+ super(Length, ChunkType, CRC, bytes);
+ // this.parser = parser;
+
+ {
+ int index = findNull(bytes);
+ if (index < 0)
+ throw new ImageReadException("PNGChunkiCCP: No Profile Name");
+ byte name_bytes[] = new byte[index];
+ System.arraycopy(bytes, 0, name_bytes, 0, index);
+ ProfileName = new String(name_bytes);
+
+ CompressionMethod = bytes[index + 1];
+
+ int CompressedProfileLength = bytes.length - (index + 1 + 1);
+ CompressedProfile = new byte[CompressedProfileLength];
+ System.arraycopy(bytes, index + 1 + 1, CompressedProfile, 0,
+ CompressedProfileLength);
+
+ if (getDebug())
+ {
+ System.out.println("ProfileName: " + ProfileName);
+ System.out.println("ProfileName.length(): "
+ + ProfileName.length());
+ System.out.println("CompressionMethod: " + CompressionMethod);
+ System.out.println("CompressedProfileLength: "
+ + CompressedProfileLength);
+ System.out.println("bytes.length: " + bytes.length);
+ }
+
+ UncompressedProfile = new ZLibUtils()
+ .inflate(CompressedProfile);
+
+ if (getDebug())
+ {
+ System.out.println("UncompressedProfile: "
+ + ((UncompressedProfile == null) ? "null" : ""
+ + bytes.length));
+ }
- }
- }
+ }
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiTXt.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiTXt.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiTXt.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkiTXt.java Fri Sep 10 16:33:35 2010
@@ -25,105 +25,105 @@ import org.apache.sanselan.formats.png.P
public class PNGChunkiTXt extends PNGTextChunk
{
- public final String keyword, text;
+ public final String keyword, text;
- /*
- * The language tag defined in [RFC-3066] indicates the human language used
- * by the translated keyword and the text. Unlike the keyword, the language
- * tag is case-insensitive. It is an ISO 646.IRV:1991 [ISO 646] string
- * consisting of hyphen-separated words of 1-8 alphanumeric characters each
- * (for example cn, en-uk, no-bok, x-klingon, x-KlInGoN). If the first word
- * is two or three letters long, it is an ISO language code [ISO-639]. If
- * the language tag is empty, the language is unspecified.
- */
- public final String languageTag;
-
- public final String translatedKeyword;
-
- public PNGChunkiTXt(int length, int chunkType, int crc, byte bytes[])
- throws ImageReadException, IOException
- {
- super(length, chunkType, crc, bytes);
- {
- int terminator = findNull(bytes);
- if (terminator < 0)
- throw new ImageReadException(
- "PNG iTXt chunk keyword is not terminated.");
-
- keyword = new String(bytes, 0, terminator, "ISO-8859-1");
- int index = terminator + 1;
-
- int compressionFlag = bytes[index++];
- if (compressionFlag != 0 && compressionFlag != 1)
- throw new ImageReadException(
- "PNG iTXt chunk has invalid compression flag: "
- + compressionFlag);
-
- boolean compressed = compressionFlag == 1;
-
- int compressionMethod = bytes[index++];
- if (compressed)
- if (compressionMethod != PngConstants.COMPRESSION_DEFLATE_INFLATE)
- throw new ImageReadException(
- "PNG iTXt chunk has unexpected compression method: "
- + compressionMethod);
- else if (compressionMethod != 0)
- throw new ImageReadException(
- "PNG iTXt chunk has unexpected compression method: "
- + compressionMethod);
-
- terminator = findNull(bytes, index);
- if (terminator < 0)
- throw new ImageReadException(
- "PNG iTXt chunk language tag is not terminated.");
-
- languageTag = new String(bytes, index, terminator - index,
- "ISO-8859-1");
- index = terminator + 1;
-
- terminator = findNull(bytes, index);
- if (terminator < 0)
- throw new ImageReadException(
- "PNG iTXt chunk translated keyword is not terminated.");
-
- translatedKeyword = new String(bytes, index, terminator - index,
- "utf-8");
- index = terminator + 1;
-
- if (compressed)
- {
- int compressedTextLength = bytes.length - index;
-
- byte compressedText[] = new byte[compressedTextLength];
- System.arraycopy(bytes, index, compressedText, 0,
- compressedTextLength);
-
- text = new String(new ZLibUtils().inflate(compressedText),
- "utf-8");
-
- } else
- text = new String(bytes, index, bytes.length - index, "utf-8");
- }
- }
-
- /**
- * @return Returns the keyword.
- */
- public String getKeyword()
- {
- return keyword;
- }
-
- /**
- * @return Returns the text.
- */
- public String getText()
- {
- return text;
- }
-
- public PngText getContents()
- {
- return new PngText.iTXt(keyword, text, languageTag, translatedKeyword);
- }
+ /*
+ * The language tag defined in [RFC-3066] indicates the human language used
+ * by the translated keyword and the text. Unlike the keyword, the language
+ * tag is case-insensitive. It is an ISO 646.IRV:1991 [ISO 646] string
+ * consisting of hyphen-separated words of 1-8 alphanumeric characters each
+ * (for example cn, en-uk, no-bok, x-klingon, x-KlInGoN). If the first word
+ * is two or three letters long, it is an ISO language code [ISO-639]. If
+ * the language tag is empty, the language is unspecified.
+ */
+ public final String languageTag;
+
+ public final String translatedKeyword;
+
+ public PNGChunkiTXt(int length, int chunkType, int crc, byte bytes[])
+ throws ImageReadException, IOException
+ {
+ super(length, chunkType, crc, bytes);
+ {
+ int terminator = findNull(bytes);
+ if (terminator < 0)
+ throw new ImageReadException(
+ "PNG iTXt chunk keyword is not terminated.");
+
+ keyword = new String(bytes, 0, terminator, "ISO-8859-1");
+ int index = terminator + 1;
+
+ int compressionFlag = bytes[index++];
+ if (compressionFlag != 0 && compressionFlag != 1)
+ throw new ImageReadException(
+ "PNG iTXt chunk has invalid compression flag: "
+ + compressionFlag);
+
+ boolean compressed = compressionFlag == 1;
+
+ int compressionMethod = bytes[index++];
+ if (compressed)
+ if (compressionMethod != PngConstants.COMPRESSION_DEFLATE_INFLATE)
+ throw new ImageReadException(
+ "PNG iTXt chunk has unexpected compression method: "
+ + compressionMethod);
+ else if (compressionMethod != 0)
+ throw new ImageReadException(
+ "PNG iTXt chunk has unexpected compression method: "
+ + compressionMethod);
+
+ terminator = findNull(bytes, index);
+ if (terminator < 0)
+ throw new ImageReadException(
+ "PNG iTXt chunk language tag is not terminated.");
+
+ languageTag = new String(bytes, index, terminator - index,
+ "ISO-8859-1");
+ index = terminator + 1;
+
+ terminator = findNull(bytes, index);
+ if (terminator < 0)
+ throw new ImageReadException(
+ "PNG iTXt chunk translated keyword is not terminated.");
+
+ translatedKeyword = new String(bytes, index, terminator - index,
+ "utf-8");
+ index = terminator + 1;
+
+ if (compressed)
+ {
+ int compressedTextLength = bytes.length - index;
+
+ byte compressedText[] = new byte[compressedTextLength];
+ System.arraycopy(bytes, index, compressedText, 0,
+ compressedTextLength);
+
+ text = new String(new ZLibUtils().inflate(compressedText),
+ "utf-8");
+
+ } else
+ text = new String(bytes, index, bytes.length - index, "utf-8");
+ }
+ }
+
+ /**
+ * @return Returns the keyword.
+ */
+ public String getKeyword()
+ {
+ return keyword;
+ }
+
+ /**
+ * @return Returns the text.
+ */
+ public String getText()
+ {
+ return text;
+ }
+
+ public PngText getContents()
+ {
+ return new PngText.iTXt(keyword, text, languageTag, translatedKeyword);
+ }
}
\ No newline at end of file
Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkpHYs.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkpHYs.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkpHYs.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/chunks/PNGChunkpHYs.java Fri Sep 10 16:33:35 2010
@@ -23,23 +23,23 @@ import org.apache.sanselan.ImageReadExce
public class PNGChunkpHYs extends PNGChunk
{
- public final int PixelsPerUnitXAxis;
- public final int PixelsPerUnitYAxis;
- public final int UnitSpecifier;
+ public final int PixelsPerUnitXAxis;
+ public final int PixelsPerUnitYAxis;
+ public final int UnitSpecifier;
- public PNGChunkpHYs(int Length, int ChunkType, int CRC, byte bytes[])
- throws ImageReadException, IOException
- {
- super(Length, ChunkType, CRC, bytes);
+ public PNGChunkpHYs(int Length, int ChunkType, int CRC, byte bytes[])
+ throws ImageReadException, IOException
+ {
+ super(Length, ChunkType, CRC, bytes);
- ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
- PixelsPerUnitXAxis = read4Bytes("PixelsPerUnitXAxis", is,
- "Not a Valid Png File: pHYs Corrupt");
- PixelsPerUnitYAxis = read4Bytes("PixelsPerUnitYAxis", is,
- "Not a Valid Png File: pHYs Corrupt");
- UnitSpecifier = readByte("Unit specifier", is,
- "Not a Valid Png File: pHYs Corrupt");
- }
+ PixelsPerUnitXAxis = read4Bytes("PixelsPerUnitXAxis", is,
+ "Not a Valid Png File: pHYs Corrupt");
+ PixelsPerUnitYAxis = read4Bytes("PixelsPerUnitYAxis", is,
+ "Not a Valid Png File: pHYs Corrupt");
+ UnitSpecifier = readByte("Unit specifier", is,
+ "Not a Valid Png File: pHYs Corrupt");
+ }
}
\ No newline at end of file