ASF Bugzilla – Attachment 28931 Details for
Bug 53408
[PATCH] two new image loaders for PNG
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch to replace previous one
commons.patch (text/plain), 66.83 KB, created by
Luis Bernardo
on 2012-06-13 14:51:27 UTC
(
hide
)
Description:
patch to replace previous one
Filename:
MIME Type:
Creator:
Luis Bernardo
Created:
2012-06-13 14:51:27 UTC
Size:
66.83 KB
patch
obsolete
>Index: test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderPNGTestCase.java >=================================================================== >--- test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderPNGTestCase.java (revision 0) >+++ test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderPNGTestCase.java (revision 0) >@@ -0,0 +1,62 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.io.IOException; >+ >+import org.junit.Test; >+ >+import org.apache.xmlgraphics.image.loader.Image; >+import org.apache.xmlgraphics.image.loader.ImageContext; >+import org.apache.xmlgraphics.image.loader.ImageException; >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+import org.apache.xmlgraphics.image.loader.ImageSessionContext; >+import org.apache.xmlgraphics.image.loader.MockImageContext; >+import org.apache.xmlgraphics.image.loader.MockImageSessionContext; >+import org.apache.xmlgraphics.util.MimeConstants; >+ >+import static org.junit.Assert.assertEquals; >+import static org.junit.Assert.assertTrue; >+ >+public class ImageLoaderPNGTestCase { >+ >+ private ImageLoaderPNG ilpng = new ImageLoaderPNG(); >+ >+ @Test >+ public void testGetUsagePenalty() { >+ assertEquals(1000, ilpng.getUsagePenalty()); >+ } >+ >+ @Test >+ public void testLoadImageImageInfoMapImageSessionContext() throws ImageException, IOException { >+ ImageContext context = MockImageContext.newSafeInstance(); >+ ImageSessionContext session = new MockImageSessionContext(context); >+ ImageInfo info = new ImageInfo("basn2c08.png", MimeConstants.MIME_PNG); >+ Image im = ilpng.loadImage(info, null, session); >+ assertTrue(im instanceof ImageRendered); >+ } >+ >+ @Test >+ public void testGetTargetFlavor() { >+ assertEquals(ImageFlavor.RENDERED_IMAGE, ilpng.getTargetFlavor()); >+ } >+ >+} >Index: test/java/org/apache/xmlgraphics/image/loader/impl/PNGFileTestCase.java >=================================================================== >--- test/java/org/apache/xmlgraphics/image/loader/impl/PNGFileTestCase.java (revision 0) >+++ test/java/org/apache/xmlgraphics/image/loader/impl/PNGFileTestCase.java (revision 0) >@@ -0,0 +1,119 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.awt.image.ColorModel; >+import java.awt.image.ComponentColorModel; >+import java.awt.image.IndexColorModel; >+import java.io.IOException; >+ >+import org.junit.Test; >+ >+import org.apache.xmlgraphics.image.loader.ImageContext; >+import org.apache.xmlgraphics.image.loader.ImageException; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+import org.apache.xmlgraphics.image.loader.ImageSessionContext; >+import org.apache.xmlgraphics.image.loader.MockImageContext; >+import org.apache.xmlgraphics.image.loader.MockImageSessionContext; >+import org.apache.xmlgraphics.util.MimeConstants; >+ >+import static org.junit.Assert.assertEquals; >+import static org.junit.Assert.assertTrue; >+import static org.junit.Assert.fail; >+ >+public class PNGFileTestCase implements PNGConstants { >+ >+ @Test >+ public void testColorTypeTwoPNG() throws ImageException, IOException { >+ testColorTypePNG("basn2c08.png", PNG_COLOR_RGB); >+ } >+ >+ @Test >+ public void testColorTypeZeroPNG() throws ImageException, IOException { >+ testColorTypePNG("basn0g08.png", PNG_COLOR_GRAY); >+ } >+ >+ @Test >+ public void testColorTypeSixPNG() throws ImageException, IOException { >+ testColorTypePNG("basn6a08.png", PNG_COLOR_RGB_ALPHA); >+ } >+ >+ @Test >+ public void testColorTypeThreePNG() throws ImageException, IOException { >+ testColorTypePNG("basn3p08.png", PNG_COLOR_PALETTE); >+ } >+ >+ @Test >+ public void testColorTypeFourPNG() throws ImageException, IOException { >+ testColorTypePNG("basn4a08.png", PNG_COLOR_GRAY_ALPHA); >+ } >+ >+ @Test >+ public void testTransparentPNG() throws ImageException, IOException { >+ testColorTypePNG("tbbn3p08.png", PNG_COLOR_PALETTE, true); >+ testColorTypePNG("tbrn2c08.png", PNG_COLOR_RGB, true); >+ } >+ >+ @Test >+ public void testCorruptPNG() { >+ ImageContext context = MockImageContext.newSafeInstance(); >+ ImageSessionContext session = new MockImageSessionContext(context); >+ ImageInfo info = new ImageInfo("corrupt-image.png", MimeConstants.MIME_PNG); >+ ImageLoaderRawPNG ilrpng = new ImageLoaderRawPNG(); >+ try { >+ ImageRawPNG irpng = (ImageRawPNG) ilrpng.loadImage(info, null, session); >+ fail("An exception should have been thrown above"); >+ } catch (Exception e) { >+ // do nothing; this was expected >+ } >+ } >+ >+ private void testColorTypePNG(String imageName, int colorType) throws ImageException, IOException { >+ testColorTypePNG(imageName, colorType, false); >+ } >+ >+ private void testColorTypePNG(String imageName, int colorType, boolean isTransparent) >+ throws ImageException, IOException { >+ ImageContext context = MockImageContext.newSafeInstance(); >+ ImageSessionContext session = new MockImageSessionContext(context); >+ ImageInfo info = new ImageInfo(imageName, MimeConstants.MIME_PNG); >+ ImageLoaderRawPNG ilrpng = new ImageLoaderRawPNG(); >+ ImageRawPNG irpng = (ImageRawPNG) ilrpng.loadImage(info, null, session); >+ ColorModel cm = irpng.getColorModel(); >+ if (colorType == PNG_COLOR_PALETTE) { >+ assertTrue(cm instanceof IndexColorModel); >+ } else { >+ assertTrue(cm instanceof ComponentColorModel); >+ int numComponents = 3; >+ if (colorType == PNG_COLOR_GRAY) { >+ numComponents = 1; >+ } else if (colorType == PNG_COLOR_GRAY_ALPHA) { >+ numComponents = 2; >+ } else if (colorType == PNG_COLOR_RGB_ALPHA) { >+ numComponents = 4; >+ } >+ assertEquals(numComponents, cm.getNumComponents()); >+ } >+ if (isTransparent) { >+ assertTrue(irpng.isTransparent()); >+ } >+ } >+ >+} >Index: test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawPNGTestCase.java >=================================================================== >--- test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawPNGTestCase.java (revision 0) >+++ test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawPNGTestCase.java (revision 0) >@@ -0,0 +1,76 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.io.IOException; >+ >+import org.junit.Test; >+ >+import org.apache.xmlgraphics.image.loader.Image; >+import org.apache.xmlgraphics.image.loader.ImageContext; >+import org.apache.xmlgraphics.image.loader.ImageException; >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+import org.apache.xmlgraphics.image.loader.ImageSessionContext; >+import org.apache.xmlgraphics.image.loader.MockImageContext; >+import org.apache.xmlgraphics.image.loader.MockImageSessionContext; >+import org.apache.xmlgraphics.util.MimeConstants; >+ >+import static org.junit.Assert.assertEquals; >+import static org.junit.Assert.assertTrue; >+import static org.junit.Assert.fail; >+ >+public class ImageLoaderRawPNGTestCase { >+ >+ private ImageLoaderRawPNG ilrpng = new ImageLoaderRawPNG(); >+ >+ @Test >+ public void testGetUsagePenalty() { >+ assertEquals(1000, ilrpng.getUsagePenalty()); >+ } >+ >+ @Test >+ public void testLoadImageBadMime() throws ImageException, IOException { >+ ImageContext context = MockImageContext.newSafeInstance(); >+ ImageSessionContext session = new MockImageSessionContext(context); >+ ImageInfo info = new ImageInfo("basn2c08.png", MimeConstants.MIME_JPEG); >+ try { >+ ImageRawPNG irpng = (ImageRawPNG) ilrpng.loadImage(info, null, session); >+ fail("An exception should have been thrown above"); >+ } catch (IllegalArgumentException e) { >+ // do nothing; this was expected >+ } >+ } >+ >+ @Test >+ public void testGetTargetFlavor() { >+ assertEquals(ImageFlavor.RAW_PNG, ilrpng.getTargetFlavor()); >+ } >+ >+ @Test >+ public void testLoadImageGoodMime() throws ImageException, IOException { >+ ImageContext context = MockImageContext.newSafeInstance(); >+ ImageSessionContext session = new MockImageSessionContext(context); >+ ImageInfo info = new ImageInfo("basn2c08.png", MimeConstants.MIME_PNG); >+ Image im = ilrpng.loadImage(info, null, session); >+ assertTrue(im instanceof ImageRawPNG); >+ } >+ >+} >Index: test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryPNGTestCase.java >=================================================================== >--- test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryPNGTestCase.java (revision 0) >+++ test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryPNGTestCase.java (revision 0) >@@ -0,0 +1,64 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import org.junit.Test; >+ >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.spi.ImageLoader; >+import org.apache.xmlgraphics.util.MimeConstants; >+ >+import static org.junit.Assert.assertArrayEquals; >+import static org.junit.Assert.assertTrue; >+import static org.junit.Assert.fail; >+ >+public class ImageLoaderFactoryPNGTestCase { >+ >+ private ImageLoaderFactoryPNG ilfpng = new ImageLoaderFactoryPNG(); >+ >+ @Test >+ public void testGetSupportedMIMETypes() { >+ assertArrayEquals(new String[] {MimeConstants.MIME_PNG}, ilfpng.getSupportedMIMETypes()); >+ } >+ >+ @Test >+ public void testGetSupportedFlavors() { >+ assertArrayEquals(new ImageFlavor[] {ImageFlavor.RENDERED_IMAGE}, >+ ilfpng.getSupportedFlavors(MimeConstants.MIME_PNG)); >+ try { >+ ilfpng.getSupportedFlavors(MimeConstants.MIME_JPEG); >+ fail("An exception should have been thrown above...."); >+ } catch (IllegalArgumentException e) { >+ // do nothing; this is expected >+ } >+ } >+ >+ @Test >+ public void testNewImageLoader() { >+ ImageLoader il = ilfpng.newImageLoader(ImageFlavor.RENDERED_IMAGE); >+ assertTrue(il instanceof ImageLoaderPNG); >+ } >+ >+ @Test >+ public void testIsAvailable() { >+ assertTrue(ilfpng.isAvailable()); >+ } >+ >+} >Index: test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java >=================================================================== >--- test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java (revision 1349255) >+++ test/java/org/apache/xmlgraphics/image/loader/ImageLoaderTestCase.java (working copy) >@@ -34,6 +34,9 @@ > import junit.framework.TestCase; > > import org.apache.commons.io.IOUtils; >+ >+import org.apache.xmlgraphics.image.loader.impl.ImageLoaderPNG; >+import org.apache.xmlgraphics.image.loader.impl.ImageLoaderRawPNG; > import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; > import org.apache.xmlgraphics.image.loader.impl.ImageRendered; > import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry; >@@ -186,11 +189,15 @@ > String mime, ImageFlavor rawFlavor) throws Exception { > ImageLoaderFactory ilfs[] = ImageImplRegistry.getDefaultInstance() > .getImageLoaderFactories(mime); >- if (ilfs != null) >+ if (ilfs != null) { > for (int i = 0; i < ilfs.length; i++) { > ImageLoaderFactory ilf = ilfs[i]; > try { > final ImageLoader il = ilf.newImageLoader(rawFlavor); >+ if (il instanceof ImageLoaderRawPNG || il instanceof ImageLoaderPNG) { >+ // temporary measure until ImageLoaderRawPNG and ImageLoader PNG handle ICC profiles >+ continue; >+ } > final ImageInfo im = new ImageInfo(uri, mime); > final Image img = il.loadImage(im, isc); > final ICC_Profile icc = img.getICCProfile(); >@@ -203,8 +210,7 @@ > // Ignore. This imageLoader does not support RAW > } > try { >- final ImageLoader il = ilf >- .newImageLoader(ImageFlavor.BUFFERED_IMAGE); >+ final ImageLoader il = ilf.newImageLoader(ImageFlavor.BUFFERED_IMAGE); > final ImageInfo im = new ImageInfo(uri, mime); > final Image img = il.loadImage(im, isc); > final ICC_Profile icc = img.getICCProfile(); >@@ -213,6 +219,7 @@ > // Ignore. This imageLoader does not support Buffered. > } > } >+ } > } > > public void testBrokenIccPng() throws Exception { >Index: test/java/org/apache/xmlgraphics/java2d/ps/PSGraphics2DTestCase.java >=================================================================== >--- test/java/org/apache/xmlgraphics/java2d/ps/PSGraphics2DTestCase.java (revision 1349255) >+++ test/java/org/apache/xmlgraphics/java2d/ps/PSGraphics2DTestCase.java (working copy) >@@ -1,6 +1,5 @@ > /* > * Licensed to the Apache Software Foundation (ASF) under one or more >- > * contributor license agreements. See the NOTICE file distributed with > * this work for additional information regarding copyright ownership. > * The ASF licenses this file to You under the Apache License, Version 2.0 >Index: src/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory >=================================================================== >--- src/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory (revision 1349255) >+++ src/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory (working copy) >@@ -2,4 +2,5 @@ > org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryRaw > org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryRawCCITTFax > org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryEPS >-org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryInternalTIFF >\ No newline at end of file >+org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryInternalTIFF >+org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryPNG >\ No newline at end of file >Index: src/java/org/apache/xmlgraphics/ps/PSImageUtils.java >=================================================================== >--- src/java/org/apache/xmlgraphics/ps/PSImageUtils.java (revision 1349255) >+++ src/java/org/apache/xmlgraphics/ps/PSImageUtils.java (working copy) >@@ -143,25 +143,23 @@ > > /** > * Writes a bitmap image to the PostScript stream. >- * @param img the bitmap image as a byte array >+ * @param encoder the image encoder >+ * @param imgDim the dimensions of the image >+ * @param imgDescription the name of the image > * @param targetRect the target rectangle to place the image in >+ * @param colorModel the color model of the image > * @param gen the PostScript generator > * @throws IOException In case of an I/O exception > */ >- private static void writeImage(RenderedImage img, >- Rectangle2D targetRect, PSGenerator gen) throws IOException { >- ImageEncoder encoder = ImageEncodingHelper.createRenderedImageEncoder(img); >- String imgDescription = img.getClass().getName(); >+ public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription, >+ Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen) >+ throws IOException { > > gen.saveGraphicsState(); > translateAndScale(gen, null, targetRect); >- > gen.commentln("%AXGBeginBitmap: " + imgDescription); >- > gen.writeln("{{"); >- // Template: (RawData is used for the EOF signal only) >- // gen.write("/RawData currentfile <first filter> filter def"); >- // gen.write("/Data RawData <second filter> <third filter> [...] def"); >+ > String implicitFilter = encoder.getImplicitFilter(); > if (implicitFilter != null) { > gen.writeln("/RawData currentfile /ASCII85Decode filter def"); >@@ -175,11 +173,15 @@ > gen.writeln("/Data RawData /RunLengthDecode filter def"); > } > } >+ > PSDictionary imageDict = new PSDictionary(); > imageDict.put("/DataSource", "Data"); >- writeImageCommand(img, imageDict, gen); > >- /* the following two lines could be enabled if something still goes wrong >+ populateImageDictionary(imgDim, colorModel, imageDict); >+ writeImageCommand(imageDict, colorModel, gen); >+ >+ /* >+ * the following two lines could be enabled if something still goes wrong > * gen.write("Data closefile"); > * gen.write("RawData flushfile"); > */ >@@ -189,43 +191,40 @@ > > compressAndWriteBitmap(encoder, gen); > >- gen.writeln(""); >+ gen.newLine(); > gen.commentln("%AXGEndBitmap"); > gen.restoreGraphicsState(); > } > >- private static ColorModel populateImageDictionary( >- ImageEncodingHelper helper, PSDictionary imageDict) { >- RenderedImage img = helper.getImage(); >- String w = Integer.toString(img.getWidth()); >- String h = Integer.toString(img.getHeight()); >+ private static ColorModel populateImageDictionary(Dimension imgDim, ColorModel colorModel, >+ PSDictionary imageDict) { >+ String w = Integer.toString(imgDim.width); >+ String h = Integer.toString(imgDim.height); > imageDict.put("/ImageType", "1"); > imageDict.put("/Width", w); > imageDict.put("/Height", h); > >- ColorModel cm = helper.getEncodedColorModel(); >- > boolean invertColors = false; >- String decodeArray = getDecodeArray(cm.getNumComponents(), invertColors); >- int bitsPerComp = cm.getComponentSize(0); >+ String decodeArray = getDecodeArray(colorModel.getNumColorComponents(), invertColors); >+ int bitsPerComp = colorModel.getComponentSize(0); > > // Setup scanning for left-to-right and top-to-bottom > imageDict.put("/ImageMatrix", "[" + w + " 0 0 " + h + " 0 0]"); > >- if ((cm instanceof IndexColorModel)) { >- IndexColorModel im = (IndexColorModel)cm; >- int c = im.getMapSize(); >+ if ((colorModel instanceof IndexColorModel)) { >+ IndexColorModel indexColorModel = (IndexColorModel) colorModel; >+ int c = indexColorModel.getMapSize(); > int hival = c - 1; > if (hival > 4095) { > throw new UnsupportedOperationException("hival must not go beyond 4095"); > } >- bitsPerComp = im.getPixelSize(); >- int ceiling = ((int)Math.pow(2, bitsPerComp)) - 1; >+ bitsPerComp = indexColorModel.getPixelSize(); >+ int ceiling = ((int) Math.pow(2, bitsPerComp)) - 1; > decodeArray = "[0 " + ceiling + "]"; > } > imageDict.put("/BitsPerComponent", Integer.toString(bitsPerComp)); > imageDict.put("/Decode", decodeArray); >- return cm; >+ return colorModel; > } > > private static String getDecodeArray(int numComponents, boolean invertColors) { >@@ -288,8 +287,9 @@ > PSDictionary imageDict, PSGenerator gen) throws IOException { > ImageEncodingHelper helper = new ImageEncodingHelper(img, true); > ColorModel cm = helper.getEncodedColorModel(); >- populateImageDictionary(helper, imageDict); >+ Dimension imgDim = new Dimension(img.getWidth(), img.getHeight()); > >+ populateImageDictionary(imgDim, cm, imageDict); > writeImageCommand(imageDict, cm, gen); > } > >@@ -345,7 +345,13 @@ > float x, float y, float w, float h, PSGenerator gen) > throws IOException { > Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h); >- writeImage(img, targetRect, gen); >+ ImageEncoder encoder = ImageEncodingHelper.createRenderedImageEncoder(img); >+ Dimension imgDim = new Dimension(img.getWidth(), img.getHeight()); >+ String imgDescription = img.getClass().getName(); >+ ImageEncodingHelper helper = new ImageEncodingHelper(img); >+ ColorModel cm = helper.getEncodedColorModel(); >+ >+ writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen); > } > > /** >Index: src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java (revision 1349255) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryRaw.java (working copy) >@@ -81,6 +81,8 @@ > public ImageLoader newImageLoader(ImageFlavor targetFlavor) { > if (targetFlavor.equals(ImageFlavor.RAW_JPEG)) { > return new ImageLoaderRawJPEG(); >+ } else if (targetFlavor.equals(ImageFlavor.RAW_PNG)) { >+ return new ImageLoaderRawPNG(); > } else { > return new ImageLoaderRaw(targetFlavor); > } >Index: src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawPNG.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawPNG.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawPNG.java (revision 0) >@@ -0,0 +1,85 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+// Original author: Matthias Reichenbacher >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.io.IOException; >+import java.util.Map; >+ >+import javax.imageio.stream.ImageInputStream; >+import javax.xml.transform.Source; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+ >+import org.apache.xmlgraphics.image.codec.util.ImageInputStreamSeekableStreamAdapter; >+import org.apache.xmlgraphics.image.codec.util.SeekableStream; >+import org.apache.xmlgraphics.image.loader.Image; >+import org.apache.xmlgraphics.image.loader.ImageException; >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+import org.apache.xmlgraphics.image.loader.ImageSessionContext; >+import org.apache.xmlgraphics.image.loader.util.ImageUtil; >+import org.apache.xmlgraphics.util.MimeConstants; >+ >+public class ImageLoaderRawPNG extends AbstractImageLoader { >+ >+ /** logger */ >+ protected static Log log = LogFactory.getLog(ImageLoaderRawPNG.class); >+ >+ /** >+ * Main constructor. >+ */ >+ public ImageLoaderRawPNG() { >+ } >+ >+ /** {@inheritDoc} */ >+ public ImageFlavor getTargetFlavor() { >+ return ImageFlavor.RAW_PNG; >+ } >+ >+ /** {@inheritDoc} */ >+ public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, >+ IOException { >+ if (!MimeConstants.MIME_PNG.equals(info.getMimeType())) { >+ throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: " >+ + MimeConstants.MIME_PNG); >+ } >+ >+ Source src = session.needSource(info.getOriginalURI()); >+ ImageInputStream in = ImageUtil.needImageInputStream(src); >+ // Remove streams as we do things with them at some later time. >+ ImageUtil.removeStreams(src); >+ SeekableStream seekStream = new ImageInputStreamSeekableStreamAdapter(in); >+ PNGFile im = new PNGFile(seekStream); >+ ImageRawPNG irpng = im.getImageRawPNG(info); >+ return irpng; >+ } >+ >+ /** {@inheritDoc} */ >+ public int getUsagePenalty() { >+ // since this image loader does not handle all kinds of PNG images then we add some penalty to it >+ // so that it is not chosen by default; instead, users need to give it a negative penalty in >+ // fop.xconf so that it is used >+ return 1000; >+ } >+ >+} >Index: src/java/org/apache/xmlgraphics/image/loader/impl/PNGConstants.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/PNGConstants.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/PNGConstants.java (revision 0) >@@ -0,0 +1,47 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+public interface PNGConstants { >+ >+ /* >+ * First 8 bytes of any PNG file. >+ */ >+ long PNG_SIGNATURE = 0x89504e470d0a1a0aL; >+ >+ /* >+ * Color types. >+ */ >+ int PNG_COLOR_GRAY = 0; >+ int PNG_COLOR_RGB = 2; >+ int PNG_COLOR_PALETTE = 3; >+ int PNG_COLOR_GRAY_ALPHA = 4; >+ int PNG_COLOR_RGB_ALPHA = 6; >+ >+ /* >+ * Filter types. >+ */ >+ int PNG_FILTER_NONE = 0; >+ int PNG_FILTER_SUB = 1; >+ int PNG_FILTER_UP = 2; >+ int PNG_FILTER_AVERAGE = 3; >+ int PNG_FILTER_PAETH = 4; >+ >+} >Index: src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryPNG.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryPNG.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderFactoryPNG.java (revision 0) >@@ -0,0 +1,59 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.spi.ImageLoader; >+import org.apache.xmlgraphics.util.MimeConstants; >+ >+public class ImageLoaderFactoryPNG extends AbstractImageLoaderFactory { >+ >+ private static final String[] MIMES = new String[] {MimeConstants.MIME_PNG}; >+ >+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {ImageFlavor.RENDERED_IMAGE}; >+ >+ public ImageLoaderFactoryPNG() { >+ // >+ } >+ >+ /** {@inheritDoc} */ >+ public String[] getSupportedMIMETypes() { >+ return MIMES; >+ } >+ >+ /** {@inheritDoc} */ >+ public ImageFlavor[] getSupportedFlavors(String mime) { >+ if (MimeConstants.MIME_PNG.equals(mime)) { >+ return FLAVORS; >+ } >+ throw new IllegalArgumentException("Unsupported MIME type: " + mime); >+ } >+ >+ /** {@inheritDoc} */ >+ public ImageLoader newImageLoader(ImageFlavor targetFlavor) { >+ return new ImageLoaderPNG(); >+ } >+ >+ /** {@inheritDoc} */ >+ public boolean isAvailable() { >+ return true; >+ } >+ >+} >Index: src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderPNG.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderPNG.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderPNG.java (revision 0) >@@ -0,0 +1,75 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.awt.image.RenderedImage; >+import java.io.IOException; >+import java.util.Map; >+ >+import javax.imageio.stream.ImageInputStream; >+import javax.xml.transform.Source; >+ >+import org.apache.xmlgraphics.image.codec.png.PNGDecodeParam; >+import org.apache.xmlgraphics.image.codec.png.PNGImageDecoder; >+import org.apache.xmlgraphics.image.codec.util.ImageInputStreamSeekableStreamAdapter; >+import org.apache.xmlgraphics.image.codec.util.SeekableStream; >+import org.apache.xmlgraphics.image.loader.Image; >+import org.apache.xmlgraphics.image.loader.ImageException; >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+import org.apache.xmlgraphics.image.loader.ImageSessionContext; >+import org.apache.xmlgraphics.image.loader.util.ImageUtil; >+ >+public class ImageLoaderPNG extends AbstractImageLoader { >+ >+ public ImageLoaderPNG() { >+ // >+ } >+ >+ /** {@inheritDoc} */ >+ public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, >+ IOException { >+ >+ Source src = session.needSource(info.getOriginalURI()); >+ ImageInputStream imgStream = ImageUtil.needImageInputStream(src); >+ >+ SeekableStream seekStream = new ImageInputStreamSeekableStreamAdapter(imgStream); >+ >+ PNGImageDecoder decoder = new PNGImageDecoder(seekStream, new PNGDecodeParam()); >+ RenderedImage image = decoder.decodeAsRenderedImage(); >+ >+ // need transparency here? >+ return new ImageRendered(info, image, null); >+ } >+ >+ /** {@inheritDoc} */ >+ public ImageFlavor getTargetFlavor() { >+ return ImageFlavor.RENDERED_IMAGE; >+ } >+ >+ /** {@inheritDoc} */ >+ public int getUsagePenalty() { >+ // since this image loader does not provide any benefits over the default sun.imageio one we add >+ // some penalty to it so that it is not chosen by default; instead users need to give it a negative >+ // penalty in fop.xconf so that it is used; this image loader is mostly for testing purposes for now. >+ return 1000; >+ } >+ >+} >Index: src/java/org/apache/xmlgraphics/image/loader/impl/ImageRawPNG.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/ImageRawPNG.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/ImageRawPNG.java (revision 0) >@@ -0,0 +1,144 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+// Original author: Matthias Reichenbacher >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.awt.Color; >+import java.awt.color.ColorSpace; >+import java.awt.color.ICC_Profile; >+import java.awt.image.ColorModel; >+import java.io.InputStream; >+ >+import org.apache.xmlgraphics.image.loader.ImageFlavor; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+ >+public class ImageRawPNG extends ImageRawStream { >+ >+ private ColorModel cm; >+ private ICC_Profile iccProfile; >+ private int bitDepth; >+ private boolean isTransparent; >+ private int grayTransparentAlpha; >+ private int redTransparentAlpha; >+ private int greenTransparentAlpha; >+ private int blueTransparentAlpha; >+ >+ /** >+ * Main constructor. >+ * @param info the image info object >+ * @param in the ImageInputStream with the raw content >+ * @param colorSpace the color space >+ * @param iccProfile an ICC color profile or null if no profile is associated >+ */ >+ public ImageRawPNG(ImageInfo info, InputStream in, ColorModel cm, int bitDepth, ICC_Profile iccProfile) { >+ super(info, ImageFlavor.RAW_PNG, in); >+ this.iccProfile = iccProfile; >+ this.cm = cm; >+ this.bitDepth = bitDepth; >+ } >+ >+ /** >+ * The bit depth of each color channel. >+ * @return the bit depth of one channel (same for all) >+ */ >+ public int getBitDepth() { >+ return bitDepth; >+ } >+ >+ /** >+ * Returns the ICC color profile if one is associated with the PNG image. >+ * @return the ICC color profile or null if there's no profile >+ */ >+ public ICC_Profile getICCProfile() { >+ return this.iccProfile; >+ } >+ >+ /** >+ * Returns the image's color model. >+ * @return the color model >+ */ >+ public ColorModel getColorModel() { >+ return this.cm; >+ } >+ >+ /** >+ * Returns the image's color space. >+ * @return the color space >+ */ >+ public ColorSpace getColorSpace() { >+ return this.cm.getColorSpace(); >+ } >+ >+ /** >+ * Sets the gray transparent pixel value. >+ * @param gray the transparent pixel gray value (0...255) >+ */ >+ protected void setGrayTransparentAlpha(int gray) { >+ this.isTransparent = true; >+ this.grayTransparentAlpha = gray; >+ } >+ >+ /** >+ * Sets the RGB transparent pixel values. >+ * @param red the transparent pixel red value (0...255) >+ * @param green the transparent pixel green value (0...255) >+ * @param blue the transparent pixel blue value (0...255) >+ */ >+ protected void setRGBTransparentAlpha(int red, int green, int blue) { >+ this.isTransparent = true; >+ this.redTransparentAlpha = red; >+ this.greenTransparentAlpha = green; >+ this.blueTransparentAlpha = blue; >+ } >+ >+ /** >+ * Used to flag image as transparent when the image is of pallete type. >+ */ >+ protected void setTransparent() { >+ this.isTransparent = true; >+ } >+ >+ /** >+ * Whether the image is transparent (meaning there is a transparent pixel) >+ * @return true if transparent pixel exists >+ */ >+ public boolean isTransparent() { >+ return this.isTransparent; >+ } >+ >+ /** >+ * The color of the transparent pixel. >+ * @return the color of the transparent pixel. >+ */ >+ public Color getTransparentColor() { >+ Color color = null; >+ if (!this.isTransparent) { >+ return color; >+ } >+ if (cm.getNumColorComponents() == 3) { >+ color = new Color(this.redTransparentAlpha, this.greenTransparentAlpha, this.blueTransparentAlpha); >+ } else { >+ color = new Color(this.grayTransparentAlpha, 0, 0); >+ } >+ return color; >+ } >+ >+} >Index: src/java/org/apache/xmlgraphics/image/loader/impl/PNGFile.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/loader/impl/PNGFile.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/loader/impl/PNGFile.java (revision 0) >@@ -0,0 +1,236 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.loader.impl; >+ >+import java.awt.color.ColorSpace; >+import java.awt.color.ICC_Profile; >+import java.awt.image.ColorModel; >+import java.awt.image.ComponentColorModel; >+import java.awt.image.DataBuffer; >+import java.awt.image.IndexColorModel; >+import java.io.BufferedInputStream; >+import java.io.ByteArrayInputStream; >+import java.io.DataInputStream; >+import java.io.IOException; >+import java.io.InputStream; >+import java.io.SequenceInputStream; >+import java.util.ArrayList; >+import java.util.Collections; >+import java.util.List; >+ >+import org.apache.xmlgraphics.image.codec.png.PNGChunk; >+import org.apache.xmlgraphics.image.codec.util.PropertyUtil; >+import org.apache.xmlgraphics.image.loader.ImageException; >+import org.apache.xmlgraphics.image.loader.ImageInfo; >+ >+/** >+ * Provides methods useful for processing PNG files. >+ */ >+class PNGFile implements PNGConstants { >+ >+ private ColorModel colorModel; >+ private ICC_Profile iccProfile; >+ private int bitDepth; >+ private int colorType; >+ private boolean isTransparent; >+ private int grayTransparentAlpha; >+ private int redTransparentAlpha; >+ private int greenTransparentAlpha; >+ private int blueTransparentAlpha; >+ private List<InputStream> streamVec = new ArrayList<InputStream>(); >+ private int paletteEntries; >+ private byte[] redPalette; >+ private byte[] greenPalette; >+ private byte[] bluePalette; >+ private byte[] alphaPalette; >+ private boolean hasPalette; >+ private boolean hasAlphaPalette = false; >+ >+ public PNGFile(InputStream stream) throws IOException, ImageException { >+ if (!stream.markSupported()) { >+ stream = new BufferedInputStream(stream); >+ } >+ DataInputStream distream = new DataInputStream(stream); >+ long magic = distream.readLong(); >+ if (magic != PNG_SIGNATURE) { >+ String msg = PropertyUtil.getString("PNGImageDecoder0"); >+ throw new ImageException(msg); >+ } >+ // only some chunks are worth parsing in the current implementation >+ do { >+ try { >+ PNGChunk chunk; >+ String chunkType = PNGChunk.getChunkType(distream); >+ if (chunkType.equals(PNGChunk.ChunkType.IHDR.name())) { >+ chunk = PNGChunk.readChunk(distream); >+ parse_IHDR_chunk(chunk); >+ } else if (chunkType.equals(PNGChunk.ChunkType.PLTE.name())) { >+ chunk = PNGChunk.readChunk(distream); >+ parse_PLTE_chunk(chunk); >+ } else if (chunkType.equals(PNGChunk.ChunkType.IDAT.name())) { >+ chunk = PNGChunk.readChunk(distream); >+ streamVec.add(new ByteArrayInputStream(chunk.getData())); >+ } else if (chunkType.equals(PNGChunk.ChunkType.IEND.name())) { >+ // chunk = PNGChunk.readChunk(distream); >+ PNGChunk.skipChunk(distream); >+ break; // fall through to the bottom >+ } else if (chunkType.equals(PNGChunk.ChunkType.tRNS.name())) { >+ chunk = PNGChunk.readChunk(distream); >+ parse_tRNS_chunk(chunk); >+ } else { >+ // chunk = PNGChunk.readChunk(distream); >+ PNGChunk.skipChunk(distream); >+ } >+ } catch (Exception e) { >+ e.printStackTrace(); >+ String msg = PropertyUtil.getString("PNGImageDecoder2"); >+ throw new RuntimeException(msg); >+ } >+ } while (true); >+ } >+ >+ public ImageRawPNG getImageRawPNG(ImageInfo info) throws ImageException { >+ InputStream seqStream = new SequenceInputStream(Collections.enumeration(streamVec)); >+ switch (colorType) { >+ case PNG_COLOR_GRAY: >+ if (hasPalette) { >+ throw new ImageException("Corrupt PNG: color palette is not allowed!"); >+ } >+ colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, >+ ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); >+ break; >+ case PNG_COLOR_RGB: >+ // actually a check of the sRGB chunk would be necessary to confirm if it's really sRGB >+ colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, >+ ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); >+ break; >+ case PNG_COLOR_PALETTE: >+ if (hasAlphaPalette) { >+ colorModel = new IndexColorModel(bitDepth, paletteEntries, redPalette, greenPalette, >+ bluePalette, alphaPalette); >+ } else { >+ colorModel = new IndexColorModel(bitDepth, paletteEntries, redPalette, greenPalette, >+ bluePalette); >+ } >+ break; >+ case PNG_COLOR_GRAY_ALPHA: >+ if (hasPalette) { >+ throw new ImageException("Corrupt PNG: color palette is not allowed!"); >+ } >+ colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, >+ ColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE); >+ break; >+ case PNG_COLOR_RGB_ALPHA: >+ // actually a check of the sRGB chunk would be necessary to confirm if it's really sRGB >+ colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, >+ ColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE); >+ break; >+ default: >+ throw new ImageException("Unsupported color type: " + colorType); >+ } >+ // the iccProfile is still null for now >+ ImageRawPNG rawImage = new ImageRawPNG(info, seqStream, colorModel, bitDepth, iccProfile); >+ if (isTransparent) { >+ if (colorType == PNG_COLOR_GRAY) { >+ rawImage.setGrayTransparentAlpha(grayTransparentAlpha); >+ } else if (colorType == PNG_COLOR_RGB) { >+ rawImage.setRGBTransparentAlpha(redTransparentAlpha, greenTransparentAlpha, >+ blueTransparentAlpha); >+ } else if (colorType == PNG_COLOR_PALETTE) { >+ rawImage.setTransparent(); >+ } else { >+ // >+ } >+ } >+ return rawImage; >+ } >+ >+ private void parse_IHDR_chunk(PNGChunk chunk) { >+ int width = chunk.getInt4(0); >+ int height = chunk.getInt4(4); >+ bitDepth = chunk.getInt1(8); >+ if (bitDepth != 8) { >+ // this is a limitation of the current implementation >+ throw new RuntimeException("Unsupported bit depth: " + bitDepth); >+ } >+ colorType = chunk.getInt1(9); >+ int compressionMethod = chunk.getInt1(10); >+ if (compressionMethod != 0) { >+ throw new RuntimeException("Unsupported PNG compression method: " + compressionMethod); >+ } >+ int filterMethod = chunk.getInt1(11); >+ if (filterMethod != 0) { >+ throw new RuntimeException("Unsupported PNG filter method: " + filterMethod); >+ } >+ int interlaceMethod = chunk.getInt1(12); >+ if (interlaceMethod != 0) { >+ // this is a limitation of the current implementation >+ throw new RuntimeException("Unsupported PNG interlace method: " + interlaceMethod); >+ } >+ } >+ >+ private void parse_PLTE_chunk(PNGChunk chunk) { >+ paletteEntries = chunk.getLength() / 3; >+ redPalette = new byte[paletteEntries]; >+ greenPalette = new byte[paletteEntries]; >+ bluePalette = new byte[paletteEntries]; >+ hasPalette = true; >+ >+ int pltIndex = 0; >+ for (int i = 0; i < paletteEntries; i++) { >+ redPalette[i] = chunk.getByte(pltIndex++); >+ greenPalette[i] = chunk.getByte(pltIndex++); >+ bluePalette[i] = chunk.getByte(pltIndex++); >+ } >+ } >+ >+ private void parse_tRNS_chunk(PNGChunk chunk) { >+ if (colorType == PNG_COLOR_PALETTE) { >+ int entries = chunk.getLength(); >+ if (entries > paletteEntries) { >+ // Error -- mustn't have more alpha than RGB palette entries >+ String msg = PropertyUtil.getString("PNGImageDecoder14"); >+ throw new RuntimeException(msg); >+ } >+ // Load beginning of palette from the chunk >+ alphaPalette = new byte[paletteEntries]; >+ for (int i = 0; i < entries; i++) { >+ alphaPalette[i] = chunk.getByte(i); >+ } >+ // Fill rest of palette with 255 >+ for (int i = entries; i < paletteEntries; i++) { >+ alphaPalette[i] = (byte) 255; >+ } >+ hasAlphaPalette = true; >+ } else if (colorType == PNG_COLOR_GRAY) { >+ grayTransparentAlpha = chunk.getInt2(0); >+ } else if (colorType == PNG_COLOR_RGB) { >+ redTransparentAlpha = chunk.getInt2(0); >+ greenTransparentAlpha = chunk.getInt2(2); >+ blueTransparentAlpha = chunk.getInt2(4); >+ } else if (colorType == PNG_COLOR_GRAY_ALPHA || colorType == PNG_COLOR_RGB_ALPHA) { >+ // Error -- GA or RGBA image can't have a tRNS chunk. >+ String msg = PropertyUtil.getString("PNGImageDecoder15"); >+ throw new RuntimeException(msg); >+ } >+ isTransparent = true; >+ } >+ >+} >Index: src/java/org/apache/xmlgraphics/image/codec/png/PNGImageDecoder.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/codec/png/PNGImageDecoder.java (revision 1349255) >+++ src/java/org/apache/xmlgraphics/image/codec/png/PNGImageDecoder.java (working copy) >@@ -51,6 +51,7 @@ > import org.apache.xmlgraphics.image.codec.util.ImageDecoderImpl; > import org.apache.xmlgraphics.image.codec.util.PropertyUtil; > import org.apache.xmlgraphics.image.codec.util.SimpleRenderedImage; >+import org.apache.xmlgraphics.image.loader.impl.PNGConstants; > > // CSOFF: ConstantName > // CSOFF: InnerAssignment >@@ -80,101 +81,19 @@ > } > } > >-class PNGChunk { >- int length; >- int type; >- byte[] data; >- int crc; >- >- final String typeString; >- >- PNGChunk(int length, int type, byte[] data, int crc) { >- this.length = length; >- this.type = type; >- this.data = data; >- this.crc = crc; >- >- typeString = "" >- + (char)((type >>> 24) & 0xff) >- + (char)((type >>> 16) & 0xff) >- + (char)((type >>> 8) & 0xff) >- + (char)((type ) & 0xff); >- } >- >- public int getLength() { >- return length; >- } >- >- public int getType() { >- return type; >- } >- >- public String getTypeString() { >- return typeString; >- } >- >- public byte[] getData() { >- return data; >- } >- >- public byte getByte(int offset) { >- return data[offset]; >- } >- >- public int getInt1(int offset) { >- return data[offset] & 0xff; >- } >- >- public int getInt2(int offset) { >- return ((data[offset] & 0xff) << 8) | >- (data[offset + 1] & 0xff); >- } >- >- public int getInt4(int offset) { >- return ((data[offset] & 0xff) << 24) | >- ((data[offset + 1] & 0xff) << 16) | >- ((data[offset + 2] & 0xff) << 8) | >- (data[offset + 3] & 0xff); >- } >- >- public String getString4(int offset) { >- return "" >- + (char)data[offset] >- + (char)data[offset + 1] >- + (char)data[offset + 2] >- + (char)data[offset + 3]; >- } >- >- public boolean isType(String typeName) { >- return typeString.equals(typeName); >- } >-} >- > /** > * TO DO: > * > * zTXt chunks > * > */ >-class PNGImage extends SimpleRenderedImage { >- >- public static final int PNG_COLOR_GRAY = 0; >- public static final int PNG_COLOR_RGB = 2; >- public static final int PNG_COLOR_PALETTE = 3; >- public static final int PNG_COLOR_GRAY_ALPHA = 4; >- public static final int PNG_COLOR_RGB_ALPHA = 6; >+class PNGImage extends SimpleRenderedImage implements PNGConstants { > > private static final String[] colorTypeNames = { > "Grayscale", "Error", "Truecolor", "Index", > "Grayscale with alpha", "Error", "Truecolor with alpha" > }; > >- public static final int PNG_FILTER_NONE = 0; >- public static final int PNG_FILTER_SUB = 1; >- public static final int PNG_FILTER_UP = 2; >- public static final int PNG_FILTER_AVERAGE = 3; >- public static final int PNG_FILTER_PAETH = 4; >- > private int[][] bandOffsets = { > null, > { 0 }, // G >@@ -304,7 +223,7 @@ > private static final int POST_ADD_GRAY_TRANS_EXP = > POST_ADD_GRAY_TRANS | POST_EXP_MASK; > >- private List streamVec = new ArrayList(); >+ private List<InputStream> streamVec = new ArrayList<InputStream>(); > private DataInputStream dataStream; > > private int bytesPerPixel; // number of bytes per input pixel >@@ -399,7 +318,7 @@ > > try { > long magic = distream.readLong(); >- if (magic != 0x89504e470d0a1a0aL) { >+ if (magic != PNG_SIGNATURE) { > String msg = PropertyUtil.getString("PNGImageDecoder0"); > throw new RuntimeException(msg); > } >@@ -413,58 +332,58 @@ > try { > PNGChunk chunk; > >- String chunkType = getChunkType(distream); >- if (chunkType.equals("IHDR")) { >- chunk = readChunk(distream); >+ String chunkType = PNGChunk.getChunkType(distream); >+ if (chunkType.equals(PNGChunk.ChunkType.IHDR.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_IHDR_chunk(chunk); >- } else if (chunkType.equals("PLTE")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.PLTE.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_PLTE_chunk(chunk); >- } else if (chunkType.equals("IDAT")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.IDAT.name())) { >+ chunk = PNGChunk.readChunk(distream); > streamVec.add(new ByteArrayInputStream(chunk.getData())); >- } else if (chunkType.equals("IEND")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.IEND.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_IEND_chunk(chunk); > break; // fall through to the bottom >- } else if (chunkType.equals("bKGD")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.bKGD.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_bKGD_chunk(chunk); >- } else if (chunkType.equals("cHRM")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.cHRM.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_cHRM_chunk(chunk); >- } else if (chunkType.equals("gAMA")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.gAMA.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_gAMA_chunk(chunk); >- } else if (chunkType.equals("hIST")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.hIST.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_hIST_chunk(chunk); >- } else if (chunkType.equals("iCCP")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.iCCP.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_iCCP_chunk(chunk); >- } else if (chunkType.equals("pHYs")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.pHYs.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_pHYs_chunk(chunk); >- } else if (chunkType.equals("sBIT")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.sBIT.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_sBIT_chunk(chunk); >- } else if (chunkType.equals("sRGB")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.sRGB.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_sRGB_chunk(chunk); >- } else if (chunkType.equals("tEXt")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.tEXt.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_tEXt_chunk(chunk); >- } else if (chunkType.equals("tIME")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.tIME.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_tIME_chunk(chunk); >- } else if (chunkType.equals("tRNS")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.tRNS.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_tRNS_chunk(chunk); >- } else if (chunkType.equals("zTXt")) { >- chunk = readChunk(distream); >+ } else if (chunkType.equals(PNGChunk.ChunkType.zTXt.name())) { >+ chunk = PNGChunk.readChunk(distream); > parse_zTXt_chunk(chunk); > } else { >- chunk = readChunk(distream); >+ chunk = PNGChunk.readChunk(distream); > // Output the chunk data in raw form > > String type = chunk.getTypeString(); >@@ -498,40 +417,6 @@ > } > } > >- private static String getChunkType(DataInputStream distream) { >- try { >- distream.mark(8); >- /* int length = */ distream.readInt(); >- int type = distream.readInt(); >- distream.reset(); >- >- String typeString = ""; // todo simplify this >- typeString += (char)(type >> 24); >- typeString += (char)((type >> 16) & 0xff); >- typeString += (char)((type >> 8) & 0xff); >- typeString += (char)(type & 0xff); >- return typeString; >- } catch (Exception e) { >- e.printStackTrace(); >- return null; >- } >- } >- >- private static PNGChunk readChunk(DataInputStream distream) { >- try { >- int length = distream.readInt(); >- int type = distream.readInt(); >- byte[] data = new byte[length]; >- distream.readFully(data); >- int crc = distream.readInt(); >- >- return new PNGChunk(length, type, data, crc); >- } catch (Exception e) { >- e.printStackTrace(); >- return null; >- } >- } >- > private void parse_IHDR_chunk(PNGChunk chunk) { > tileWidth = width = chunk.getInt4(0); > tileHeight = height = chunk.getInt4(4); >Index: src/java/org/apache/xmlgraphics/image/codec/png/PNGChunk.java >=================================================================== >--- src/java/org/apache/xmlgraphics/image/codec/png/PNGChunk.java (revision 0) >+++ src/java/org/apache/xmlgraphics/image/codec/png/PNGChunk.java (revision 0) >@@ -0,0 +1,184 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.xmlgraphics.image.codec.png; >+ >+import java.io.DataInputStream; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+ >+public class PNGChunk { >+ int length; >+ int type; >+ byte[] data; >+ int crc; >+ >+ String typeString; >+ >+ /** logger */ >+ protected static Log log = LogFactory.getLog(PNGChunk.class); >+ >+ /** >+ * See http://en.wikipedia.org/wiki/Portable_Network_Graphics for a light explanation; >+ * See http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html for the spec. >+ */ >+ public enum ChunkType { >+ IHDR, // IHDR must be the first chunk >+ PLTE, // PLTE contains the palette >+ IDAT, // IDAT contains the image, which may be split among multiple IDAT chunks >+ IEND, // IEND marks the image end >+ bKGD, // bKGD gives the default background color >+ cHRM, // cHRM gives the chromaticity coordinates >+ gAMA, // gAMA specifies gamma >+ hIST, // hIST can store the histogram >+ iCCP, // iCCP is an ICC color profile >+ iTXt, // iTXt contains UTF-8 text >+ pHYs, // pHYs holds the intended pixel size >+ sBIT, // sBIT (significant bits) indicates the color-accuracy >+ sPLT, // sPLT suggests a palette to use >+ sRGB, // sRGB indicates that the standard sRGB color space is used >+ sTER, // sTER stereo-image indicator chunk for stereoscopic images >+ tEXt, // tEXt can store text that can be represented in ISO/IEC 8859-1 >+ tIME, // tIME stores the time that the image was last changed >+ tRNS, // tRNS contains transparency information >+ zTXt; // zTXt contains compressed text with the same limits as tEXt >+ } >+ >+ public PNGChunk(int length, int type, byte[] data, int crc) { >+ this.length = length; >+ this.type = type; >+ this.data = data; >+ this.crc = crc; >+ this.typeString = typeIntToString(this.type); >+ } >+ >+ public int getLength() { >+ return length; >+ } >+ >+ public int getType() { >+ return type; >+ } >+ >+ public String getTypeString() { >+ return typeString; >+ } >+ >+ public byte[] getData() { >+ return data; >+ } >+ >+ public byte getByte(int offset) { >+ return data[offset]; >+ } >+ >+ public int getInt1(int offset) { >+ return data[offset] & 0xff; >+ } >+ >+ public int getInt2(int offset) { >+ return ((data[offset] & 0xff) << 8) | (data[offset + 1] & 0xff); >+ } >+ >+ public int getInt4(int offset) { >+ return ((data[offset] & 0xff) << 24) | ((data[offset + 1] & 0xff) << 16) >+ | ((data[offset + 2] & 0xff) << 8) | (data[offset + 3] & 0xff); >+ } >+ >+ public String getString4(int offset) { >+ return "" + (char) data[offset] + (char) data[offset + 1] + (char) data[offset + 2] >+ + (char) data[offset + 3]; >+ } >+ >+ public boolean isType(String typeName) { >+ return typeString.equals(typeName); >+ } >+ >+ /** >+ * Reads the next chunk from the input stream. >+ * @param distream the input stream >+ * @return the chunk >+ */ >+ public static PNGChunk readChunk(DataInputStream distream) { >+ try { >+ int length = distream.readInt(); >+ int type = distream.readInt(); >+ byte[] data = new byte[length]; >+ distream.readFully(data); >+ int crc = distream.readInt(); >+ >+ return new PNGChunk(length, type, data, crc); >+ } catch (Exception e) { >+ e.printStackTrace(); >+ return null; >+ } >+ } >+ >+ /** >+ * Returns the PNG chunk type, a four letter case sensitive ASCII type/name. >+ * @param distream the input stream >+ * @return a four letter case sensitive ASCII type/name >+ */ >+ public static String getChunkType(DataInputStream distream) { >+ try { >+ distream.mark(8); >+ /* int length = */distream.readInt(); >+ int type = distream.readInt(); >+ distream.reset(); >+ >+ return typeIntToString(type); >+ } catch (Exception e) { >+ e.printStackTrace(); >+ return null; >+ } >+ } >+ >+ private static String typeIntToString(int type) { >+ String typeString = ""; >+ typeString += (char) (type >> 24); >+ typeString += (char) ((type >> 16) & 0xff); >+ typeString += (char) ((type >> 8) & 0xff); >+ typeString += (char) (type & 0xff); >+ return typeString; >+ } >+ >+ /** >+ * Skips the next chunk from the input stream. >+ * @param distream the input stream >+ * @return true if skipping successful, false otherwise >+ */ >+ public static boolean skipChunk(DataInputStream distream) { >+ try { >+ int length = distream.readInt(); >+ int type = distream.readInt(); >+ // is this really faster than reading? >+ int skipped = distream.skipBytes(length); >+ int crc = distream.readInt(); >+ if (skipped != length) { >+ log.warn("Incorrect number of bytes skipped."); >+ return false; >+ } >+ return true; >+ } catch (Exception e) { >+ log.warn(e.getMessage()); >+ return false; >+ } >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 53408
:
28927
|
28928
| 28931 |
29131