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 2015/02/26 19:14:58 UTC

svn commit: r1662523 - /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java

Author: tilman
Date: Thu Feb 26 18:14:57 2015
New Revision: 1662523

URL: http://svn.apache.org/r1662523
Log:
PDFBOX-2128: use meta data to decide read() or readRaster()

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java?rev=1662523&r1=1662522&r2=1662523&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java Thu Feb 26 18:14:57 2015
@@ -28,10 +28,12 @@ import javax.imageio.IIOException;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageReader;
 import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
 import javax.imageio.stream.ImageInputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.pdfbox.cos.COSDictionary;
+import org.w3c.dom.DOMException;
 import org.w3c.dom.Element;
 
 /**
@@ -61,17 +63,32 @@ final class DCTFilter extends Filter
             }
             
             reader.setInput(iis);
+            
+            String numChannels = getNumChannels(reader);
 
             // get the raster using horrible JAI workarounds
             ImageIO.setUseCache(false);
             Raster raster;
-            try
+
+            // Strategy: use read() for RGB or "can't get metadata"
+            // use readRaster() for CMYK and gray and as fallback if read() fails 
+            // after "can't get metadata" because "no meta" file was CMYK
+            if ("3".equals(numChannels) || numChannels.isEmpty())
             {
-                // I'd like to use ImageReader#readRaster but it is buggy and can't read RGB correctly
-                BufferedImage image = reader.read(0);
-                raster = image.getRaster();
+                try
+                {
+                    // I'd like to use ImageReader#readRaster but it is buggy and can't read RGB correctly
+                    BufferedImage image = reader.read(0);
+                    raster = image.getRaster();
+                }
+                catch (IIOException e)
+                {
+                    // JAI can't read CMYK JPEGs using ImageReader#read or ImageIO.read but
+                    // fortunately ImageReader#readRaster isn't buggy when reading 4-channel files
+                    raster = reader.readRaster(0, null);
+                }
             }
-            catch (IIOException e)
+            else
             {
                 // JAI can't read CMYK JPEGs using ImageReader#read or ImageIO.read but
                 // fortunately ImageReader#readRaster isn't buggy when reading 4-channel files
@@ -100,11 +117,18 @@ final class DCTFilter extends Filter
                         field.setAccessible(true);
                         int colorSpaceCode = field.getInt(reader);
                         
-                        if (colorSpaceCode == 7 || colorSpaceCode == 8 || colorSpaceCode == 9) {
-                            transform = 2; // YCCK
-                        } else if (colorSpaceCode == 4) {
-                            transform = 0; // CMYK
-                        } else {
+                        if (colorSpaceCode == 7 || colorSpaceCode == 8 || colorSpaceCode == 9)
+                        {
+                            // YCCK
+                            transform = 2;
+                        }
+                        else if (colorSpaceCode == 4)
+                        {
+                            // CMYK
+                            transform = 0;
+                        }
+                        else
+                        {
                             throw new IOException("Unexpected color space: " + colorSpaceCode);
                         }
                     }
@@ -227,6 +251,30 @@ final class DCTFilter extends Filter
         }
         return writableRaster;
     }
+    
+    // returns the number of channels as a string, or an empty string if there is an error getting the meta data
+    private String getNumChannels(ImageReader reader) throws DOMException, IOException
+    {
+        try
+        {
+            IIOMetadata imageMetadata = reader.getImageMetadata(0);
+            if (imageMetadata == null)
+            {
+                return "";
+            }
+            IIOMetadataNode metaTree = (IIOMetadataNode) imageMetadata.getAsTree("javax_imageio_1.0");
+            Element numChannelsItem = (Element) metaTree.getElementsByTagName("NumChannels").item(0);
+            if (numChannelsItem == null)
+            {
+                return "";
+            }
+            return numChannelsItem.getAttribute("value");
+        }
+        catch (IOException e)
+        {
+            return "";
+        }
+    }    
 
     // clamps value to 0-255 range
     private int clamp(float value)