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/21 17:21:09 UTC
svn commit: r1881063 - in
/pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image:
PNGConverterTest.java ValidateXImage.java
Author: tilman
Date: Fri Aug 21 17:21:09 2020
New Revision: 1881063
URL: http://svn.apache.org/viewvc?rev=1881063&view=rev
Log:
PDFBOX-4847: convert non sRGB images to sRGB and enable testImageConversionRGB16BitICC, by Emmeran Seehuber
Modified:
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java
Modified: pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java?rev=1881063&r1=1881062&r2=1881063&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/PNGConverterTest.java Fri Aug 21 17:21:09 2020
@@ -17,14 +17,19 @@
package org.apache.pdfbox.pdmodel.graphics.image;
import java.awt.Color;
+import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Hashtable;
import javax.imageio.ImageIO;
import org.apache.pdfbox.cos.COSName;
@@ -37,6 +42,7 @@ import org.apache.pdfbox.pdmodel.graphic
import static org.apache.pdfbox.pdmodel.graphics.image.ValidateXImage.checkIdent;
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.assertTrue;
import org.junit.Before;
@@ -87,7 +93,7 @@ public class PNGConverterTest
checkImageConvert("png_rgb_gamma.png");
}
- // @Test
+ @Test
public void testImageConversionRGB16BitICC() throws IOException
{
checkImageConvert("png_rgb_romm_16bit.png");
@@ -165,11 +171,14 @@ public class PNGConverterTest
PDDocument doc = new PDDocument();
byte[] imageBytes = IOUtils.toByteArray(PNGConverterTest.class.getResourceAsStream(name));
PDImageXObject pdImageXObject = PNGConverter.convertPNGImage(doc, imageBytes);
+ assertNotNull(pdImageXObject);
+
+ ICC_Profile imageProfile = null;
if (pdImageXObject.getColorSpace() instanceof PDICCBased)
{
// Make sure that ICC profile is a valid one
PDICCBased iccColorSpace = (PDICCBased) pdImageXObject.getColorSpace();
- ICC_Profile.getInstance(iccColorSpace.getPDStream().toByteArray());
+ imageProfile = ICC_Profile.getInstance(iccColorSpace.getPDStream().toByteArray());
}
PDPage page = new PDPage();
doc.addPage(page);
@@ -183,10 +192,45 @@ public class PNGConverterTest
contentStream.close();
doc.save(new File(parentDir, name + ".pdf"));
BufferedImage image = pdImageXObject.getImage();
- checkIdent(ImageIO.read(new ByteArrayInputStream(imageBytes)), image);
+
+ BufferedImage expectedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
+ if (imageProfile != null && expectedImage.getColorModel().getColorSpace().isCS_sRGB())
+ {
+ // The image has an embedded ICC Profile, but the default java PNG
+ // reader does not correctly read that.
+ expectedImage = getImageWithProfileData(expectedImage, imageProfile);
+ }
+
+ checkIdent(expectedImage, image);
+
doc.close();
}
+ public static BufferedImage getImageWithProfileData(BufferedImage sourceImage,
+ ICC_Profile realProfile)
+ {
+ Hashtable<String, Object> properties = new Hashtable<String, Object>();
+ String[] propertyNames = sourceImage.getPropertyNames();
+ if (propertyNames != null)
+ {
+ for (String propertyName : propertyNames)
+ {
+ properties.put(propertyName, sourceImage.getProperty(propertyName));
+ }
+ }
+ ComponentColorModel oldColorModel = (ComponentColorModel) sourceImage.getColorModel();
+ boolean hasAlpha = oldColorModel.hasAlpha();
+ int transparency = oldColorModel.getTransparency();
+ boolean alphaPremultiplied = oldColorModel.isAlphaPremultiplied();
+ WritableRaster raster = sourceImage.getRaster();
+ int dataType = raster.getDataBuffer().getDataType();
+ int[] componentSize = oldColorModel.getComponentSize();
+ final ColorModel colorModel = new ComponentColorModel(new ICC_ColorSpace(realProfile),
+ componentSize, hasAlpha, alphaPremultiplied, transparency, dataType);
+ return new BufferedImage(colorModel, raster, sourceImage.isAlphaPremultiplied(),
+ properties);
+ }
+
@Test
public void testCheckConverterState()
{
Modified: pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java?rev=1881063&r1=1881062&r2=1881063&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/image/ValidateXImage.java Fri Aug 21 17:21:09 2020
@@ -15,15 +15,24 @@
*/
package org.apache.pdfbox.pdmodel.graphics.image;
+import java.awt.Point;
+import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorConvertOp;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
+import java.util.Hashtable;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageWriterSpi;
+import static junit.framework.TestCase.assertEquals;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -32,7 +41,6 @@ import org.apache.pdfbox.pdmodel.PDPageC
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
-import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
@@ -155,6 +163,9 @@ public class ValidateXImage
{
String errMsg = "";
+ expectedImage = convertToSRGB(expectedImage);
+ actualImage = convertToSRGB(actualImage);
+
int w = expectedImage.getWidth();
int h = expectedImage.getHeight();
assertEquals(w, actualImage.getWidth());
@@ -171,7 +182,73 @@ public class ValidateXImage
}
}
}
-
+ public static BufferedImage convertToSRGB(BufferedImage image)
+ {
+ // The image is already sRGB - we don't need to do anything
+ if (image.getColorModel().getColorSpace().isCS_sRGB())
+ {
+ return image;
+ }
+ // 16-Bit images need to converted to 8 bit first, to avoid rounding differences
+ if (image.getRaster().getDataBuffer().getDataType() == DataBuffer.TYPE_USHORT)
+ {
+ final int width = image.getWidth();
+ final boolean hasAlpha = image.getColorModel().hasAlpha();
+
+ final DirectColorModel colorModel = new DirectColorModel(
+ image.getColorModel().getColorSpace(), 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000,
+ false, DataBuffer.TYPE_INT);
+ WritableRaster targetRaster = Raster
+ .createPackedRaster(DataBuffer.TYPE_INT, image.getWidth(), image.getHeight(),
+ colorModel.getMasks(), new Point(0, 0));
+ BufferedImage image8Bit = new BufferedImage(colorModel, targetRaster, false,
+ new Hashtable<String, Object>());
+
+ WritableRaster sourceRaster = image.getRaster();
+
+ final int numShortPixelElements = hasAlpha ? 3 : 4;
+ // 3 or 4 short per pixel
+ short[] pixelShort = new short[numShortPixelElements * width];
+ // Packed RGB
+ int[] pixelInt = new int[width];
+ for (int y = 0; y < image.getHeight(); y++)
+ {
+ sourceRaster.getDataElements(0, y, width, 1, pixelShort);
+ int ptrShort = 0;
+ for (int x = 0; x < width; x++)
+ {
+ int r = pixelShort[ptrShort++] & 0xFFFF;
+ int g = pixelShort[ptrShort++] & 0xFFFF;
+ int b = pixelShort[ptrShort++] & 0xFFFF;
+ if (hasAlpha)
+ ptrShort++;
+
+ // We devide using a float exactly the same way as SampledImageReader
+ // to get from 16 bit to 8 bit sample values
+ int r8bit = convert16To8Bit(r);
+ int g8bit = convert16To8Bit(g);
+ int b8bit = convert16To8Bit(b);
+ int v = r8bit | (g8bit << 8) | (b8bit << 16) | 0xFF000000;
+ pixelInt[x] = v;
+ }
+ targetRaster.setDataElements(0, y, width, 1, pixelInt);
+
+ }
+ image = image8Bit;
+
+ }
+
+ BufferedImage destination = new BufferedImage(image.getWidth(), image.getHeight(),
+ BufferedImage.TYPE_INT_RGB);
+ ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null);
+ return op.filter(image, destination);
+ }
+
+ private static int convert16To8Bit(int v)
+ {
+ float output = (float) v / (float) 0xFFFF;
+ return Math.round(output * 0xFF);
+ }
}