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 2020/08/29 11:32:15 UTC
svn commit: r1881293 - in /pdfbox/branches/issue45/pdfbox/src:
main/java/org/apache/pdfbox/pdmodel/graphics/color/
main/java/org/apache/pdfbox/pdmodel/graphics/image/
test/java/org/apache/pdfbox/pdmodel/graphics/image/
Author: tilman
Date: Sat Aug 29 11:32:15 2020
New Revision: 1881293
URL: http://svn.apache.org/viewvc?rev=1881293&view=rev
Log:
PDFBOX-4847: implements (optional) access to raw images as BufferedImage, by Emmeran Seehuber
Modified:
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDCIEBasedColorSpace.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceCMYK.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceGray.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceRGB.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDIndexed.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDJPXColorSpace.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java
pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDInlineImage.java
pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java
pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java
pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDCIEBasedColorSpace.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDCIEBasedColorSpace.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDCIEBasedColorSpace.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDCIEBasedColorSpace.java Sat Aug 29 11:32:15 2020
@@ -1,80 +1,88 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pdfbox.pdmodel.graphics.color;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.WritableRaster;
-import java.io.IOException;
-
-/**
- * CIE-based colour spaces specify colours in a way that is independent of the characteristics
- * of any particular output device. They are based on an international standard for colour
- * specification created by the Commission Internationale de l'Ãclairage (CIE).
- *
- * @author John Hewson
- */
-public abstract class PDCIEBasedColorSpace extends PDColorSpace
-{
- //
- // WARNING: this method is performance sensitive, modify with care!
- //
- @Override
- public BufferedImage toRGBImage(WritableRaster raster) throws IOException
- {
- // This method calls toRGB to convert images one pixel at a time. For matrix-based
- // CIE color spaces this is fast enough. However, it should not be used with any
- // color space which uses an ICC Profile as it will be far too slow.
-
- int width = raster.getWidth();
- int height = raster.getHeight();
-
- BufferedImage rgbImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- WritableRaster rgbRaster = rgbImage.getRaster();
-
- // always three components: ABC
- float[] abc = new float[3];
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- raster.getPixel(x, y, abc);
-
- // 0..255 -> 0..1
- abc[0] /= 255;
- abc[1] /= 255;
- abc[2] /= 255;
-
- float[] rgb = toRGB(abc);
-
- // 0..1 -> 0..255
- rgb[0] *= 255;
- rgb[1] *= 255;
- rgb[2] *= 255;
-
- rgbRaster.setPixel(x, y, rgb);
- }
- }
-
- return rgbImage;
- }
-
- @Override
- public String toString()
- {
- return getName(); // TODO return more info
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.pdmodel.graphics.color;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+
+/**
+ * CIE-based colour spaces specify colours in a way that is independent of the characteristics
+ * of any particular output device. They are based on an international standard for colour
+ * specification created by the Commission Internationale de l'Ãclairage (CIE).
+ *
+ * @author John Hewson
+ */
+public abstract class PDCIEBasedColorSpace extends PDColorSpace
+{
+ //
+ // WARNING: this method is performance sensitive, modify with care!
+ //
+ @Override
+ public BufferedImage toRGBImage(WritableRaster raster) throws IOException
+ {
+ // This method calls toRGB to convert images one pixel at a time. For matrix-based
+ // CIE color spaces this is fast enough. However, it should not be used with any
+ // color space which uses an ICC Profile as it will be far too slow.
+
+ int width = raster.getWidth();
+ int height = raster.getHeight();
+
+ BufferedImage rgbImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ WritableRaster rgbRaster = rgbImage.getRaster();
+
+ // always three components: ABC
+ float[] abc = new float[3];
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ raster.getPixel(x, y, abc);
+
+ // 0..255 -> 0..1
+ abc[0] /= 255;
+ abc[1] /= 255;
+ abc[2] /= 255;
+
+ float[] rgb = toRGB(abc);
+
+ // 0..1 -> 0..255
+ rgb[0] *= 255;
+ rgb[1] *= 255;
+ rgb[2] *= 255;
+
+ rgbRaster.setPixel(x, y, rgb);
+ }
+ }
+
+ return rgbImage;
+ }
+
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster) throws IOException
+ {
+ // There is no direct equivalent of a CIE colorspace in Java. So we can
+ // not do anything here.
+ return null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getName(); // TODO return more info
+ }
+}
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java Sat Aug 29 11:32:15 2020
@@ -298,6 +298,35 @@ public abstract class PDColorSpace imple
public abstract BufferedImage toRGBImage(WritableRaster raster) throws IOException;
/**
+ * Returns the image in this colorspace or null. No conversion is performed.
+ *
+ * For special colorspaces like PDSeparation the image is returned in the gray colorspace.
+ * For undefined colorspaces like DeviceCMYK/DeviceRGB and DeviceGray null is returned.
+ *
+ * You can always fallback to {@link #toRGBImage(WritableRaster)} if this returns null.
+ *
+ * @param raster the source raster
+ * @return an buffered image in this colorspace. Or null if it is not possible to extract
+ * that image with the original colorspace without conversion.
+ */
+ public abstract BufferedImage toRawImage(WritableRaster raster) throws IOException;
+
+ /**
+ * Returns the given raster as BufferedImage with the given awtColorSpace using a
+ * ComponentColorModel.
+ * @param raster the source raster
+ * @param awtColorSpace the AWT colorspace
+ * @return a BufferedImage in this colorspace
+ */
+ protected final BufferedImage toRawImage(WritableRaster raster, ColorSpace awtColorSpace)
+ {
+ ColorModel colorModel = new ComponentColorModel(awtColorSpace,
+ false, false, Transparency.OPAQUE, raster.getDataBuffer().getDataType());
+ return new BufferedImage(colorModel, raster, false, null);
+ }
+
+
+ /**
* Returns the (A)RGB equivalent of the given raster, using the given AWT color space
* to perform the conversion.
* @param raster the source raster
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceCMYK.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceCMYK.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceCMYK.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceCMYK.java Sat Aug 29 11:32:15 2020
@@ -136,6 +136,14 @@ public class PDDeviceCMYK extends PDDevi
}
@Override
+ public BufferedImage toRawImage(WritableRaster raster) throws IOException
+ {
+ // Device CMYK is not specified, as its the colors of whatever device you use.
+ // The user should fallback to the RGB image
+ return null;
+ }
+
+ @Override
public BufferedImage toRGBImage(WritableRaster raster) throws IOException
{
init();
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceGray.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceGray.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceGray.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceGray.java Sat Aug 29 11:32:15 2020
@@ -70,6 +70,14 @@ public final class PDDeviceGray extends
}
@Override
+ public BufferedImage toRawImage(WritableRaster raster) throws IOException
+ {
+ // DeviceGray is whatever the output device chooses. We have no Java colorspace
+ // for this.
+ return null;
+ }
+
+ @Override
public BufferedImage toRGBImage(WritableRaster raster) throws IOException
{
int width = raster.getWidth();
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java Sat Aug 29 11:32:15 2020
@@ -414,6 +414,13 @@ public class PDDeviceN extends PDSpecial
return alternateColorSpace.toRGB(altValue);
}
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster)
+ {
+ // We don't know how to convert that.
+ return null;
+ }
+
/**
* Returns true if this color space has the NChannel subtype.
* @return true if subtype is NChannel
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceRGB.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceRGB.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceRGB.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceRGB.java Sat Aug 29 11:32:15 2020
@@ -117,4 +117,12 @@ public final class PDDeviceRGB extends P
image.setData(raster);
return image;
}
+
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster) throws IOException
+ {
+ // Device RGB is not specified, as its the colors of whatever device you use. The user
+ // should use the toRGBImage().
+ return null;
+ }
}
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java Sat Aug 29 11:32:15 2020
@@ -381,6 +381,16 @@ public final class PDICCBased extends PD
}
@Override
+ public BufferedImage toRawImage(WritableRaster raster) throws IOException
+ {
+ if(awtColorSpace == null)
+ {
+ return alternateColorSpace.toRawImage(raster);
+ }
+ return toRawImage(raster, awtColorSpace);
+ }
+
+ @Override
public int getNumberOfComponents()
{
if (numberOfComponents < 0)
@@ -595,6 +605,15 @@ public final class PDICCBased extends PD
stream.getCOSObject().setItem(COSName.METADATA, metadata);
}
+ /**
+ * Internal accessor to support indexed raw images.
+ * @return true if this colorspace is sRGB.
+ */
+ boolean isSRGB()
+ {
+ return isRGB;
+ }
+
@Override
public String toString()
{
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDIndexed.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDIndexed.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDIndexed.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDIndexed.java Sat Aug 29 11:32:15 2020
@@ -18,7 +18,9 @@ package org.apache.pdfbox.pdmodel.graphi
import java.awt.Point;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
+import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.IOException;
@@ -210,6 +212,32 @@ public final class PDIndexed extends PDS
return rgbImage;
}
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster)
+ {
+ // We can only convert sRGB index colorspaces, depending on the base colorspace
+ if (baseColorSpace instanceof PDICCBased)
+ {
+ if (((PDICCBased) baseColorSpace).isSRGB())
+ {
+ byte[] r = new byte[colorTable.length];
+ byte[] g = new byte[colorTable.length];
+ byte[] b = new byte[colorTable.length];
+ for (int i = 0; i < colorTable.length; i++)
+ {
+ r[i] = (byte) ((int) (colorTable[i][0] * 255) & 0xFF);
+ g[i] = (byte) ((int) (colorTable[i][1] * 255) & 0xFF);
+ b[i] = (byte) ((int) (colorTable[i][2] * 255) & 0xFF);
+ }
+ ColorModel colorModel = new IndexColorModel(8, colorTable.length, r, g, b);
+ return new BufferedImage(colorModel, raster, false, null);
+ }
+ }
+
+ // We can't handle all other cases at the moment.
+ return null;
+ }
+
/**
* Returns the base color space.
* @return the base color space.
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDJPXColorSpace.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDJPXColorSpace.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDJPXColorSpace.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDJPXColorSpace.java Sat Aug 29 11:32:15 2020
@@ -1,93 +1,99 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pdfbox.pdmodel.graphics.color;
-
-import org.apache.pdfbox.cos.COSBase;
-
-import java.awt.color.ColorSpace;
-import java.awt.image.BufferedImage;
-import java.awt.image.WritableRaster;
-import java.io.IOException;
-
-/**
- * A color space embedded in a JPX file.
- * This wraps the AWT ColorSpace which is obtained after JAI Image I/O reads a JPX stream.
- *
- * @author John Hewson
- */
-public final class PDJPXColorSpace extends PDColorSpace
-{
- private final ColorSpace awtColorSpace;
-
- /**
- * Creates a new JPX color space from the given AWT color space.
- * @param colorSpace AWT color space from a JPX image
- */
- public PDJPXColorSpace(ColorSpace colorSpace)
- {
- this.awtColorSpace = colorSpace;
- }
-
- @Override
- public String getName()
- {
- return "JPX";
- }
-
- @Override
- public int getNumberOfComponents()
- {
- return awtColorSpace.getNumComponents();
- }
-
- @Override
- public float[] getDefaultDecode(int bitsPerComponent)
- {
- int n = getNumberOfComponents();
- float[] decode = new float[n * 2];
- for (int i = 0; i < n; i++)
- {
- decode[i * 2] = awtColorSpace.getMinValue(i);
- decode[i * 2 + 1] = awtColorSpace.getMaxValue(i);
- }
- return decode;
- }
-
- @Override
- public PDColor getInitialColor()
- {
- throw new UnsupportedOperationException("JPX color spaces don't support drawing");
- }
-
- @Override
- public float[] toRGB(float[] value)
- {
- throw new UnsupportedOperationException("JPX color spaces don't support drawing");
- }
-
- @Override
- public BufferedImage toRGBImage(WritableRaster raster) throws IOException
- {
- return toRGBImageAWT(raster, awtColorSpace);
- }
-
- @Override
- public COSBase getCOSObject()
- {
- throw new UnsupportedOperationException("JPX color spaces don't have COS objects");
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.pdmodel.graphics.color;
+
+import org.apache.pdfbox.cos.COSBase;
+
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+
+/**
+ * A color space embedded in a JPX file.
+ * This wraps the AWT ColorSpace which is obtained after JAI Image I/O reads a JPX stream.
+ *
+ * @author John Hewson
+ */
+public final class PDJPXColorSpace extends PDColorSpace
+{
+ private final ColorSpace awtColorSpace;
+
+ /**
+ * Creates a new JPX color space from the given AWT color space.
+ * @param colorSpace AWT color space from a JPX image
+ */
+ public PDJPXColorSpace(ColorSpace colorSpace)
+ {
+ this.awtColorSpace = colorSpace;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "JPX";
+ }
+
+ @Override
+ public int getNumberOfComponents()
+ {
+ return awtColorSpace.getNumComponents();
+ }
+
+ @Override
+ public float[] getDefaultDecode(int bitsPerComponent)
+ {
+ int n = getNumberOfComponents();
+ float[] decode = new float[n * 2];
+ for (int i = 0; i < n; i++)
+ {
+ decode[i * 2] = awtColorSpace.getMinValue(i);
+ decode[i * 2 + 1] = awtColorSpace.getMaxValue(i);
+ }
+ return decode;
+ }
+
+ @Override
+ public PDColor getInitialColor()
+ {
+ throw new UnsupportedOperationException("JPX color spaces don't support drawing");
+ }
+
+ @Override
+ public float[] toRGB(float[] value)
+ {
+ throw new UnsupportedOperationException("JPX color spaces don't support drawing");
+ }
+
+ @Override
+ public BufferedImage toRGBImage(WritableRaster raster) throws IOException
+ {
+ return toRGBImageAWT(raster, awtColorSpace);
+ }
+
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster)
+ {
+ return toRawImage(raster, this.awtColorSpace);
+ }
+
+ @Override
+ public COSBase getCOSObject()
+ {
+ throw new UnsupportedOperationException("JPX color spaces don't have COS objects");
+ }
+}
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java Sat Aug 29 11:32:15 2020
@@ -20,6 +20,7 @@ import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.common.PDRange;
+
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
@@ -107,6 +108,13 @@ public final class PDLab extends PDCIEDi
}
@Override
+ public BufferedImage toRawImage(WritableRaster raster)
+ {
+ // Not handled at the moment.
+ return null;
+ }
+
+ @Override
public float[] toRGB(float[] value)
{
// CIE LAB to RGB, see http://en.wikipedia.org/wiki/Lab_color_space
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java Sat Aug 29 11:32:15 2020
@@ -101,6 +101,12 @@ public final class PDPattern extends PDS
throw new UnsupportedOperationException();
}
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Returns the pattern for the given color.
*
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java Sat Aug 29 11:32:15 2020
@@ -17,6 +17,7 @@
package org.apache.pdfbox.pdmodel.graphics.color;
import java.awt.Point;
+import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
@@ -222,6 +223,12 @@ public class PDSeparation extends PDSpec
}
}
+ @Override
+ public BufferedImage toRawImage(WritableRaster raster)
+ {
+ return toRawImage(raster, ColorSpace.getInstance(ColorSpace.CS_GRAY));
+ }
+
/**
* Returns the colorant name.
* @return the name of the colorant
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java Sat Aug 29 11:32:15 2020
@@ -56,6 +56,28 @@ public interface PDImage extends COSObje
WritableRaster getRawRaster() throws IOException;
/**
+ * Try to get the raw image as AWT buffered image with it's original colorspace. No
+ * color conversion is performed.
+ *
+ * You could use the returned BufferedImage for draw operations. But this would be very
+ * slow as the color conversion would happen on demand. You rather should use
+ * {@link #getImage()} for that.
+ *
+ * This method returns null if it is not possible to map the underlying colorspace into a
+ * java.awt.ColorSpace.
+ *
+ * Use this method if you want to extract the image without loosing any color information, as
+ * no color conversion will be performed.
+ *
+ * You can alwoys use {@link #getRawRaster()}, if you want to access the raw data even if
+ * no matching java.awt.ColorSpace exists
+ *
+ * @return the raw image with a java.awt.ColorSpace or null
+ * @throws IOException
+ */
+ BufferedImage getRawImage() throws IOException;
+
+ /**
* Returns the content of this image as an AWT buffered image with an (A)RGB colored space. Only
* the subregion specified is rendered, and is subsampled by advancing the specified amount of
* rows and columns in the source image for every resulting pixel.
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java Sat Aug 29 11:32:15 2020
@@ -507,6 +507,12 @@ public final class PDImageXObject extend
}
@Override
+ public BufferedImage getRawImage() throws IOException
+ {
+ return getColorSpace().toRawImage(getRawRaster());
+ }
+
+ @Override
public WritableRaster getRawRaster() throws IOException
{
return SampledImageReader.getRawRaster(this);
Modified: pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDInlineImage.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDInlineImage.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDInlineImage.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDInlineImage.java Sat Aug 29 11:32:15 2020
@@ -363,6 +363,12 @@ public final class PDInlineImage impleme
}
@Override
+ public BufferedImage getRawImage() throws IOException
+ {
+ return getColorSpace().toRawImage(getRawRaster());
+ }
+
+ @Override
public BufferedImage getStencilImage(Paint paint) throws IOException
{
if (!isStencil())
Modified: pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java Sat Aug 29 11:32:15 2020
@@ -37,8 +37,6 @@ import java.util.Hashtable;
import java.util.Random;
import javax.imageio.ImageIO;
import junit.framework.TestCase;
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
@@ -375,6 +373,56 @@ public class LosslessFactoryTest extends
}
}
+ /**
+ * Check whether the raw data of images are identical.
+ * @param expectedImage
+ * @param actualImage
+ */
+ static void checkIdentRaw(BufferedImage expectedImage, PDImageXObject actualImage)
+ throws IOException
+ {
+ WritableRaster expectedRaster = expectedImage.getRaster();
+ WritableRaster actualRaster = actualImage.getRawRaster();
+ int w = expectedRaster.getWidth();
+ int h = expectedRaster.getHeight();
+ assertEquals(w, actualRaster.getWidth());
+ assertEquals(h, actualRaster.getHeight());
+ assertEquals(expectedRaster.getDataBuffer().getDataType(), actualRaster.getDataBuffer().getDataType());
+ int numDataElements = expectedRaster.getNumDataElements();
+ int numDataElementsToCompare;
+ if (expectedImage.getAlphaRaster() != null)
+ {
+ // We do not compare the alpha channel, as this is stored extra
+ numDataElementsToCompare = numDataElements - 1;
+ assertEquals(numDataElementsToCompare, actualRaster.getNumDataElements());
+ } else
+ {
+ numDataElementsToCompare = numDataElements;
+ assertEquals(numDataElements, actualRaster.getNumDataElements());
+ }
+ int[] expectedData = new int[numDataElements];
+ int[] actualData = new int[numDataElements];
+ for (int y = 0; y < h; ++y)
+ {
+ for (int x = 0; x < w; ++x)
+ {
+ expectedRaster.getPixel(x, y, expectedData);
+ actualRaster.getPixel(x, y, actualData);
+ for (int i = 0; i < numDataElementsToCompare; i++)
+ {
+ int expectedValue = expectedData[i];
+ int actualValue = actualData[i];
+ if (expectedValue != actualValue)
+ {
+ String errMsg = String.format("(%d,%d) Channel %d %04X != %04X", x, y, i, expectedValue,
+ actualValue);
+ assertEquals(errMsg, expectedValue, actualValue);
+ }
+ }
+ }
+ }
+ }
+
private void doBitmaskTransparencyTest(int imageType, String pdfFilename) throws IOException
{
PDDocument document = new PDDocument();
@@ -587,6 +635,7 @@ public class LosslessFactoryTest extends
validate(ximage, 16, w, h, "png", PDDeviceRGB.INSTANCE.getName());
checkIdent(image, ximage.getImage());
checkIdentRGB(image, ximage.getOpaqueImage());
+ checkIdentRaw(image, ximage);
assertNotNull(ximage.getSoftMask());
validate(ximage.getSoftMask(), 16, w, h, "png", PDDeviceGray.INSTANCE.getName());
Modified: pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java Sat Aug 29 11:32:15 2020
@@ -41,13 +41,16 @@ import org.apache.pdfbox.pdmodel.PDPageC
import org.apache.pdfbox.pdmodel.graphics.color.PDICCBased;
import org.apache.pdfbox.pdmodel.graphics.color.PDIndexed;
+import static org.apache.pdfbox.pdmodel.graphics.image.LosslessFactoryTest.checkIdentRaw;
import static org.apache.pdfbox.pdmodel.graphics.image.ValidateXImage.checkIdent;
import org.junit.Assert;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+
import org.junit.Before;
import org.junit.Test;
@@ -173,6 +176,7 @@ public class PNGConverterTest
{
PDDocument doc = new PDDocument();
byte[] imageBytes = IOUtils.toByteArray(PNGConverterTest.class.getResourceAsStream(name));
+
PDImageXObject pdImageXObject = PNGConverter.convertPNGImage(doc, imageBytes);
assertNotNull(pdImageXObject);
@@ -196,6 +200,8 @@ public class PNGConverterTest
doc.save(new File(parentDir, name + ".pdf"));
BufferedImage image = pdImageXObject.getImage();
+ assertNotNull(pdImageXObject.getRawRaster());
+
BufferedImage expectedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
if (imageProfile != null && expectedImage.getColorModel().getColorSpace().isCS_sRGB())
{
@@ -206,6 +212,15 @@ public class PNGConverterTest
checkIdent(expectedImage, image);
+ BufferedImage rawImage = pdImageXObject.getRawImage();
+ if (rawImage != null)
+ {
+ assertEquals(rawImage.getWidth(), pdImageXObject.getWidth());
+ assertEquals(rawImage.getHeight(), pdImageXObject.getHeight());
+ // We compare the raw data
+ checkIdentRaw(expectedImage, pdImageXObject);
+ }
+
doc.close();
}
Modified: pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java?rev=1881293&r1=1881292&r2=1881293&view=diff
==============================================================================
--- pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java (original)
+++ pdfbox/branches/issue45/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java Sat Aug 29 11:32:15 2020
@@ -70,6 +70,17 @@ public class ValidateXImage
assertNotNull(ximage.getImage());
assertEquals(ximage.getWidth(), ximage.getImage().getWidth());
assertEquals(ximage.getHeight(), ximage.getImage().getHeight());
+ WritableRaster rawRaster = ximage.getRawRaster();
+ assertNotNull(rawRaster);
+ assertEquals(rawRaster.getWidth(), ximage.getWidth());
+ assertEquals(rawRaster.getHeight(), ximage.getHeight());
+ if (colorSpaceName.equals("ICCBased"))
+ {
+ BufferedImage rawImage = ximage.getRawImage();
+ assertNotNull(rawImage);
+ assertEquals(rawImage.getWidth(), ximage.getWidth());
+ assertEquals(rawImage.getHeight(), ximage.getHeight());
+ }
boolean canEncode = true;
boolean writeOk;