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/04/25 11:09:58 UTC

svn commit: r1876977 - /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java

Author: tilman
Date: Sat Apr 25 11:09:58 2020
New Revision: 1876977

URL: http://svn.apache.org/viewvc?rev=1876977&view=rev
Log:
PDFBOX-4516: pre-scale image because drawImage scales down in poor quality

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java?rev=1876977&r1=1876976&r2=1876977&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java Sat Apr 25 11:09:58 2020
@@ -22,6 +22,7 @@ import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsDevice;
+import java.awt.Image;
 import java.awt.Paint;
 import java.awt.Point;
 import java.awt.Rectangle;
@@ -1137,7 +1138,42 @@ public class PageDrawer extends PDFGraph
             imageTransform.translate(0, -height);
             if (isContentRendered())
             {
-                graphics.drawImage(image, imageTransform, null);
+                // PDFBOX-4516, PDFBOX-4527, PDFBOX-4815:
+                // graphics.drawImage() has terrible quality when scaling down, even when
+                // RenderingHints.VALUE_INTERPOLATION_BICUBIC, VALUE_ALPHA_INTERPOLATION_QUALITY,
+                // VALUE_COLOR_RENDER_QUALITY and VALUE_RENDER_QUALITY are all set.
+                // A workaround is to get a pre-scaled image with Image.getScaledInstance()
+                // and then draw that one. To reduce differences in testing
+                // (partly because the method needs integer parameters), only smaller scalings
+                // will trigger the workaround. Because of the slowness we only do it if the user
+                // expects quality rendering and interpolation.
+                Matrix m = new Matrix(imageTransform);
+                float scaleX = Math.abs(m.getScalingFactorX());
+                float scaleY = Math.abs(m.getScalingFactorY());
+                Image imageToDraw = image;
+
+                if ((scaleX < 0.25f || scaleY < 0.25f) &&
+                    RenderingHints.VALUE_RENDER_QUALITY.equals(graphics.getRenderingHint(RenderingHints.KEY_RENDERING)) &&
+                    RenderingHints.VALUE_INTERPOLATION_BICUBIC.equals(graphics.getRenderingHint(RenderingHints.KEY_INTERPOLATION)))
+                {
+                    System.out.println(graphics.getRenderingHints());
+                    int w = Math.round(image.getWidth() * scaleX);
+                    int h = Math.round(image.getHeight() * scaleY);
+                    if (w < 1)
+                    {
+                        w = 1;
+                    }
+                    if (h < 1)
+                    {
+                        h = 1;
+                    }
+                    imageToDraw = image.getScaledInstance(
+                            w,
+                            h,
+                            Image.SCALE_SMOOTH);
+                    imageTransform.scale(1 / scaleX, 1 / scaleY); // remove the scale
+                }
+                graphics.drawImage(imageToDraw, imageTransform, null);
             }
         }
     }