aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2010-06-12 08:19:48 +0000
committerJeremias Maerki <jeremias@apache.org>2010-06-12 08:19:48 +0000
commit97aa2c35b008616df914162cb398ee017cc5169c (patch)
tree9739e69937acb88c337e0707aebbe535f237d630 /src/java/org/apache
parent1fae69d5fdafcf8ba313087e5afa67d203af6482 (diff)
downloadxmlgraphics-fop-97aa2c35b008616df914162cb398ee017cc5169c.tar.gz
xmlgraphics-fop-97aa2c35b008616df914162cb398ee017cc5169c.zip
AFP Output Changes:
- Fixed positioning of Java2D-based images (when GOCA is enabled). GraphicsDataDescriptor had a bit order bug. The Graphics2D image handler didn't save state and reposition the image origin. - Switched bitmap image handling in AFPGraphics2D to (re-)use AFPImageHandlerRenderedImage so it can profit from it's advanced image conversion functionality. This also avoids some bugs with certain image formats. - Added enhanced dithering functionality for images that need to be converted to bi-level images. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@953952 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/afp/AFPGraphics2D.java108
-rw-r--r--src/java/org/apache/fop/afp/AFPPaintingState.java22
-rw-r--r--src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java4
-rw-r--r--src/java/org/apache/fop/render/afp/AFPCustomizable.java7
-rw-r--r--src/java/org/apache/fop/render/afp/AFPDocumentHandler.java7
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java9
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java8
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRenderer.java5
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java15
-rw-r--r--src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java47
10 files changed, 144 insertions, 88 deletions
diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java
index b8d7158cf..fa9c0d7bf 100644
--- a/src/java/org/apache/fop/afp/AFPGraphics2D.java
+++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java
@@ -45,7 +45,6 @@ import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.io.IOException;
-import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -56,8 +55,6 @@ import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
import org.apache.xmlgraphics.java2d.GraphicContext;
import org.apache.xmlgraphics.java2d.StrokingTextHandler;
import org.apache.xmlgraphics.java2d.TextHandler;
-import org.apache.xmlgraphics.ps.ImageEncodingHelper;
-import org.apache.xmlgraphics.util.MimeConstants;
import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.afp.goca.GraphicsSetLineType;
@@ -65,6 +62,8 @@ import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.afp.svg.AFPGraphicsConfiguration;
import org.apache.fop.afp.util.CubicBezierApproximator;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.render.afp.AFPImageHandlerRenderedImage;
+import org.apache.fop.render.afp.AFPRenderingContext;
import org.apache.fop.svg.NativeImageHandler;
/**
@@ -559,75 +558,6 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
BufferedImage.TYPE_INT_ARGB);
}
- private AFPImageObjectInfo createImageObjectInfo(
- RenderedImage img, int x, int y, int width, int height) throws IOException {
- ImageInfo imageInfo = new ImageInfo(null, "image/unknown");
- ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72);
- imageInfo.setSize(size);
-
- ImageRendered imageRendered = new ImageRendered(imageInfo, img, null);
- RenderedImage renderedImage = imageRendered.getRenderedImage();
-
- // create image object info
- AFPImageObjectInfo imageObjectInfo = new AFPImageObjectInfo();
-
- imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
-
- int bitsPerPixel = paintingState.getBitsPerPixel();
- imageObjectInfo.setBitsPerPixel(bitsPerPixel);
-
- imageObjectInfo.setResourceInfo(resourceInfo);
-
- int dataHeight = renderedImage.getHeight();
- imageObjectInfo.setDataHeight(dataHeight);
-
- int dataWidth = renderedImage.getWidth();
- imageObjectInfo.setDataWidth(dataWidth);
-
- int resolution = paintingState.getResolution();
- imageObjectInfo.setDataWidthRes(resolution);
- imageObjectInfo.setDataHeightRes(resolution);
-
- boolean colorImages = paintingState.isColorImages();
- imageObjectInfo.setColor(colorImages);
-
- ByteArrayOutputStream boas = new ByteArrayOutputStream();
- ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, boas);
- byte[] imageData = boas.toByteArray();
-
- // convert to grayscale
- if (!colorImages) {
- boas.reset();
- imageObjectInfo.setBitsPerPixel(bitsPerPixel);
- ImageEncodingHelper.encodeRGBAsGrayScale(
- imageData, dataWidth, dataHeight, bitsPerPixel, boas);
- imageData = boas.toByteArray();
- if (bitsPerPixel == 1) {
- //FS10 should generate a page seqment to avoid problems
- imageObjectInfo.setCreatePageSegment(true);
- }
- }
- imageObjectInfo.setData(imageData);
-
- if (imageInfo != null) {
- imageObjectInfo.setUri(imageInfo.getOriginalURI());
- }
-
- // create object area info
- AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
- objectAreaInfo.setX(x);
- objectAreaInfo.setY(y);
- objectAreaInfo.setWidth(width);
- objectAreaInfo.setHeight(height);
-
- objectAreaInfo.setWidthRes(resolution);
- objectAreaInfo.setHeightRes(resolution);
-
- imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
-
- return imageObjectInfo;
- }
-
/**
* Draws an AWT image into a BufferedImage using an AWT Graphics2D implementation
*
@@ -667,7 +597,6 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
/** {@inheritDoc} */
public boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer) {
-
// draw with AWT Graphics2D
Dimension imageSize = new Dimension(width, height);
BufferedImage bufferedImage = buildBufferedImage(imageSize);
@@ -684,20 +613,33 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();
- AffineTransform at = paintingState.getData().getTransform();
AffineTransform gat = gc.getTransform();
int graphicsObjectHeight
= graphicsObj.getObjectEnvironmentGroup().getObjectAreaDescriptor().getHeight();
- int x = (int)Math.round(at.getTranslateX() + gat.getTranslateX());
- int y = (int)Math.round(at.getTranslateY() - (gat.getTranslateY() - graphicsObjectHeight));
- int width = (int)Math.round(imgWidth * gat.getScaleX());
- int height = (int)Math.round(imgHeight * -gat.getScaleY());
+
+ double toMillipointFactor = UnitConv.IN2PT * 1000 / (double)paintingState.getResolution();
+ double x = gat.getTranslateX();
+ double y = -(gat.getTranslateY() - graphicsObjectHeight);
+ x = toMillipointFactor * x;
+ y = toMillipointFactor * y;
+ double w = toMillipointFactor * imgWidth * gat.getScaleX();
+ double h = toMillipointFactor * imgHeight * -gat.getScaleY();
+
+ AFPImageHandlerRenderedImage handler = new AFPImageHandlerRenderedImage();
+ ImageInfo imageInfo = new ImageInfo(null, null);
+ imageInfo.setSize(new ImageSize(
+ img.getWidth(), img.getHeight(), paintingState.getResolution()));
+ imageInfo.getSize().calcSizeFromPixels();
+ ImageRendered red = new ImageRendered(imageInfo, img, null);
+ Rectangle targetPos = new Rectangle(
+ (int)Math.round(x),
+ (int)Math.round(y),
+ (int)Math.round(w),
+ (int)Math.round(h));
+ AFPRenderingContext context = new AFPRenderingContext(null,
+ resourceManager, paintingState, fontInfo, null);
try {
- // get image object info
- AFPImageObjectInfo imageObjectInfo
- = createImageObjectInfo(img, x, y, width, height);
- // create image resource
- resourceManager.createObject(imageObjectInfo);
+ handler.handleImage(context, red, targetPos);
} catch (IOException ioe) {
handleIOException(ioe);
}
diff --git a/src/java/org/apache/fop/afp/AFPPaintingState.java b/src/java/org/apache/fop/afp/AFPPaintingState.java
index a19874183..4e314e5d9 100644
--- a/src/java/org/apache/fop/afp/AFPPaintingState.java
+++ b/src/java/org/apache/fop/afp/AFPPaintingState.java
@@ -51,6 +51,9 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
/** color image support */
private boolean colorImages = false;
+ /** dithering quality setting (0.0f..1.0f) */
+ private float ditheringQuality;
+
/** color image handler */
private ColorConverter colorConverter = GrayScaleColorConverter.getInstance();
@@ -234,6 +237,25 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
}
/**
+ * Gets the dithering quality setting to use when converting images to monochrome images.
+ * @return the dithering quality (a value between 0.0f and 1.0f)
+ */
+ public float getDitheringQuality() {
+ return this.ditheringQuality;
+ }
+
+ /**
+ * Sets the dithering quality setting to use when converting images to monochrome images.
+ * @param quality Defines the desired quality level for the conversion.
+ * Valid values: a value between 0.0f (fastest) and 1.0f (best)
+ */
+ public void setDitheringQuality(float quality) {
+ quality = Math.max(quality, 0.0f);
+ quality = Math.min(quality, 1.0f);
+ this.ditheringQuality = quality;
+ }
+
+ /**
* Sets the output/device resolution
*
* @param resolution
diff --git a/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java b/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java
index 5495e2e9c..5fa3b70a9 100644
--- a/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java
+++ b/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java
@@ -104,8 +104,8 @@ public class GraphicsDataDescriptor extends AbstractDescriptor {
return data;
}
- private static final int ABS = 2;
- private static final int IMGRES = 8;
+ private static final int ABS = 64;
+ private static final int IMGRES = 16;
/**
* Returns the window specification data
diff --git a/src/java/org/apache/fop/render/afp/AFPCustomizable.java b/src/java/org/apache/fop/render/afp/AFPCustomizable.java
index 5f3fe6823..93aaa8b1a 100644
--- a/src/java/org/apache/fop/render/afp/AFPCustomizable.java
+++ b/src/java/org/apache/fop/render/afp/AFPCustomizable.java
@@ -65,6 +65,13 @@ public interface AFPCustomizable {
void setShadingMode(AFPShadingMode shadingMode);
/**
+ * Sets the dithering quality setting to use when converting images to monochrome images.
+ * @param quality Defines the desired quality level for the conversion.
+ * Valid values: a value between 0.0f (fastest) and 1.0f (best)
+ */
+ void setDitheringQuality(float quality);
+
+ /**
* Sets the output/device resolution
*
* @param resolution
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index 3fec25d8d..21d4faf56 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -46,8 +46,8 @@ import org.apache.fop.fonts.FontManager;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
import org.apache.fop.render.afp.extensions.AFPIncludeFormMap;
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap;
-import org.apache.fop.render.afp.extensions.AFPPageSetup;
import org.apache.fop.render.afp.extensions.AFPPageOverlay;
+import org.apache.fop.render.afp.extensions.AFPPageSetup;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
@@ -362,6 +362,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ public void setDitheringQuality(float quality) {
+ this.paintingState.setDitheringQuality(quality);
+ }
+
+ /** {@inheritDoc} */
public void setShadingMode(AFPShadingMode shadingMode) {
this.shadingMode = shadingMode;
}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
index 32a95b445..aaaecf2ea 100644
--- a/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
@@ -20,6 +20,7 @@
package org.apache.fop.render.afp;
import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
import java.io.IOException;
import org.apache.xmlgraphics.image.loader.Image;
@@ -136,6 +137,12 @@ public class AFPImageHandlerGraphics2D extends AFPImageHandler implements ImageH
setDefaultResourceLevel(graphicsObjectInfo, afpContext.getResourceManager());
+ AFPPaintingState paintingState = afpContext.getPaintingState();
+ paintingState.save(); // save
+ AffineTransform placement = new AffineTransform();
+ placement.translate(pos.x, pos.y);
+ paintingState.concatenate(placement);
+
// Image content
ImageGraphics2D imageG2D = (ImageGraphics2D)image;
boolean textAsShapes = false; //TODO Make configurable
@@ -152,6 +159,8 @@ public class AFPImageHandlerGraphics2D extends AFPImageHandler implements ImageH
// Create image
afpContext.getResourceManager().createObject(graphicsObjectInfo);
+
+ paintingState.restore(); // resume
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
index 330f78d63..cb7b23da2 100644
--- a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
@@ -101,6 +101,7 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima
maxPixelSize *= 3; //RGB is maximum
}
}
+ float ditheringQuality = paintingState.getDitheringQuality();
RenderedImage renderedImage = imageRendered.getRenderedImage();
ImageInfo imageInfo = imageRendered.getInfo();
@@ -130,9 +131,13 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima
log.debug("Resample from " + intrinsicSize.getDimensionPx()
+ " to " + resampledDim);
}
- renderedImage = BitmapImageUtil.convertToMonochrome(renderedImage, resampledDim);
+ renderedImage = BitmapImageUtil.convertToMonochrome(renderedImage,
+ resampledDim, ditheringQuality);
effIntrinsicSize = new ImageSize(
resampledDim.width, resampledDim.height, resolution);
+ } else if (ditheringQuality >= 0.5f) {
+ renderedImage = BitmapImageUtil.convertToMonochrome(renderedImage,
+ intrinsicSize.getDimensionPx(), ditheringQuality);
}
}
@@ -157,7 +162,6 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima
if (cm.hasAlpha()) {
pixelSize -= 8;
}
- //TODO Add support for CMYK images
byte[] imageData = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index d88deadfe..1f373023c 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -839,6 +839,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust
}
/** {@inheritDoc} */
+ public void setDitheringQuality(float quality) {
+ this.paintingState.setDitheringQuality(quality);
+ }
+
+ /** {@inheritDoc} */
public void setShadingMode(AFPShadingMode shadingMode) {
this.shadingMode = shadingMode;
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index 23f413813..1720667df 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -390,6 +390,21 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
customizable.setBitsPerPixel(bitsPerPixel);
}
+ String dithering = imagesCfg.getAttribute("dithering-quality", "medium");
+ float dq = 0.5f;
+ if (dithering.startsWith("min")) {
+ dq = 0.0f;
+ } else if (dithering.startsWith("max")) {
+ dq = 1.0f;
+ } else {
+ try {
+ dq = Float.parseFloat(dithering);
+ } catch (NumberFormatException nfe) {
+ //ignore and leave the default above
+ }
+ }
+ customizable.setDitheringQuality(dq);
+
// native image support
boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false);
customizable.setNativeImagesSupported(nativeImageSupport);
diff --git a/src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java b/src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java
index cb46395ca..c08076316 100644
--- a/src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java
+++ b/src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java
@@ -135,6 +135,53 @@ public class BitmapImageUtil {
*/
public static final BufferedImage convertToMonochrome(RenderedImage img,
Dimension targetDimension) {
+ return toBufferedImage(convertToMonochrome(img, targetDimension, 0.0f));
+ }
+
+ /**
+ * Converts an image to a monochrome 1-bit image. Optionally, the image can be scaled.
+ * @param img the image to be converted
+ * @param targetDimension the new target dimensions or null if no scaling is necessary
+ * @param quality Defines the desired quality level for the conversion.
+ * Valid values: a value between 0.0f (fastest) and 1.0f (best)
+ * @return the monochrome image
+ */
+ public static final RenderedImage convertToMonochrome(RenderedImage img,
+ Dimension targetDimension, float quality) {
+ if (!isMonochromeImage(img)) {
+ if (quality >= 0.5f) {
+ BufferedImage bi;
+ Dimension orgDim = new Dimension(img.getWidth(), img.getHeight());
+ if (targetDimension != null && !orgDim.equals(targetDimension)) {
+ //Scale only before dithering
+ ColorModel cm = img.getColorModel();
+ BufferedImage tgt = new BufferedImage(cm,
+ cm.createCompatibleWritableRaster(
+ targetDimension.width, targetDimension.height),
+ cm.isAlphaPremultiplied(), null);
+ transferImage(img, tgt);
+ bi = tgt;
+ } else {
+ bi = toBufferedImage(img);
+ }
+ //Now convert to monochrome (dithering if available)
+ MonochromeBitmapConverter converter = createDefaultMonochromeBitmapConverter();
+ if (quality >= 0.8f) {
+ //Activates error diffusion if JAI is available
+ converter.setHint("quality", Boolean.TRUE.toString());
+ //Need to convert to grayscale first since otherwise, there may be encoding
+ //problems later with the images JAI can generate.
+ bi = convertToGrayscale(bi, targetDimension);
+ }
+ try {
+ return converter.convertToMonochrome(bi);
+ } catch (Exception e) {
+ //Provide a fallback if exotic formats are encountered
+ bi = convertToGrayscale(bi, targetDimension);
+ return converter.convertToMonochrome(bi);
+ }
+ }
+ }
return convertAndScaleImage(img, targetDimension, BufferedImage.TYPE_BYTE_BINARY);
}