Skip to content

Commit

Permalink
Merge pull request #256 from simboss/9.x-up
Browse files Browse the repository at this point in the history
 	GEOT-4540, Error rendering very simple transparent 8 bit PNG images
  • Loading branch information
Simone Giannecchini committed Aug 23, 2013
2 parents b6b04eb + b0e0aef commit 97826a5
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 73 deletions.
Expand Up @@ -54,6 +54,7 @@
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageOutputStreamSpi;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
Expand Down Expand Up @@ -2717,23 +2718,36 @@ public final void writePNG(final Object destination, final String compression,
}

// let me check if the native writer can encode this image (paranoiac checks this was already performed by the ImageIO search
if(!originatingProvider.canEncodeImage(new ImageTypeSpecifier(image))){
LOGGER.fine("The following encoder cannot encode this image: "+originatingProvider.getClass().getCanonicalName());

// kk, last resort reformat the image
forceComponentColorModel(true, true);
rescaleToBytes();
if(!originatingProvider.canEncodeImage(image)){
LOGGER.severe("Unable to find a valid PNG Encoder!");
}
}
if(originatingProvider.canEncodeImage(new ImageTypeSpecifier(image))){
break; // leave loop
}

// clean
writer=null;
originatingProvider=null;
}
}

// do we have a writer?
// ok, last resort use the JDK one and reformat the image
if(writer==null){
throw new IllegalStateException("Unable to find a valid PNG Encoder!");
}
List providers = com.sun.media.imageioimpl.common.ImageUtil.getJDKImageReaderWriterSPI(
IIORegistry.getDefaultInstance(),
"PNG",
false);
if(providers==null||providers.isEmpty()){
throw new IllegalStateException("Unable to find JDK Png encoder!");
}
originatingProvider=(ImageWriterSpi) providers.get(0);
writer=originatingProvider.createWriterInstance();

// kk, last resort reformat the image
forceComponentColorModel(true, true);
rescaleToBytes();
if(!originatingProvider.canEncodeImage(image)){
throw new IllegalArgumentException("Unable to find a valid PNG Encoder! And believe me, we tried hard!");
}
}

LOGGER.fine("Using ImageIO Writer with SPI: "+originatingProvider.getClass().getCanonicalName());

// Getting a stream.
Expand Down Expand Up @@ -2768,22 +2782,22 @@ public final void writePNG(final Object destination, final String compression,
}
LOGGER.fine("About to write png image");
try{
writer.setOutput(memOutStream);
writer.write(null, new IIOImage(image, null, null), iwp);
writer.setOutput(memOutStream);
writer.write(null, new IIOImage(image, null, null), iwp);
}
finally{
try{
writer.dispose();
}catch (Throwable e) {
if(LOGGER.isLoggable(Level.FINEST))
LOGGER.log(Level.FINEST,e.getLocalizedMessage(),e);
}
try{
memOutStream.close();
}catch (Throwable e) {
if(LOGGER.isLoggable(Level.FINEST))
LOGGER.log(Level.FINEST,e.getLocalizedMessage(),e);
}
try{
writer.dispose();
}catch (Throwable e) {
if(LOGGER.isLoggable(Level.FINEST))
LOGGER.log(Level.FINEST,e.getLocalizedMessage(),e);
}
try{
memOutStream.close();
}catch (Throwable e) {
if(LOGGER.isLoggable(Level.FINEST))
LOGGER.log(Level.FINEST,e.getLocalizedMessage(),e);
}


}
Expand Down
Expand Up @@ -439,39 +439,69 @@ public void testPNGWrite() throws IOException {
assertTrue(readWorker.getRenderedImage().getColorModel() instanceof IndexColorModel);
}

@Test
public void test16BitPNG() throws Exception {
// the resource has been compressed since the palette is way larger than the image itself,
// and the palette does not get compressed
InputStream gzippedStream = ImageWorkerTest.class.getResource("test-data/sf-sfdem.tif.gz").openStream();
GZIPInputStream is = new GZIPInputStream(gzippedStream);
try {
ImageInputStream iis = ImageIO.createImageInputStream(is);
ImageReader reader = new TIFFImageReaderSpi().createReaderInstance(iis);
reader.setInput(iis);
BufferedImage bi = reader.read(0);
IndexColorModel icm = (IndexColorModel) bi.getColorModel();
assertEquals(65536, icm.getMapSize());

final File outFile = TestData.temp(this, "temp.png");
ImageWorker worker = new ImageWorker(bi);
worker.writePNG(outFile, "FILTERED", 0.75f, true, false);
worker.dispose();

// make sure we can read it
BufferedImage back = ImageIO.read(outFile);

// we expect a RGB one
ComponentColorModel ccm = (ComponentColorModel) back.getColorModel();
assertEquals(3, ccm.getNumColorComponents());
} finally {
is.close();
}
}

@Test
public void test4BitPNG() throws Exception {

// create test image
IndexColorModel icm =new IndexColorModel(
4,
16,
new byte[]{(byte)255,0, 0, 0,16,32,64,(byte)128,1,2,3,4,5,6,7,8},
new byte[]{0, (byte)255,0, 0,16,32,64,(byte)128,1,2,3,4,5,6,7,8},
new byte[]{0, 0, (byte)255,0,16,32,64,(byte)128,1,2,3,4,5,6,7,8});
4,
16,
new byte[]{(byte)255,0, 0, 0,16,32,64,(byte)128,1,2,3,4,5,6,7,8},
new byte[]{0, (byte)255,0, 0,16,32,64,(byte)128,1,2,3,4,5,6,7,8},
new byte[]{0, 0, (byte)255,0,16,32,64,(byte)128,1,2,3,4,5,6,7,8});
assertEquals(16, icm.getMapSize());

// create random data
WritableRaster data = com.sun.media.jai.codecimpl.util.RasterFactory.createWritableRaster(
icm.createCompatibleSampleModel(32,32),
new Point(0,0));
icm.createCompatibleSampleModel(32,32),
new Point(0,0));
for(int x=data.getMinX();x<data.getMinX()+data.getWidth();x++){
for(int y=data.getMinY();y<data.getMinY()+data.getHeight();y++){
data.setSample(x, y, 0, (x+y)%8);
}
for(int y=data.getMinY();y<data.getMinY()+data.getHeight();y++){
data.setSample(x, y, 0, (x+y)%8);
}
}


final BufferedImage bi = new BufferedImage(
icm,
data,
false,
null);
icm,
data,
false,
null);
assertEquals(16, ((IndexColorModel)bi.getColorModel()).getMapSize());
assertEquals(4, bi.getSampleModel().getSampleSize(0));
bi.setData(data);
if(TestData.isInteractiveTest()){
ImageIOUtilities.visualize(bi,"before");
ImageIOUtilities.visualize(bi,"before");
}

// encode as png
Expand All @@ -489,37 +519,7 @@ public void test4BitPNG() throws Exception {
assertEquals(16, ccm.getMapSize());
assertEquals(4, ccm.getPixelSize());
if(TestData.isInteractiveTest()){
ImageIOUtilities.visualize(back,"after");
}
}

@Test
public void test16BitPNG() throws Exception {
// the resource has been compressed since the palette is way larger than the image itself,
// and the palette does not get compressed
InputStream gzippedStream = ImageWorkerTest.class.getResource("test-data/sf-sfdem.tif.gz").openStream();
GZIPInputStream is = new GZIPInputStream(gzippedStream);
try {
ImageInputStream iis = ImageIO.createImageInputStream(is);
ImageReader reader = new TIFFImageReaderSpi().createReaderInstance(iis);
reader.setInput(iis);
BufferedImage bi = reader.read(0);
IndexColorModel icm = (IndexColorModel) bi.getColorModel();
assertEquals(65536, icm.getMapSize());

final File outFile = TestData.temp(this, "temp.png");
ImageWorker worker = new ImageWorker(bi);
worker.writePNG(outFile, "FILTERED", 0.75f, true, false);
worker.dispose();

// make sure we can read it
BufferedImage back = ImageIO.read(outFile);

// we expect a RGB one
ComponentColorModel ccm = (ComponentColorModel) back.getColorModel();
assertEquals(3, ccm.getNumColorComponents());
} finally {
is.close();
ImageIOUtilities.visualize(back,"after");
}
}

Expand Down

0 comments on commit 97826a5

Please sign in to comment.