You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2011/10/24 21:25:19 UTC

svn commit: r1188317 - /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java

Author: lehmi
Date: Mon Oct 24 19:25:19 2011
New Revision: 1188317

URL: http://svn.apache.org/viewvc?rev=1188317&view=rev
Log:
PDFBOX-1116: added a color conversion for separation based jpegs

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java?rev=1188317&r1=1188316&r2=1188317&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java Mon Oct 24 19:25:19 2011
@@ -56,10 +56,12 @@ import org.apache.pdfbox.cos.COSName;
 
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.common.function.PDFunction;
 import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
 import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
 import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray;
 import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.apache.pdfbox.pdmodel.graphics.color.PDSeparation;
 
 /**
  * An image class for JPegs.
@@ -252,7 +254,14 @@ public class PDJpeg extends PDXObjectIma
         {
             if (cs instanceof PDDeviceCMYK)
             {
-                bi = readImage(img, cs);
+                // create BufferedImage based on the converted color values
+                bi = convertCMYK2RGB(readImage(img), cs);
+
+            }
+            else if (cs instanceof PDSeparation)
+            {
+                // create BufferedImage based on the converted color values
+                bi = processSeparation(readImage(img), cs);
             }
             else 
             {
@@ -380,8 +389,7 @@ public class PDJpeg extends PDXObjectIma
         return newImage;
     }
 
-    // CMYK jpegs are not supported by JAI, so that we have the conversion on our own
-    private BufferedImage readImage(byte[] bytes, PDColorSpace colorspace) throws IOException 
+    private Raster readImage(byte[] bytes) throws IOException 
     {
         ImageInputStream input = ImageIO.createImageInputStream(new ByteArrayInputStream(bytes));
         Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
@@ -400,24 +408,26 @@ public class PDJpeg extends PDXObjectIma
             input.close();
         }
         reader.dispose();
-        int w = raster.getWidth();
-        int h = raster.getHeight();
+        return raster;
+    }
 
+    // CMYK jpegs are not supported by JAI, so that we have the conversion on our own
+    private BufferedImage convertCMYK2RGB(Raster raster, PDColorSpace colorspace) throws IOException 
+    {
         // create a java color space to be used for conversion
         ColorSpace cs = colorspace.getJavaColorSpace();
-        // target data array
-        byte[] rgb = new byte[w * h * 3];
-        int numberOfComponents = colorspace.getNumberOfComponents();
-        // pointer into the target array
+        int width = raster.getWidth();
+        int height = raster.getHeight();
+        byte[] rgb = new byte[width * height * 3]; 
         int rgbIndex = 0;
-        for (int i = 0; i < h; i++) 
+        for (int i = 0; i < height; i++) 
         {
-            for (int j = 0; j < w; j++)
+            for (int j = 0; j < width; j++)
             {
                 // get the source color values
                 float[] srcColorValues = raster.getPixel(j,i, (float[])null);
                 // convert values from 0..255 to 0..1
-                for (int k = 0; k < numberOfComponents; k++)
+                for (int k = 0; k < 4; k++)
                 {
                     srcColorValues[k] /= 255f; 
                 }
@@ -435,7 +445,7 @@ public class PDJpeg extends PDXObjectIma
         ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 
                 false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
         // create the target raster
-        WritableRaster writeableRaster = cm.createCompatibleWritableRaster(w, h);
+        WritableRaster writeableRaster = cm.createCompatibleWritableRaster(width, height);
         // get the data buffer of the raster
         DataBufferByte buffer = (DataBufferByte)writeableRaster.getDataBuffer();
         byte[] bufferData = buffer.getData();
@@ -445,5 +455,51 @@ public class PDJpeg extends PDXObjectIma
         return new BufferedImage(cm, writeableRaster, true, null);
     }
 
+    // a separation colorspace uses a tint transform function to convert color values 
+    private BufferedImage processSeparation(Raster raster, PDColorSpace colorspace) throws IOException 
+    {
+        PDSeparation csSeparation = (PDSeparation)colorspace;
+        PDFunction function = csSeparation.getTintTransform();
+        int numberOfInputValues = function.getNumberOfInputParameters();
+        int numberOfOutputValues = function.getNumberOfInputParameters();
+        int width = raster.getWidth();
+        int height = raster.getHeight();
+        byte[] sourceBuffer = new byte[width * height * numberOfOutputValues]; 
+        int bufferIndex = 0;
+        for (int i = 0; i < height; i++) 
+        {
+            for (int j = 0; j < width; j++)
+            {
+                // get the source color values
+                float[] srcColorValues = raster.getPixel(j,i, (float[])null);
+                // convert values from 0..255 to 0..1
+                for (int k = 0; k < numberOfInputValues; k++)
+                {
+                    srcColorValues[k] /= 255f; 
+                }
+                // transform the color values using the tint function
+                float[] convertedValues = function.eval(srcColorValues);
+                // convert values from 0..1 to 0..255
+                for (int k = 0; k < numberOfOutputValues; k++)
+                {
+                    sourceBuffer[bufferIndex+k] = (byte)(convertedValues[k] * 255); 
+                }
+                bufferIndex +=numberOfOutputValues;
+            }
+        }
+        // create a target color model
+        ColorModel cm = new ComponentColorModel(colorspace.getJavaColorSpace(), 
+                false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+        // create the target raster
+        WritableRaster writeableRaster = cm.createCompatibleWritableRaster(width, height);
+        // get the data buffer of the raster
+        DataBufferByte buffer = (DataBufferByte)writeableRaster.getDataBuffer();
+        byte[] bufferData = buffer.getData();
+        // copy all the converted data to the raster buffer
+        System.arraycopy( sourceBuffer, 0,bufferData, 0,sourceBuffer.length );
+        // create an image using the converted color values
+        return new BufferedImage(cm, writeableRaster, true, null);
+    }
+
 }