|
Description
|
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,
customer 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. customer );
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. customer .xmp");
iTXtEntry.setAttribute("compressionFlag", "false");
iTXtEntry.setAttribute("compressionMethod", "0");
iTXtEntry.setAttribute("languageTag", "en");
iTXtEntry.setAttribute("translatedKeyword",
"XML:com. customer .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));
}
}
}
}
Posted Date : 2007-04-02 13:33:18.0
|
|
Evaluation
|
The CR 6541476 is about problem with a writing of iTXt chunk
but we read it incorrectly too if this chunk contains
non-ascii data (namely, translatedKeyword and text attributes
may contain UTF8 data).
The main reason of reading failures is the DataInputStream.readUTF()
function usage. This function interprets first two bytes in the
input stream as a string data length and seems to be designed
for de-serialization purposes only.
The idea of fix is to avoid usage of this function and pay attention
to expected data encoding on writing and reading stage.
Another problem is that PNG metadata class uses collections (ArraList,
for example) without specifying the type of stored data. It may lead
to problem like described in this CR. To avoid this, we can specify
data type for each collection.
Posted Date : 2008-10-31 13:31:14.0
|