diff options
author | Jeremias Maerki <jeremias@apache.org> | 2010-05-27 19:20:54 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2010-05-27 19:20:54 +0000 |
commit | ecdba569b1fa3e0858f5bfea7483b689591ea878 (patch) | |
tree | e76421b672ed1e1bd40115e6872dc0ea3f71448b /src | |
parent | 0e7b0816b0e8b30c21bd595d83ac977819fb74d2 (diff) | |
download | xmlgraphics-fop-ecdba569b1fa3e0858f5bfea7483b689591ea878.tar.gz xmlgraphics-fop-ecdba569b1fa3e0858f5bfea7483b689591ea878.zip |
Big encoding performance improvement for bi-level images which do not have the right bit order. Apparently, setting the subtractive option doesn't help with inverting a bi-level FS10 image.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@948959 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r-- | src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java index b0988e754..330f78d63 100644 --- a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java @@ -22,8 +22,12 @@ package org.apache.fop.render.afp; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.io.IOException; +import java.io.OutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; @@ -86,6 +90,8 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima AFPPaintingState paintingState, ImageRendered imageRendered, Dimension targetSize) throws IOException { + long start = System.currentTimeMillis(); + int resolution = paintingState.getResolution(); int maxPixelSize = paintingState.getBitsPerPixel(); if (paintingState.isColorImages()) { @@ -171,15 +177,15 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima && BitmapImageUtil.isMonochromeImage(renderedImage) && BitmapImageUtil.isZeroBlack(renderedImage)) { directEncode = false; + //need a special method to invert the bit-stream since setting the subtractive mode + //in AFP alone doesn't seem to do the trick. + if (encodeInvertedBilevel(helper, imageObjectInfo, baos)) { + imageData = baos.toByteArray(); + } } if (directEncode) { log.debug("Encoding image directly..."); imageObjectInfo.setBitsPerPixel(encodedColorModel.getPixelSize()); - if (BitmapImageUtil.isMonochromeImage(renderedImage) - && BitmapImageUtil.isZeroBlack(renderedImage)) { - log.trace("set subtractive mode"); - imageObjectInfo.setSubtractive(true); - } if (pixelSize == 32) { functionSet = 45; //IOCA FS45 required for CMYK } @@ -237,9 +243,58 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima objectAreaInfo.setWidthRes(resolution); objectAreaInfo.setHeightRes(resolution); + if (log.isDebugEnabled()) { + long duration = System.currentTimeMillis() - start; + log.debug("Image encoding took " + duration + "ms."); + } + return imageObjectInfo; } + /** + * Efficiently encodes a bi-level image in inverted form as a plain bit-stream. + * @param helper the image encoding helper used to analyze the image + * @param imageObjectInfo the AFP image object + * @param out the output stream + * @return true if the image was encoded, false if there was something prohibiting that + * @throws IOException if an I/O error occurs + */ + private boolean encodeInvertedBilevel(ImageEncodingHelper helper, + AFPImageObjectInfo imageObjectInfo, OutputStream out) throws IOException { + RenderedImage renderedImage = helper.getImage(); + if (!BitmapImageUtil.isMonochromeImage(renderedImage)) { + throw new IllegalStateException("This method only supports binary images!"); + } + int tiles = renderedImage.getNumXTiles() * renderedImage.getNumYTiles(); + if (tiles > 1) { + return false; + } + + imageObjectInfo.setBitsPerPixel(1); + + Raster raster = renderedImage.getTile(0, 0); + DataBuffer buffer = raster.getDataBuffer(); + if (buffer instanceof DataBufferByte) { + DataBufferByte byteBuffer = (DataBufferByte)buffer; + log.debug("Encoding image as inverted bi-level..."); + byte[] rawData = byteBuffer.getData(); + int remaining = rawData.length; + int pos = 0; + byte[] data = new byte[4096]; + while (remaining > 0) { + int size = Math.min(remaining, data.length); + for (int i = 0; i < size; i++) { + data[i] = (byte)~rawData[pos]; //invert bits + pos++; + } + out.write(data, 0, size); + remaining -= size; + } + return true; + } + return false; + } + private void setDefaultResourceLevel(AFPImageObjectInfo imageObjectInfo, AFPResourceManager resourceManager) { AFPResourceInfo resourceInfo = imageObjectInfo.getResourceInfo(); |