You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2014/05/08 07:24:47 UTC

svn commit: r1593182 - in /pdfbox/trunk/pdfbox/src: main/java/org/apache/pdfbox/pdmodel/graphics/image/ test/java/org/apache/pdfbox/pdmodel/graphics/image/ test/resources/org/apache/pdfbox/pdmodel/graphics/image/

Author: tilman
Date: Thu May  8 05:24:47 2014
New Revision: 1593182

URL: http://svn.apache.org/r1593182
Log:
PDFBOX-2067: handle jpeg alpha channel for all image types

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java
    pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactoryTest.java
    pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/jpeg.jpg
    pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/jpeg256.jpg

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java?rev=1593182&r1=1593181&r2=1593182&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java Thu May  8 05:24:47 2014
@@ -30,6 +30,8 @@ import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.awt.image.ComponentColorModel;
 import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
 import java.awt.image.WritableRaster;
 
 /**
@@ -84,20 +86,48 @@ class ImageFactory
     // returns the alpha channel of an image
     protected static BufferedImage getAlphaImage(BufferedImage image)
     {
-        //FIXME This doesn't work. The raster returned has a
-        // SinglePixelPackedSampleModel, and ComponentColorModel created is not
-        // compatible with it, because the BufferedImage constructor expects a
-        // ComponentSampleModel, and with the same number of bands.
         if (!image.getColorModel().hasAlpha())
         {
             return null;
         }
-
-        // extract the alpha information
+        BufferedImage alphaImage = null;
         WritableRaster alphaRaster = image.getAlphaRaster();
-        ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
-                false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
-        return new BufferedImage(cm, alphaRaster, false, null);
+        DataBuffer dbSrc = alphaRaster.getDataBuffer();
+        if (dbSrc instanceof DataBufferInt)
+        {
+            // PDFBOX-2057, handle TYPE_INT_A... types
+            // See also
+            // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4243485
+
+            alphaImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
+            DataBuffer dbDst = alphaImage.getRaster().getDataBuffer();
+            // alpha value is in the highest byte
+            for (int i = 0; i < dbSrc.getSize(); ++i)
+            {
+                dbDst.setElem(i, dbSrc.getElem(i) >>> 24);
+            }
+        }
+        else if (dbSrc instanceof DataBufferByte)
+        {
+            alphaImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
+            DataBuffer dbDst = alphaImage.getRaster().getDataBuffer();
+            // alpha value is at bytes 0...4...8...
+            for (int i = 0; i < dbDst.getSize(); ++i)
+            {
+                dbDst.setElem(i, dbSrc.getElem(i << 2));
+            }
+        }
+        else
+        {
+            // This didn't work for INT types, see PDFBOX-2057. The raster returned has a
+            // SinglePixelPackedSampleModel, and ComponentColorModel created is not
+            // compatible with it, because the BufferedImage constructor expects a
+            // ComponentSampleModel, and with the same number of bands.
+            ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
+                    false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+            alphaImage = new BufferedImage(cm, alphaRaster, false, null);
+        }
+        return alphaImage;
     }
 
     // returns the color channels of an image

Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactoryTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactoryTest.java?rev=1593182&r1=1593181&r2=1593182&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactoryTest.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactoryTest.java Thu May  8 05:24:47 2014
@@ -17,11 +17,14 @@ package org.apache.pdfbox.pdmodel.graphi
 
 import java.awt.Graphics;
 import java.awt.image.BufferedImage;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.imageio.ImageIO;
 import junit.framework.TestCase;
 import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
 import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray;
 import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
 import static org.apache.pdfbox.pdmodel.graphics.image.ValidateXImage.validate;
@@ -33,6 +36,15 @@ import static org.apache.pdfbox.pdmodel.
  */
 public class JPEGFactoryTest extends TestCase
 {
+    private final File testResultsDir = new File("target/test-output/graphics");
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        testResultsDir.mkdirs();
+    }
+
     /**
      * Tests JPEGFactory#createFromStream(PDDocument document, InputStream
      * stream) with color JPEG file
@@ -101,27 +113,39 @@ public class JPEGFactoryTest extends Tes
         BufferedImage image = ImageIO.read(JPEGFactoryTest.class.getResourceAsStream("jpeg.jpg"));
 
         // create an ARGB image
-        int w = image.getWidth();
-        int h = image.getHeight();
-        BufferedImage argbImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+        int width = image.getWidth();
+        int height = image.getHeight();
+        BufferedImage argbImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
         Graphics ag = argbImage.getGraphics();
         ag.drawImage(image, 0, 0, null);
         ag.dispose();
 
-        // create a weird transparency triangle
-        for (int y = 0; y < h; ++y)
+        for (int x = 0; x < argbImage.getWidth(); ++x)
         {
-            for (int x = 0; x < Math.min(y, w); ++x)
+            for (int y = 0; y < argbImage.getHeight(); ++y)
             {
-                argbImage.setRGB(x, y, image.getRGB(x, y) & 0xFFFFFF | ((x * 255 / w) << 24));
+                argbImage.setRGB(x, y, (argbImage.getRGB(x, y) & 0xFFFFFF) | ((y / 10 * 10) << 24));
             }
         }
 
-        //TODO uncomment if ImageFactory.getAlphaImage() ever works
-//        PDImageXObject ximage = JPEGFactory.createFromImage(document, argbImage);
-//        validate(ximage, 8, 344, 287, "jpg");
-//        assertNotNull(ximage.getSoftMask());
-//        validate(ximage.getSoftMask(), 8, 344, 287, "jpg");
+        PDImageXObject ximage = JPEGFactory.createFromImage(document, argbImage);
+        validate(ximage, 8, width, height, "jpg", PDDeviceRGB.INSTANCE.getName());
+        assertNotNull(ximage.getSoftMask());
+        validate(ximage.getSoftMask(), 8, width, height, "jpg", PDDeviceGray.INSTANCE.getName());
+
+        // This part isn't really needed because this test doesn't break
+        // if the mask has the wrong colorspace (PDFBOX-2057), but it is still useful
+        // if something goes wrong in the future and we want to have a PDF to open.
+        PDPage page = new PDPage();
+        document.addPage(page);
+        PDPageContentStream contentStream = new PDPageContentStream(document, page, true, false);
+        contentStream.drawXObject(ximage, 150, 300, ximage.getWidth(), ximage.getHeight());
+        contentStream.drawXObject(ximage, 200, 350, ximage.getWidth(), ximage.getHeight());
+        contentStream.close();
+        File pdfFile = new File(testResultsDir, "jpeg-intargb.pdf");
+        document.save(pdfFile);
+        document.close();
+        document = PDDocument.loadNonSeq(pdfFile, null);
         document.close();
     }
 

Modified: pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/jpeg.jpg
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/jpeg.jpg?rev=1593182&r1=1593181&r2=1593182&view=diff
==============================================================================
Binary files - no diff available.

Modified: pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/jpeg256.jpg
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/graphics/image/jpeg256.jpg?rev=1593182&r1=1593181&r2=1593182&view=diff
==============================================================================
Binary files - no diff available.