diff options
author | Glenn Adams <gadams@apache.org> | 2012-06-15 02:56:21 +0000 |
---|---|---|
committer | Glenn Adams <gadams@apache.org> | 2012-06-15 02:56:21 +0000 |
commit | 4bba95be2e5bd480bd5adec9e9b1083d5fb9a561 (patch) | |
tree | 3773419600cf68ec5ad7ed7a5d1a32581256949b /test/java/org/apache/fop | |
parent | bb62a7639a02787839f9eec1a3214bdf7fd2d4cc (diff) | |
download | xmlgraphics-fop-4bba95be2e5bd480bd5adec9e9b1083d5fb9a561.tar.gz xmlgraphics-fop-4bba95be2e5bd480bd5adec9e9b1083d5fb9a561.zip |
Bugzilla #40676: Support use of ImageLoaderRawPNG decoder in order to prevent re-encoding of PNG images (and unnecssary output file bloat). Submitted by Luis Bernardo, Matthias Reischenbacher.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1350455 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/java/org/apache/fop')
3 files changed, 367 insertions, 0 deletions
diff --git a/test/java/org/apache/fop/render/RawPNGTestUtil.java b/test/java/org/apache/fop/render/RawPNGTestUtil.java new file mode 100644 index 000000000..e6660bb42 --- /dev/null +++ b/test/java/org/apache/fop/render/RawPNGTestUtil.java @@ -0,0 +1,92 @@ +/* + * 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.fop.render; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +import org.apache.xmlgraphics.image.loader.ImageSize; + +public final class RawPNGTestUtil { + + private static int NUM_ROWS = 32; + private static int NUM_COLUMNS = 32; + private static int DPI = 72; + + private RawPNGTestUtil() { + + } + + /** + * Builds a PNG IDAT section for a square of a given color and alpha; the filter is fixed. + * @param gray the gray color; set to -1 if using RGB + * @param red the red color; ignored if gray > -1 + * @param green the green color; ignored if gray > -1 + * @param blue the blue color; ignored if gray > -1 + * @param alpha the alpha color; set to -1 if not present + * @return the PNG IDAT byte array + * @throws IOException + */ + public static byte[] buildGRGBAData(int gray, int red, int green, int blue, int alpha) throws IOException { + // build an image, 32x32, Gray or RGB, with or without alpha, and with filter + int filter = 0; + int numRows = NUM_ROWS; + int numColumns = NUM_COLUMNS; + int numComponents = (gray > -1 ? 1 : 3) + (alpha > -1 ? 1 : 0); + int numBytesPerRow = numColumns * numComponents + 1; // 1 for filter + int numBytes = numRows * numBytesPerRow; + byte[] data = new byte[numBytes]; + for (int r = 0; r < numRows; r++) { + data[r * numBytesPerRow] = (byte) filter; + for (int c = 0; c < numColumns; c++) { + if (numComponents == 1) { + data[r * numBytesPerRow + numComponents * c + 1] = (byte) gray; + } else if (numComponents == 2) { + data[r * numBytesPerRow + numComponents * c + 1] = (byte) gray; + data[r * numBytesPerRow + numComponents * c + 2] = (byte) alpha; + } else if (numComponents == 3) { + data[r * numBytesPerRow + numComponents * c + 1] = (byte) red; + data[r * numBytesPerRow + numComponents * c + 2] = (byte) green; + data[r * numBytesPerRow + numComponents * c + 3] = (byte) blue; + } else if (numComponents == 4) { + data[r * numBytesPerRow + numComponents * c + 1] = (byte) red; + data[r * numBytesPerRow + numComponents * c + 2] = (byte) green; + data[r * numBytesPerRow + numComponents * c + 3] = (byte) blue; + data[r * numBytesPerRow + numComponents * c + 4] = (byte) alpha; + } + } + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DeflaterOutputStream dos = new DeflaterOutputStream(baos, new Deflater()); + dos.write(data); + dos.close(); + return baos.toByteArray(); + } + + /** + * + * @return a default ImageSize + */ + public static ImageSize getImageSize() { + return new ImageSize(NUM_ROWS, NUM_COLUMNS, DPI); + } +} diff --git a/test/java/org/apache/fop/render/pdf/ImageRawPNGAdapterTestCase.java b/test/java/org/apache/fop/render/pdf/ImageRawPNGAdapterTestCase.java new file mode 100644 index 000000000..885821f66 --- /dev/null +++ b/test/java/org/apache/fop/render/pdf/ImageRawPNGAdapterTestCase.java @@ -0,0 +1,142 @@ +/* + * 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.fop.render.pdf; + +import java.awt.image.ComponentColorModel; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +import org.junit.Test; + +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawPNG; + +import org.apache.fop.pdf.FlateFilter; +import org.apache.fop.pdf.PDFAMode; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFProfile; +import org.apache.fop.render.RawPNGTestUtil; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ImageRawPNGAdapterTestCase { + + @Test + public void testSetupWithIndexColorModel() { + IndexColorModel cm = mock(IndexColorModel.class); + ImageRawPNG irpng = mock(ImageRawPNG.class); + PDFDocument doc = mock(PDFDocument.class); + PDFProfile profile = mock(PDFProfile.class); + ImageRawPNGAdapter irpnga = new ImageRawPNGAdapter(irpng, "mock"); + ImageSize is = RawPNGTestUtil.getImageSize(); + + when(irpng.getColorModel()).thenReturn(cm); + // when(cm.hasAlpha()).thenReturn(false); + when(doc.getProfile()).thenReturn(profile); + when(profile.getPDFAMode()).thenReturn(PDFAMode.PDFA_1A); + when(irpng.getSize()).thenReturn(is); + irpnga.setup(doc); + FlateFilter filter = (FlateFilter) irpnga.getPDFFilter(); + assertEquals(1, filter.getColors()); + } + + @Test + public void testSetupWithComponentColorModel() throws IOException { + ComponentColorModel cm = mock(ComponentColorModel.class); + ImageRawPNG irpng = mock(ImageRawPNG.class); + PDFDocument doc = mock(PDFDocument.class); + PDFProfile profile = mock(PDFProfile.class); + ImageRawPNGAdapter irpnga = new ImageRawPNGAdapter(irpng, "mock"); + ImageSize is = RawPNGTestUtil.getImageSize(); + + when(irpng.getColorModel()).thenReturn(cm); + when(cm.getNumComponents()).thenReturn(3); + // when(cm.hasAlpha()).thenReturn(false); + when(doc.getProfile()).thenReturn(profile); + when(profile.getPDFAMode()).thenReturn(PDFAMode.PDFA_1A); + when(irpng.getSize()).thenReturn(is); + irpnga.setup(doc); + FlateFilter filter = (FlateFilter) irpnga.getPDFFilter(); + assertEquals(3, filter.getColors()); + } + + @Test + public void testOutputContentsWithRGBPNG() throws IOException { + testOutputContentsWithGRGBAPNG(-1, 128, 128, 128, -1); + } + + @Test + public void testOutputContentsWithRGBAPNG() throws IOException { + testOutputContentsWithGRGBAPNG(-1, 128, 128, 128, 128); + } + + @Test + public void testOutputContentsWithGPNG() throws IOException { + testOutputContentsWithGRGBAPNG(128, -1, -1, -1, -1); + } + + @Test + public void testOutputContentsWithGAPNG() throws IOException { + testOutputContentsWithGRGBAPNG(128, -1, -1, -1, 128); + } + + private void testOutputContentsWithGRGBAPNG(int gray, int red, int green, int blue, int alpha) + throws IOException { + int numColorComponents = gray > -1 ? 1 : 3; + int numComponents = numColorComponents + (alpha > -1 ? 1 : 0); + ComponentColorModel cm = mock(ComponentColorModel.class); + ImageRawPNG irpng = mock(ImageRawPNG.class); + PDFDocument doc = mock(PDFDocument.class); + PDFProfile profile = mock(PDFProfile.class); + ImageRawPNGAdapter irpnga = new ImageRawPNGAdapter(irpng, "mock"); + ImageSize is = RawPNGTestUtil.getImageSize(); + + when(irpng.getColorModel()).thenReturn(cm); + when(cm.getNumComponents()).thenReturn(numComponents); + // when(cm.hasAlpha()).thenReturn(false); + when(doc.getProfile()).thenReturn(profile); + when(profile.getPDFAMode()).thenReturn(PDFAMode.PDFA_1A); + when(irpng.getSize()).thenReturn(is); + irpnga.setup(doc); + FlateFilter filter = (FlateFilter) irpnga.getPDFFilter(); + assertEquals(numColorComponents, filter.getColors()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] data = RawPNGTestUtil.buildGRGBAData(gray, red, green, blue, alpha); + ByteArrayInputStream bais = new ByteArrayInputStream(data); + when(irpng.createInputStream()).thenReturn(bais); + irpnga.outputContents(baos); + if (alpha > -1) { + byte[] expected = RawPNGTestUtil.buildGRGBAData(gray, red, green, blue, -1); + assertArrayEquals(expected, baos.toByteArray()); + } else { + assertArrayEquals(data, baos.toByteArray()); + } + } + +} diff --git a/test/java/org/apache/fop/render/ps/ImageEncoderPNGTestCase.java b/test/java/org/apache/fop/render/ps/ImageEncoderPNGTestCase.java new file mode 100644 index 000000000..458033dad --- /dev/null +++ b/test/java/org/apache/fop/render/ps/ImageEncoderPNGTestCase.java @@ -0,0 +1,133 @@ +/* + * 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.fop.render.ps; + +import java.awt.image.ComponentColorModel; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.junit.Test; + +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawPNG; + +import org.apache.fop.render.RawPNGTestUtil; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ImageEncoderPNGTestCase { + + @Test + public void testWriteToWithRGBPNG() throws IOException { + testWriteToWithGRGBAPNG(-1, 128, 128, 128, -1); + } + + @Test + public void testWriteToWithGPNG() throws IOException { + testWriteToWithGRGBAPNG(128, -1, -1, -1, -1); + } + + @Test + public void testWriteToWithRGBAPNG() throws IOException { + testWriteToWithGRGBAPNG(-1, 128, 128, 128, 128); + } + + @Test + public void testWriteToWithGAPNG() throws IOException { + testWriteToWithGRGBAPNG(128, -1, -1, -1, 128); + } + + private void testWriteToWithGRGBAPNG(int gray, int red, int green, int blue, int alpha) + throws IOException { + int numComponents = (gray > -1 ? 1 : 3) + (alpha > -1 ? 1 : 0); + ImageSize is = RawPNGTestUtil.getImageSize(); + ComponentColorModel cm = mock(ComponentColorModel.class); + when(cm.getNumComponents()).thenReturn(numComponents); + ImageRawPNG irpng = mock(ImageRawPNG.class); + when(irpng.getColorModel()).thenReturn(cm); + when(irpng.getSize()).thenReturn(is); + ImageEncoderPNG iepng = new ImageEncoderPNG(irpng); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] data = RawPNGTestUtil.buildGRGBAData(gray, red, green, blue, alpha); + ByteArrayInputStream bais = new ByteArrayInputStream(data); + when(irpng.createInputStream()).thenReturn(bais); + iepng.writeTo(baos); + if (alpha > -1) { + byte[] expected = RawPNGTestUtil.buildGRGBAData(gray, red, green, blue, -1); + assertArrayEquals(expected, baos.toByteArray()); + } else { + assertArrayEquals(data, baos.toByteArray()); + } + } + + @Test + public void testWriteToWithPalettePNG() throws IOException { + ImageSize is = RawPNGTestUtil.getImageSize(); + IndexColorModel cm = mock(IndexColorModel.class); + ImageRawPNG irpng = mock(ImageRawPNG.class); + when(irpng.getColorModel()).thenReturn(cm); + when(irpng.getSize()).thenReturn(is); + ImageEncoderPNG iepng = new ImageEncoderPNG(irpng); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] data = RawPNGTestUtil.buildGRGBAData(128, -1, -1, -1, -1); + ByteArrayInputStream bais = new ByteArrayInputStream(data); + when(irpng.createInputStream()).thenReturn(bais); + iepng.writeTo(baos); + assertArrayEquals(data, baos.toByteArray()); + } + + @Test + public void testGetImplicitFilterWithIndexColorModel() { + ImageSize is = RawPNGTestUtil.getImageSize(); + IndexColorModel cm = mock(IndexColorModel.class); + ImageRawPNG irpng = mock(ImageRawPNG.class); + when(irpng.getColorModel()).thenReturn(cm); + when(irpng.getBitDepth()).thenReturn(8); + when(irpng.getSize()).thenReturn(is); + ImageEncoderPNG iepng = new ImageEncoderPNG(irpng); + + String expectedFilter = "<< /Predictor 15 /Columns 32 /Colors 1 /BitsPerComponent 8 >> /FlateDecode"; + assertEquals(expectedFilter, iepng.getImplicitFilter()); + } + + @Test + public void testGetImplicitFilterWithComponentColorModel() { + ImageSize is = RawPNGTestUtil.getImageSize(); + ComponentColorModel cm = mock(ComponentColorModel.class); + when(cm.getNumComponents()).thenReturn(3); + ImageRawPNG irpng = mock(ImageRawPNG.class); + when(irpng.getColorModel()).thenReturn(cm); + when(irpng.getBitDepth()).thenReturn(8); + when(irpng.getSize()).thenReturn(is); + ImageEncoderPNG iepng = new ImageEncoderPNG(irpng); + + String expectedFilter = "<< /Predictor 15 /Columns 32 /Colors 3 /BitsPerComponent 8 >> /FlateDecode"; + assertEquals(expectedFilter, iepng.getImplicitFilter()); + } + +} |