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