FULL PRODUCT VERSION : java version "1.6.0", java version "1.5.0_04", java version "1.4.2_05" ADDITIONAL OS VERSION INFORMATION : Linux 2.6.19-1.2288.2.4.fc5, Microsoft Windows 2000 [Version 5.00.2195] A DESCRIPTION OF THE PROBLEM : com.sun.imageio.plugins.pngPNGMetadata#mergeNativeTree incorrectly stores iTXt_compressionFlag values. At line 1406 (iTXt_compressionFlag.add(new Boolean(compressionFlag));), values are added to the iTXt_compressionFlag ArrayList as Boolean objects. If they are later retieved in a call to getNativeTree the objects are cast to Integer, which creates an exception. Other references to iTXt_compressionFlag use Integer, so line 1406 should store the value as an integer. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - a new test.png file, with an iTXt cluster containing the text "<xml></xml>" ACTUAL - java.lang.ClassCastException, see below ERROR MESSAGES/STACK TRACES THAT OCCUR : java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Integer at com.sun.imageio.plugins.png.PNGImageWriter.write_iTXt(PNGImageWriter.java:680) at com.sun.imageio.plugins.png.PNGImageWriter.write(PNGImageWriter.java:1120) at javax.imageio.ImageWriter.write(ImageWriter.java:580) at org.mbari.aosn.moqua.image.Test1.main(Test1.java:56) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- package org.mbari.aosn.moqua.image; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.IIOImage; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.FileImageOutputStream; import javax.imageio.stream.ImageOutputStream; import org.w3c.dom.Node; import com.sun.imageio.plugins.png.PNGImageWriter; import com.sun.imageio.plugins.png.PNGImageWriterSpi; public class Test1 { static public void main(String args[]) { try { File file = new File("test.png"); BufferedImage image = new BufferedImage(128, 128, BufferedImage.TYPE_4BYTE_ABGR_PRE); Graphics2D graph = image.createGraphics(); graph.setPaintMode(); graph.setColor(Color.orange); graph.fillRect(32, 32, 64, 64); graph.dispose(); ImageOutputStream imageOutputStream = new FileImageOutputStream( file); ImageTypeSpecifier imageTypeSpecifier = new ImageTypeSpecifier( image); ImageWriter imageWriter = new PNGImageWriter( new PNGImageWriterSpi()); imageWriter.setOutput(imageOutputStream); IIOMetadata metadata = imageWriter.getDefaultImageMetadata( imageTypeSpecifier, null); String formatNames[] = metadata.getMetadataFormatNames(); for (String formatName : formatNames) { IIOMetadataFormat format = metadata .getMetadataFormat(formatName); Node node = metadata.getAsTree(formatName); if (formatName.contains("png")) { IIOMetadataNode iTXt = new IIOMetadataNode("iTXt"); IIOMetadataNode iTXtEntry = new IIOMetadataNode("iTXtEntry"); iTXtEntry.setAttribute("keyword", "XML:com.adobe.xmp"); iTXtEntry.setAttribute("compressionFlag", "false"); iTXtEntry.setAttribute("compressionMethod", "0"); iTXtEntry.setAttribute("languageTag", "en"); iTXtEntry.setAttribute("translatedKeyword", "XML:com.adobe.xmp"); iTXtEntry.setAttribute("text", "<xml></xml>"); iTXt.appendChild(iTXtEntry); node.appendChild(iTXt); metadata.setFromTree(formatName, node); break; } } imageWriter.write(new IIOImage(image, null, metadata)); imageOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : before calling mageWriter.write(new IIOImage(image, null, metadata)); insert the following lines (which resolves this problem and a similar problem involving iTXt_compressionMethod): if(metadata instanceof PNGMetadata){ List iTXt_compressionFlag = ((PNGMetadata)metadata).iTXt_compressionFlag; for(int i = 0; i < iTXt_compressionFlag.size(); ++i){ Object flag = iTXt_compressionFlag.get(i); if(flag instanceof Boolean){ iTXt_compressionFlag.set(i,Integer.valueOf(((Boolean)flag).booleanValue()?1:0)); } } List iTXt_compressionMethod = ((PNGMetadata)metadata).iTXt_compressionMethod; for(int i = 0; i < iTXt_compressionMethod.size(); ++i){ Object method = iTXt_compressionMethod.get(i); if(method instanceof String){ try{ iTXt_compressionMethod.set(i,Integer.valueOf((String)method)); } catch (NumberFormatException NFE) { iTXt_compressionMethod.set(i,Integer.valueOf(0)); } } } }
|