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/23 16:59:30 UTC
svn commit: r1187901 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java
Author: lehmi
Date: Sun Oct 23 14:59:29 2011
New Revision: 1187901
URL: http://svn.apache.org/viewvc?rev=1187901&view=rev
Log:
PDFBOX-1116: added a color conversion for CMYK 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=1187901&r1=1187900&r2=1187901&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 Sun Oct 23 14:59:29 2011
@@ -18,7 +18,15 @@ package org.apache.pdfbox.pdmodel.graphi
import java.awt.Color;
import java.awt.Graphics2D;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
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.Raster;
+import java.awt.image.WritableRaster;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -35,9 +43,11 @@ import java.util.Locale;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.IIOException;
+import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
+import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import org.apache.pdfbox.cos.COSArray;
@@ -46,6 +56,8 @@ import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDStream;
+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;
@@ -230,41 +242,37 @@ public class PDJpeg extends PDXObjectIma
{ //TODO PKOCH
BufferedImage bi = null;
boolean readError = false;
- try
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ write2OutputStream(os);
+ os.close();
+ byte[] img = os.toByteArray();
+
+ PDColorSpace cs = getColorSpace();
+ try
{
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- write2OutputStream(os);
- os.close();
- byte[] img = os.toByteArray();
-
- // 1. try to read jpeg image
- try
+ if (cs instanceof PDDeviceCMYK)
{
- bi = ImageIO.read(new ByteArrayInputStream(img));
+ bi = readImage(img, cs);
}
- catch (IIOException iioe)
+ else
{
- // cannot read jpeg
- readError = true;
- }
- catch (Exception ignore)
- {
- }
-
- // 2. try to read jpeg again. some jpegs have some strange header containing
- // "Adobe " at some place. so just replace the header with a valid jpeg header.
- // TODO : not sure if it works for all cases
- if (bi == null && readError)
- {
- byte[] newImage = replaceHeader(img);
-
- ByteArrayInputStream bai = new ByteArrayInputStream(newImage);
-
+ ByteArrayInputStream bai = new ByteArrayInputStream(img);
bi = ImageIO.read(bai);
}
+
}
- finally
+ catch(IIOException exception)
+ {
+ readError = true;
+ }
+ // 2. try to read jpeg again. some jpegs have some strange header containing
+ // "Adobe " at some place. so just replace the header with a valid jpeg header.
+ // TODO : not sure if it works for all cases
+ if (bi == null && readError)
{
+ byte[] newImage = replaceHeader(img);
+ ByteArrayInputStream bai = new ByteArrayInputStream(newImage);
+ bi = ImageIO.read(bai);
}
// If there is a 'soft mask' image then we use that as a transparency mask.
@@ -305,7 +313,7 @@ public class PDJpeg extends PDXObjectIma
* Returns the given file as byte array.
* @param file File to be read
* @return given file as byte array
- * @throws IOException if somethin went wrong during reading the file
+ * @throws IOException if something went wrong during reading the file
*/
public static byte[] getBytesFromFile(File file) throws IOException
{
@@ -371,5 +379,71 @@ 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
+ {
+ ImageInputStream input = ImageIO.createImageInputStream(new ByteArrayInputStream(bytes));
+ Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
+ if (readers == null || !readers.hasNext())
+ {
+ throw new RuntimeException("No ImageReaders found");
+ }
+
+ // read the raster information only
+ // avoid to access the meta information
+ ImageReader reader = (ImageReader) readers.next();
+ reader.setInput(input);
+ Raster raster = reader.readRaster(0, reader.getDefaultReadParam());
+ if (input != null)
+ {
+ input.close();
+ }
+ reader.dispose();
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+
+ // 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 rgbIndex = 0;
+ for (int i = 0; i < h; i++)
+ {
+ for (int j = 0; j < w; 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++)
+ {
+ srcColorValues[k] /= 255f;
+ }
+ // convert CMYK to RGB
+ float[] rgbValues = cs.toRGB(srcColorValues);
+ // convert values from 0..1 to 0..255
+ for (int k = 0; k < 3; k++)
+ {
+ rgb[rgbIndex+k] = (byte)(rgbValues[k] * 255);
+ }
+ rgbIndex +=3;
+ }
+ }
+ // create a RGB color model
+ 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);
+ // 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( rgb, 0,bufferData, 0,rgb.length );
+ // create an image using the converted color values
+ return new BufferedImage(cm, writeableRaster, true, null);
+ }
+
}