From: Jeremias Maerki Date: Thu, 27 May 2010 19:20:54 +0000 (+0000) Subject: Big encoding performance improvement for bi-level images which do not have the right... X-Git-Tag: fop-1_0~29 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ecdba569b1fa3e0858f5bfea7483b689591ea878;p=xmlgraphics-fop.git 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 --- 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();