Author: tilman Date: Fri Mar 21 17:40:54 2014 New Revision: 1579990 URL: http://svn.apache.org/r1579990 Log: PDFBOX-1990: added writing bitonal and grayscale images as single color samples and improved the unit test
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactory.java pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/png.png Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactory.java URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactory.java?rev=1579990&r1=1579989&r2=1579990&view=diff ============================================================================== --- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactory.java (original) +++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactory.java Fri Mar 21 17:40:54 2014 @@ -21,11 +21,13 @@ import java.awt.image.WritableRaster; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import javax.imageio.stream.MemoryCacheImageOutputStream; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.filter.Filter; import org.apache.pdfbox.filter.FilterFactory; import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceColorSpace; import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray; import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB; import static org.apache.pdfbox.pdmodel.graphics.image.ImageFactory.getColorImage; @@ -48,22 +50,54 @@ public class LosslessFactory public static PDImageXObject createFromImage(PDDocument document, BufferedImage image) throws IOException { + int bpc; + PDDeviceColorSpace deviceColorSpace; + // extract color channel BufferedImage awtColorImage = getColorImage(image); ByteArrayOutputStream bos = new ByteArrayOutputStream(); - //TODO use bit writing, indexed, etc - int h = awtColorImage.getHeight(); - int w = awtColorImage.getWidth(); - for (int y = 0; y < h; ++y) + //TODO: using the grayscale branch for BufferedImage.TYPE_BYTE_GRAY + // fails the test. We use the RGB branch instead until this is fixed. + if ((//image.getType() == BufferedImage.TYPE_BYTE_GRAY || + image.getType() == BufferedImage.TYPE_BYTE_BINARY) + && image.getColorModel().getPixelSize() <= 8) + { + MemoryCacheImageOutputStream mcios = new MemoryCacheImageOutputStream(bos); + + // grayscale images need one color per sample + bpc = image.getColorModel().getPixelSize(); + deviceColorSpace = PDDeviceGray.INSTANCE; + int h = awtColorImage.getHeight(); + int w = awtColorImage.getWidth(); + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + mcios.writeBits(awtColorImage.getRGB(x, y), bpc); + } + } + mcios.writeBits(0, 7); // padding + mcios.flush(); + mcios.close(); + } + else { - for (int x = 0; x < w; ++x) + // RGB + bpc = 8; + deviceColorSpace = PDDeviceRGB.INSTANCE; + int h = awtColorImage.getHeight(); + int w = awtColorImage.getWidth(); + for (int y = 0; y < h; ++y) { - Color color = new Color(awtColorImage.getRGB(x, y)); - bos.write(color.getRed()); - bos.write(color.getGreen()); - bos.write(color.getBlue()); + for (int x = 0; x < w; ++x) + { + Color color = new Color(awtColorImage.getRGB(x, y)); + bos.write(color.getRed()); + bos.write(color.getGreen()); + bos.write(color.getBlue()); + } } } @@ -79,8 +113,8 @@ public class LosslessFactory COSDictionary dict = pdImage.getCOSStream(); dict.setItem(COSName.FILTER, COSName.FLATE_DECODE); - pdImage.setColorSpace(PDDeviceRGB.INSTANCE); //TODO from awtColorImage - pdImage.setBitsPerComponent(8); //TODO other sizes + pdImage.setColorSpace(deviceColorSpace); + pdImage.setBitsPerComponent(bpc); pdImage.setHeight(awtColorImage.getHeight()); pdImage.setWidth(awtColorImage.getWidth()); Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java?rev=1579990&r1=1579989&r2=1579990&view=diff ============================================================================== --- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java (original) +++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java Fri Mar 21 17:40:54 2014 @@ -40,9 +40,31 @@ public class LosslessFactoryTest extends { PDDocument document = new PDDocument(); BufferedImage image = ImageIO.read(this.getClass().getResourceAsStream("png.png")); + PDImageXObject ximage = LosslessFactory.createFromImage(document, image); validate(ximage, 8, 344, 287, "png"); + checkIdent(image, ximage.getImage()); + + // Create a grayscale image + BufferedImage grayImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY); + Graphics g = grayImage.getGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + ximage = LosslessFactory.createFromImage(document, grayImage); + validate(ximage, 8, 344, 287, "png"); + checkIdent(grayImage, ximage.getImage()); + + // Create a bitonal image + BufferedImage bitonalImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_BINARY); + g = bitonalImage.getGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + ximage = LosslessFactory.createFromImage(document, bitonalImage); + validate(ximage, 1, 344, 287, "png"); + checkIdent(bitonalImage, ximage.getImage()); + document.close(); + } /** @@ -82,4 +104,29 @@ public class LosslessFactoryTest extends document.close(); } + /** + * Check whether images are identical. + * + * @param expectedImage + * @param actualImage + */ + private void checkIdent(BufferedImage expectedImage, BufferedImage actualImage) + { + String errMsg = ""; + + int w = expectedImage.getWidth(); + int h = expectedImage.getHeight(); + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + if (expectedImage.getRGB(x, y) != actualImage.getRGB(x, y)) + { + errMsg = String.format("(%d,%d) %X != %X", x, y, expectedImage.getRGB(x, y), actualImage.getRGB(x, y)); + } + assertEquals(errMsg, expectedImage.getRGB(x, y), actualImage.getRGB(x, y)); + } + } + } + } Modified: pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/png.png URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/png.png?rev=1579990&r1=1579989&r2=1579990&view=diff ============================================================================== Binary files - no diff available.