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 2018/02/14 16:37:07 UTC
svn commit: r1824259 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java
Author: tilman
Date: Wed Feb 14 16:37:07 2018
New Revision: 1824259
URL: http://svn.apache.org/viewvc?rev=1824259&view=rev
Log:
PDFBOX-4095, PDFBOX-3000: to solve the problem that some blend modes don't work on the page background, render pages that have blending on a temporary transparent ARGB image and draw that one on the target image initialized with a white background, as suggested by Jani Pehkonen
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java?rev=1824259&r1=1824258&r2=1824259&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java Wed Feb 14 16:37:07 2018
@@ -20,9 +20,13 @@ import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
+import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
+import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
/**
* Renders a PDF document to an AWT BufferedImage.
@@ -114,20 +118,30 @@ public class PDFRenderer
int heightPx = Math.round(heightPt * scale);
int rotationAngle = page.getRotation();
+ int bimType = imageType.toBufferedImageType();
+ if (imageType != ImageType.ARGB && hasBlendMode(page))
+ {
+ // PDFBOX-4095: if the PDF has blending on the top level, draw on transparent background
+ // Inpired from PDF.js: if a PDF page uses any blend modes other than Normal,
+ // PDF.js renders everything on a fully transparent RGBA canvas.
+ // Finally when the page has been rendered, PDF.js draws the RGBA canvas on a white canvas.
+ bimType = BufferedImage.TYPE_INT_ARGB;
+ }
+
// swap width and height
BufferedImage image;
if (rotationAngle == 90 || rotationAngle == 270)
{
- image = new BufferedImage(heightPx, widthPx, imageType.toBufferedImageType());
+ image = new BufferedImage(heightPx, widthPx, bimType);
}
else
{
- image = new BufferedImage(widthPx, heightPx, imageType.toBufferedImageType());
+ image = new BufferedImage(widthPx, heightPx, bimType);
}
- // use a transparent background if the imageType supports alpha
+ // use a transparent background if the image type supports alpha
Graphics2D g = image.createGraphics();
- if (imageType == ImageType.ARGB)
+ if (image.getType() == BufferedImage.TYPE_INT_ARGB)
{
g.setBackground(new Color(0, 0, 0, 0));
}
@@ -146,6 +160,19 @@ public class PDFRenderer
g.dispose();
+ if (image.getType() != imageType.toBufferedImageType())
+ {
+ // PDFBOX-4095: draw temporary transparent image on white background
+ BufferedImage newImage =
+ new BufferedImage(image.getWidth(), image.getHeight(), imageType.toBufferedImageType());
+ Graphics2D dstGraphics = newImage.createGraphics();
+ dstGraphics.setBackground(Color.WHITE);
+ dstGraphics.clearRect(0, 0, image.getWidth(), image.getHeight());
+ dstGraphics.drawImage(image, 0, 0, null);
+ dstGraphics.dispose();
+ image = newImage;
+ }
+
return image;
}
@@ -224,4 +251,30 @@ public class PDFRenderer
{
return new PageDrawer(parameters);
}
+
+ private boolean hasBlendMode(PDPage page)
+ {
+ // check the current resources for blend modes
+ PDResources resources = page.getResources();
+ if (resources == null)
+ {
+ return false;
+ }
+ for (COSName name : resources.getExtGStateNames())
+ {
+ PDExtendedGraphicsState extGState = resources.getExtGState(name);
+ if (extGState == null)
+ {
+ // can happen if key exists but no value
+ // see PDFBOX-3950-23EGDHXSBBYQLKYOKGZUOVYVNE675PRD.pdf
+ continue;
+ }
+ BlendMode blendMode = extGState.getBlendMode();
+ if (blendMode != BlendMode.NORMAL)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}