From 4c739e3b7758ad6cd8e0d5b51aaf6f953b74c3e7 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 7 Feb 2011 08:39:46 +0000 Subject: [PATCH] Use BitmapImageUtil for converting images to bi-level images. Allow to indirectly configure the dithering quality to be applied when converting images to bi-level images. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1067881 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/pcl/PCLDocumentHandler.java | 8 ++- .../apache/fop/render/pcl/PCLGenerator.java | 70 ++++++------------- .../render/pcl/PCLImageHandlerGraphics2D.java | 1 + .../fop/render/pcl/PCLRenderingMode.java | 20 ++++-- .../fop/render/pcl/PCLRenderingUtil.java | 12 ++++ 5 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java index ff0d5c9de..5af0fd179 100644 --- a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java +++ b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java @@ -88,6 +88,7 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler } /** {@inheritDoc} */ + @Override public void setContext(IFContext context) { super.setContext(context); this.pclUtil = new PCLRenderingUtil(context.getUserAgent()); @@ -99,6 +100,7 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler } /** {@inheritDoc} */ + @Override public void setDefaultFontInfo(FontInfo fontInfo) { FontInfo fi = Java2DUtil.buildDefaultJava2DBasedFontInfo(fontInfo, getUserAgent()); setFontInfo(fi); @@ -114,7 +116,7 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler /** @return the target resolution */ protected int getResolution() { - int resolution = (int)Math.round(getUserAgent().getTargetResolution()); + int resolution = Math.round(getUserAgent().getTargetResolution()); if (resolution <= 300) { return 300; } else { @@ -125,10 +127,12 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler //---------------------------------------------------------------------------------------------- /** {@inheritDoc} */ + @Override public void startDocument() throws IFException { super.startDocument(); try { this.gen = new PCLGenerator(this.outputStream, getResolution()); + this.gen.setDitheringQuality(pclUtil.getDitheringQuality()); if (!pclUtil.isPJLDisabled()) { gen.universalEndOfLanguage(); @@ -148,10 +152,12 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler } /** {@inheritDoc} */ + @Override public void endDocumentHeader() throws IFException { } /** {@inheritDoc} */ + @Override public void endDocument() throws IFException { try { gen.separateJobs(); diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java index f89c03add..29fe77323 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java +++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java @@ -49,7 +49,6 @@ import org.apache.xmlgraphics.util.UnitConv; import org.apache.fop.util.bitmap.BitmapImageUtil; import org.apache.fop.util.bitmap.DitherUtil; -import org.apache.fop.util.bitmap.MonochromeBitmapConverter; /** * This class provides methods for generating PCL print files. @@ -76,6 +75,7 @@ public class PCLGenerator { private boolean currentPatternTransparency = true; private int maxBitmapResolution = PCL_RESOLUTIONS[PCL_RESOLUTIONS.length - 1]; + private float ditheringQuality = 0.5f; /** * true: Standard PCL shades are used (poor quality). false: user-defined pattern are used @@ -540,6 +540,24 @@ public class PCLGenerator { writeCommand("*v" + pattern + "T"); } + /** + * Sets the dithering quality used when encoding gray or color images. If not explicitely + * set a medium setting (0.5f) is used. + * @param quality a quality setting between 0.0f (worst/fastest) and 1.0f (best/slowest) + */ + public void setDitheringQuality(float quality) { + quality = Math.min(Math.max(0f, quality), 1.0f); + this.ditheringQuality = quality; + } + + /** + * Returns the dithering quality used when encoding gray or color images. + * @return the quality setting between 0.0f (worst/fastest) and 1.0f (best/slowest) + */ + public float getDitheringQuality() { + return this.ditheringQuality; + } + /** * Indicates whether an image is a monochrome (b/w) image. * @param img the image @@ -547,7 +565,7 @@ public class PCLGenerator { */ public static boolean isMonochromeImage(RenderedImage img) { return BitmapImageUtil.isMonochromeImage(img); - } + } /** * Indicates whether an image is a grayscale image. @@ -618,18 +636,6 @@ public class PCLGenerator { return resolution == calculatePCLResolution(resolution); } - private Dimension getAdjustedDimension(Dimension orgDim, double orgResolution, - int pclResolution) { - if (orgResolution == pclResolution) { - return orgDim; - } else { - Dimension result = new Dimension(); - result.width = (int)Math.round((double)orgDim.width * pclResolution / orgResolution); - result.height = (int)Math.round((double)orgDim.height * pclResolution / orgResolution); - return result; - } - } - //Threshold table to convert an alpha channel (8-bit) into a clip mask (1-bit) private static final byte[] THRESHOLD_TABLE = new byte[256]; static { // Initialize the arrays @@ -724,34 +730,8 @@ public class PCLGenerator { popCursorPos(); } - BufferedImage src = null; - if (img instanceof BufferedImage && !scaled) { - if (!isGrayscaleImage(img) || img.getColorModel().hasAlpha()) { - /* Disabled as this doesn't work reliably, use the fallback below - src = new BufferedImage(effDim.width, effDim.height, - BufferedImage.TYPE_BYTE_GRAY); - Graphics2D g2d = src.createGraphics(); - try { - clearBackground(g2d, effDim); - } finally { - g2d.dispose(); - } - ColorConvertOp op = new ColorConvertOp( - ColorSpace.getInstance(ColorSpace.CS_GRAY), null); - op.filter((BufferedImage)img, src); - */ - } else { - src = (BufferedImage)img; - } - } - if (src == null) { - src = BitmapImageUtil.convertToGrayscale(img, effDim); - } - MonochromeBitmapConverter converter - = BitmapImageUtil.createDefaultMonochromeBitmapConverter(); - converter.setHint("quality", "false"); - - RenderedImage red = converter.convertToMonochrome(src); + RenderedImage red = BitmapImageUtil.convertToMonochrome( + img, effDim, this.ditheringQuality); selectCurrentPattern(0, 0); //Solid black setTransparencyMode(sourceTransparency || mask != null, true); paintMonochromeBitmap(red, effResolution); @@ -766,12 +746,6 @@ public class PCLGenerator { } } - private void clearBackground(Graphics2D g2d, Dimension effDim) { - //white background - g2d.setBackground(Color.WHITE); - g2d.clearRect(0, 0, effDim.width, effDim.height); - } - private int toGray(int rgb) { // see http://www.jguru.com/faq/view.jsp?EID=221919 double greyVal = 0.072169d * (rgb & 0xff); diff --git a/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java index f7bb33f68..25249caf6 100644 --- a/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java +++ b/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java @@ -85,6 +85,7 @@ public class PCLImageHandlerGraphics2D implements ImageHandler { boolean painted = false; ByteArrayOutputStream baout = new ByteArrayOutputStream(); PCLGenerator tempGen = new PCLGenerator(baout, gen.getMaximumBitmapResolution()); + tempGen.setDitheringQuality(gen.getDitheringQuality()); try { GraphicContext ctx = (GraphicContext)pclContext.getGraphicContext().clone(); diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderingMode.java b/src/java/org/apache/fop/render/pcl/PCLRenderingMode.java index 2fac1d13f..6201197cf 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderingMode.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderingMode.java @@ -30,23 +30,26 @@ public final class PCLRenderingMode implements Serializable { private static final long serialVersionUID = 6359884255324755026L; /** "Quality" rendering (mixed native and bitmap for improved quality) */ - public static final PCLRenderingMode QUALITY = new PCLRenderingMode("quality"); + public static final PCLRenderingMode QUALITY = new PCLRenderingMode("quality", 1.0f); /** "Speed" rendering (maximum speed with native rendering, reduced visual quality) */ - public static final PCLRenderingMode SPEED = new PCLRenderingMode("speed"); + public static final PCLRenderingMode SPEED = new PCLRenderingMode("speed", 0.25f); /** * "Bitmap" rendering (pages are painted entirely as bitmaps, maximum quality, * reduced performance) */ - public static final PCLRenderingMode BITMAP = new PCLRenderingMode("bitmap"); + public static final PCLRenderingMode BITMAP = new PCLRenderingMode("bitmap", 1.0f); private String name; + private float defaultDitheringQuality; /** * Constructor to add a new named item. * @param name Name of the item. + * @param defaultDitheringQuality the default dithering quality (0.0f..1.0f) */ - private PCLRenderingMode(String name) { + private PCLRenderingMode(String name, float defaultDitheringQuality) { this.name = name; + this.defaultDitheringQuality = defaultDitheringQuality; } /** @return the name of the enum */ @@ -54,6 +57,14 @@ public final class PCLRenderingMode implements Serializable { return this.name; } + /** + * Returns the default dithering quality for this rendering mode. + * @return the default dithering quality (0.0f..1.0f) + */ + public float getDefaultDitheringQuality() { + return this.defaultDitheringQuality; + } + /** * Returns the enumeration/singleton object based on its name. * @param name the name of the enumeration value @@ -76,6 +87,7 @@ public final class PCLRenderingMode implements Serializable { } /** {@inheritDoc} */ + @Override public String toString() { return "PCLRenderingMode:" + name; } diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java b/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java index a02a64717..e01bcdc5f 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java @@ -47,6 +47,9 @@ public class PCLRenderingUtil { */ private PCLRenderingMode renderingMode = PCLRenderingMode.SPEED; + /** Controls the dithering quality when rendering gray or color images. */ + private float ditheringQuality = 0.5f; + /** * Controls whether all text should be painted as text. This is a fallback setting in case * the mixture of native and bitmapped text does not provide the necessary quality. @@ -88,6 +91,7 @@ public class PCLRenderingUtil { */ public void setRenderingMode(PCLRenderingMode mode) { this.renderingMode = mode; + this.ditheringQuality = mode.getDefaultDitheringQuality(); } /** @@ -98,6 +102,14 @@ public class PCLRenderingUtil { return this.renderingMode; } + /** + * Returns the dithering quality to be used when encoding gray or color images. + * @return the quality (0.0f..1.0f) + */ + public float getDitheringQuality() { + return this.ditheringQuality; + } + /** * Controls whether PJL commands shall be generated by the PCL renderer. * @param disable true to disable PJL commands -- 2.39.5