diff options
author | Jeremias Maerki <jeremias@apache.org> | 2009-10-23 13:33:18 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2009-10-23 13:33:18 +0000 |
commit | 6eb07eba36213cbe885295785041033124ec257d (patch) | |
tree | c8db430deca1dda8a38fee5b41b156be50188113 | |
parent | 9c7a867efc15bd1bf181bd747ae4567598ba14d0 (diff) | |
download | xmlgraphics-fop-6eb07eba36213cbe885295785041033124ec257d.tar.gz xmlgraphics-fop-6eb07eba36213cbe885295785041033124ec257d.zip |
Added support for encoding CMYK bitmap images (IOCA FS45) and TIFF images as embedded objects.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@829057 13f79535-47bb-0310-9956-ffa450edef68
15 files changed, 330 insertions, 78 deletions
diff --git a/src/java/org/apache/fop/afp/AFPDataObjectFactory.java b/src/java/org/apache/fop/afp/AFPDataObjectFactory.java index f6de7b5b4..792909b9e 100644 --- a/src/java/org/apache/fop/afp/AFPDataObjectFactory.java +++ b/src/java/org/apache/fop/afp/AFPDataObjectFactory.java @@ -24,6 +24,7 @@ import java.awt.geom.Rectangle2D; import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.fop.afp.ioca.IDEStructureParameter; import org.apache.fop.afp.ioca.ImageContent; import org.apache.fop.afp.modca.AbstractDataObject; import org.apache.fop.afp.modca.AbstractNamedAFPObject; @@ -113,12 +114,35 @@ public class AFPDataObjectFactory { } } - if (imageObjectInfo.isColor()) { - imageObj.setIDESize((byte) 24); - } else { - imageObj.setIDESize((byte) imageObjectInfo.getBitsPerPixel()); + ImageContent content = imageObj.getImageSegment().getImageContent(); + int bitsPerPixel = imageObjectInfo.getBitsPerPixel(); + imageObj.setIDESize((byte) bitsPerPixel); + IDEStructureParameter ideStruct; + switch (bitsPerPixel) { + case 1: + //Skip IDE Structure Parameter + break; + case 4: + case 8: + ideStruct = content.needIDEStructureParameter(); + ideStruct.setBitsPerComponent(new int[] {bitsPerPixel}); + break; + case 24: + ideStruct = content.needIDEStructureParameter(); + ideStruct.setDefaultRGBColorModel(); + break; + case 32: + ideStruct = content.needIDEStructureParameter(); + ideStruct.setDefaultCMYKColorModel(); + break; + default: + throw new IllegalArgumentException("Unsupported number of bits per pixel: " + + bitsPerPixel); + } + if (imageObjectInfo.isSubtractive()) { + ideStruct = content.needIDEStructureParameter(); + ideStruct.setSubtractive(imageObjectInfo.isSubtractive()); } - imageObj.setSubtractive(imageObjectInfo.isSubtractive()); imageObj.setData(imageObjectInfo.getData()); diff --git a/src/java/org/apache/fop/afp/AFPPaintingState.java b/src/java/org/apache/fop/afp/AFPPaintingState.java index 578924d67..643dcb702 100644 --- a/src/java/org/apache/fop/afp/AFPPaintingState.java +++ b/src/java/org/apache/fop/afp/AFPPaintingState.java @@ -46,8 +46,10 @@ implements Cloneable { /** color image support */ private boolean colorImages = false; - /** images are supported in this AFP environment */ + /** true if certain image formats may be embedded unchanged in their native format. */ private boolean nativeImagesSupported = false; + /** true if CMYK images (requires IOCA FS45 suppport on the target platform) may be generated */ + private boolean cmykImagesSupported; /** default value for image depth */ private int bitsPerPixel = 8; @@ -64,6 +66,7 @@ implements Cloneable { /** a unit converter */ private final transient AFPUnitConverter unitConv = new AFPUnitConverter(this); + /** * Sets the rotation to be used for portrait pages, valid values are 0 * (default), 90, 180, 270. @@ -186,6 +189,24 @@ implements Cloneable { } /** + * Controls whether CMYK images (IOCA FS45) are enabled. By default, support is disabled + * for wider compatibility. When disabled, any CMYK image is converted to the selected + * color format. + * @param value true to enabled CMYK images + */ + public void setCMYKImagesSupported(boolean value) { + this.cmykImagesSupported = value; + } + + /** + * Indicates whether CMYK images (IOCA FS45) are enabled. + * @return true if IOCA FS45 is enabled + */ + public boolean isCMYKImagesSupported() { + return this.cmykImagesSupported; + } + + /** * Sets the output/device resolution * * @param resolution diff --git a/src/java/org/apache/fop/afp/ioca/IDEStructureParameter.java b/src/java/org/apache/fop/afp/ioca/IDEStructureParameter.java new file mode 100644 index 000000000..8c0d0d49a --- /dev/null +++ b/src/java/org/apache/fop/afp/ioca/IDEStructureParameter.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.afp.ioca; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Streamable; + +/** + * This class represents the IOCA IDE Structure parameter (X'9B'). + */ +public class IDEStructureParameter implements Streamable { + + /** The RGB color model used by the IDE Structure parameter */ + public static final byte COLOR_MODEL_RGB = (byte)0x01; + /** The YCrCb color model used by the IDE Structure parameter */ + public static final byte COLOR_MODEL_YCRCB = (byte)0x02; + /** The CMYK color model used by the IDE Structure parameter */ + public static final byte COLOR_MODEL_CMYK = (byte)0x04; + /** The YCbCr color model used by the IDE Structure parameter */ + public static final byte COLOR_MODEL_YCBCR = (byte)0x12; + + /** additive/subtractive setting for ASFLAG */ + private boolean subtractive = false; + + /** setting for GRAYCODE flag */ + private boolean grayCoding = false; + + /** the image color model */ + private byte colorModel = COLOR_MODEL_RGB; + + /** the array with the number of bits/IDE for each component */ + private byte[] bitsPerIDE = new byte[] {(byte)1}; //1-bit by default + + /** + * Creates a new IDE Structure parameter. The values are initialized for a bi-level image + * using the RGB color model. + */ + public IDEStructureParameter() { + //nop + } + + /** + * Sets the image IDE color model. + * + * @param color the IDE color model. + */ + public void setColorModel(byte color) { + this.colorModel = color; + } + + /** + * Establishes the parameter values for the normal RGB 24bit color model. + */ + public void setDefaultRGBColorModel() { + this.colorModel = COLOR_MODEL_RGB; + setUniformBitsPerComponent(3, 8); + } + + /** + * Establishes the parameter values for the normal CMYK 32bit color model. + */ + public void setDefaultCMYKColorModel() { + this.colorModel = COLOR_MODEL_CMYK; + setUniformBitsPerComponent(4, 8); + } + + /** + * Sets + * @param numComponents + * @param bitsPerComponent + */ + public void setUniformBitsPerComponent(int numComponents, int bitsPerComponent) { + if (bitsPerComponent < 0 || bitsPerComponent >= 256) { + throw new IllegalArgumentException( + "The number of bits per component must be between 0 and 255"); + } + this.bitsPerIDE = new byte[numComponents]; + for (int i = 0; i < numComponents; i++) { + this.bitsPerIDE[i] = (byte)bitsPerComponent; + } + } + + /** + * Sets the array for the bits/IDE, one entry per component. + * @param bitsPerComponent the + */ + public void setBitsPerComponent(int[] bitsPerComponent) { + int numComponents = bitsPerComponent.length; + this.bitsPerIDE = new byte[numComponents]; + for (int i = 0; i < numComponents; i++) { + int bits = bitsPerComponent[i]; + if (bits < 0 || bits >= 256) { + throw new IllegalArgumentException( + "The number of bits per component must be between 0 and 255"); + } + this.bitsPerIDE[i] = (byte)bits; + } + } + + /** + * Set either additive or subtractive mode (used for ASFLAG). + * @param subtractive true for subtractive mode, false for additive mode + */ + public void setSubtractive(boolean subtractive) { + this.subtractive = subtractive; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + int length = 7 + bitsPerIDE.length; + + byte flags = 0x00; + if (subtractive) { + flags |= 1 << 7; + } + if (grayCoding) { + flags |= 1 << 6; + } + + DataOutputStream dout = new DataOutputStream(os); + dout.writeByte(0x9B); //ID + dout.writeByte(length - 2); //LENGTH + dout.writeByte(flags); //FLAGS + dout.writeByte(this.colorModel); //FORMAT + for (int i = 0; i < 3; i++) { + dout.writeByte(0); //RESERVED + } + dout.write(this.bitsPerIDE); //component sizes + } + +} diff --git a/src/java/org/apache/fop/afp/ioca/ImageContent.java b/src/java/org/apache/fop/afp/ioca/ImageContent.java index fe902b381..9c06589e0 100644 --- a/src/java/org/apache/fop/afp/ioca/ImageContent.java +++ b/src/java/org/apache/fop/afp/ioca/ImageContent.java @@ -56,21 +56,18 @@ public class ImageContent extends AbstractStructuredObject { /** the image size parameter */ private ImageSizeParameter imageSizeParameter = null; + /** the IDE Structure parameter */ + private IDEStructureParameter ideStructureParameter = null; + /** the image encoding */ private byte encoding = (byte)0x03; - /** the image ide size */ - private byte size = 1; + /** the image IDE (Image Data Element, Sample) size */ + private byte ideSize = 1; /** the image compression */ private byte compression = (byte)0xC0; - /** the image color model */ - private byte colorModel = (byte)0x01; - - /** additive/subtractive setting for ASFLAG */ - private boolean subtractive = false; - /** the image data */ private byte[] data; @@ -90,6 +87,34 @@ public class ImageContent extends AbstractStructuredObject { } /** + * Sets the IDE Structure parameter. + * @param parameter the IDE Structure parameter + */ + public void setIDEStructureParameter(IDEStructureParameter parameter) { + this.ideStructureParameter = parameter; + } + + /** + * Returns the (optional) IDE Structure parameter + * @return the IDE Structure parameter or null if none is set + */ + public IDEStructureParameter getIDEStructureParameter() { + return this.ideStructureParameter; + } + + /** + * Returns the (optional) IDE Structure parameter. If none is set an instance is prepared + * with defaults for a bi-level image. + * @return the IDE Structure parameter + */ + public IDEStructureParameter needIDEStructureParameter() { + if (this.ideStructureParameter == null) { + setIDEStructureParameter(new IDEStructureParameter()); + } + return getIDEStructureParameter(); + } + + /** * Sets the image encoding. * * @param enc The image encoding. @@ -113,24 +138,26 @@ public class ImageContent extends AbstractStructuredObject { * @param s The IDE size. */ public void setImageIDESize(byte s) { - this.size = s; + this.ideSize = s; } /** * Sets the image IDE color model. * * @param color the IDE color model. + * @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead */ public void setImageIDEColorModel(byte color) { - this.colorModel = color; + needIDEStructureParameter().setColorModel(color); } /** * Set either additive or subtractive mode (used for ASFLAG). * @param subtractive true for subtractive mode, false for additive mode + * @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead */ public void setSubtractive(boolean subtractive) { - this.subtractive = subtractive; + needIDEStructureParameter().setSubtractive(subtractive); } /** @@ -155,10 +182,12 @@ public class ImageContent extends AbstractStructuredObject { os.write(getImageIDESizeParameter()); - boolean useFS10 = (this.size == 1); - if (!useFS10) { - os.write(getIDEStructureParameter()); + if (getIDEStructureParameter() != null) { + getIDEStructureParameter().writeToStream(os); + } + boolean useFS10 = (this.ideSize == 1); + if (!useFS10) { os.write(getExternalAlgorithmParameter()); } @@ -243,58 +272,15 @@ public class ImageContent extends AbstractStructuredObject { * @return byte[] The data stream. */ private byte[] getImageIDESizeParameter() { - if (size != 1) { + if (ideSize != 1) { final byte[] ideSizeData = new byte[] { (byte)0x96, // ID 0x01, // Length - size}; + ideSize}; return ideSizeData; } else { return new byte[0]; } } - /** - * Helper method to return the external algorithm parameter. - * - * @return byte[] The data stream. - */ - private byte[] getIDEStructureParameter() { - byte flags = 0x00; - if (subtractive) { - flags |= 1 << 7; - } - if (colorModel != 0 && size == 24) { - final byte bits = (byte)(size / 3); - final byte[] ideStructData = new byte[] { - (byte)0x9B, // ID - 0x00, // Length - flags, // FLAGS - colorModel, // COLOR MODEL - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Reserved - bits, - bits, - bits, - }; - ideStructData[1] = (byte)(ideStructData.length - 2); - return ideStructData; - } else if (size == 1) { - final byte[] ideStructData = new byte[] { - (byte)0x9B, // ID - 0x00, // Length - flags, // FLAGS - colorModel, // COLOR MODEL - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Reserved - 0x01 - }; - ideStructData[1] = (byte)(ideStructData.length - 2); - return ideStructData; - } - return new byte[0]; - } - } diff --git a/src/java/org/apache/fop/afp/ioca/ImageSegment.java b/src/java/org/apache/fop/afp/ioca/ImageSegment.java index d8ba38ec0..9965bb94a 100644 --- a/src/java/org/apache/fop/afp/ioca/ImageSegment.java +++ b/src/java/org/apache/fop/afp/ioca/ImageSegment.java @@ -56,7 +56,11 @@ public class ImageSegment extends AbstractNamedAFPObject { this.factory = factory; } - private ImageContent getImageContent() { + /** + * Returns the image content object associated with this image segment. + * @return the image content + */ + public ImageContent getImageContent() { if (imageContent == null) { this.imageContent = factory.createImageContent(); } @@ -108,6 +112,7 @@ public class ImageSegment extends AbstractNamedAFPObject { * Sets the image IDE color model. * * @param colorModel the IDE color model. + * @deprecated Use {@link IDEStructureParameter#setColorModel(byte)} instead. */ public void setIDEColorModel(byte colorModel) { getImageContent().setImageIDEColorModel(colorModel); @@ -116,6 +121,7 @@ public class ImageSegment extends AbstractNamedAFPObject { /** * Set either additive or subtractive mode (used for ASFLAG). * @param subtractive true for subtractive mode, false for additive mode + * @deprecated Use {@link IDEStructureParameter#setSubtractive(boolean)} instead. */ public void setSubtractive(boolean subtractive) { getImageContent().setSubtractive(subtractive); @@ -124,7 +130,7 @@ public class ImageSegment extends AbstractNamedAFPObject { /** * Set the data image data. * - * @param data the image data + * @param imageData the image data */ public void setData(byte[] imageData) { getImageContent().setImageData(imageData); diff --git a/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java index 0f99d6624..38c60d7b6 100644 --- a/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java +++ b/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java @@ -79,6 +79,8 @@ public class ContainerDataDescriptor extends AbstractDescriptor { data[18] = ysize[0]; data[19] = ysize[1]; data[20] = ysize[2]; + + os.write(data); } } diff --git a/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java index 0a7b665d7..386d2f40f 100644 --- a/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java +++ b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java @@ -31,6 +31,7 @@ public class ImageDataDescriptor extends AbstractDescriptor { public static final byte FUNCTION_SET_FS10 = 0x0A; public static final byte FUNCTION_SET_FS11 = 0x0B; + public static final byte FUNCTION_SET_FS45 = 45; private byte functionSet = FUNCTION_SET_FS11; // FCNSET = IOCA FS 11 diff --git a/src/java/org/apache/fop/afp/modca/ImageObject.java b/src/java/org/apache/fop/afp/modca/ImageObject.java index 65802f6ca..2f075ce33 100644 --- a/src/java/org/apache/fop/afp/modca/ImageObject.java +++ b/src/java/org/apache/fop/afp/modca/ImageObject.java @@ -24,9 +24,12 @@ import java.io.OutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.xmlgraphics.util.MimeConstants; + import org.apache.fop.afp.AFPDataObjectInfo; import org.apache.fop.afp.AFPImageObjectInfo; import org.apache.fop.afp.Factory; +import org.apache.fop.afp.ioca.IDEStructureParameter; import org.apache.fop.afp.ioca.ImageSegment; /** @@ -50,7 +53,11 @@ public class ImageObject extends AbstractDataObject { super(factory, name); } - private ImageSegment getImageSegment() { + /** + * Returns the image segment object associated with this image object. + * @return the image segment + */ + public ImageSegment getImageSegment() { if (imageSegment == null) { this.imageSegment = factory.createImageSegment(); } @@ -71,6 +78,8 @@ public class ImageObject extends AbstractDataObject { = factory.createImageDataDescriptor(dataWidth, dataHeight, dataWidthRes, dataHeightRes); if (imageObjectInfo.getBitsPerPixel() == 1) { imageDataDescriptor.setFunctionSet(ImageDataDescriptor.FUNCTION_SET_FS10); + } else if (MimeConstants.MIME_AFP_IOCA_FS45.equals(imageObjectInfo.getMimeType())) { + imageDataDescriptor.setFunctionSet(ImageDataDescriptor.FUNCTION_SET_FS45); } getObjectEnvironmentGroup().setDataDescriptor(imageDataDescriptor); getObjectEnvironmentGroup().setMapImageObject( @@ -110,6 +119,7 @@ public class ImageObject extends AbstractDataObject { * Sets the image IDE color model. * * @param colorModel the IDE color model. + * @deprecated Use {@link IDEStructureParameter#setColorModel(byte)} instead. */ public void setIDEColorModel(byte colorModel) { getImageSegment().setIDEColorModel(colorModel); @@ -118,6 +128,7 @@ public class ImageObject extends AbstractDataObject { /** * Set either additive or subtractive mode (used for ASFLAG). * @param subtractive true for subtractive mode, false for additive mode + * @deprecated Use {@link IDEStructureParameter#setSubtractive(boolean)} instead. */ public void setSubtractive(boolean subtractive) { getImageSegment().setSubtractive(subtractive); diff --git a/src/java/org/apache/fop/render/afp/AFPCustomizable.java b/src/java/org/apache/fop/render/afp/AFPCustomizable.java index ed1ea443b..5f3fe6823 100644 --- a/src/java/org/apache/fop/render/afp/AFPCustomizable.java +++ b/src/java/org/apache/fop/render/afp/AFPCustomizable.java @@ -51,6 +51,14 @@ public interface AFPCustomizable { void setNativeImagesSupported(boolean nativeImages); /** + * Controls whether CMYK images (IOCA FS45) are enabled. By default, support is disabled + * for wider compatibility. When disabled, any CMYK image is converted to the selected + * color format. + * @param value true to enabled CMYK images + */ + void setCMYKImagesSupported(boolean value); + + /** * Sets the shading mode for painting filled rectangles. * @param shadingMode the shading mode */ diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java index 1f7a732d1..3fec25d8d 100644 --- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java @@ -357,6 +357,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler } /** {@inheritDoc} */ + public void setCMYKImagesSupported(boolean value) { + paintingState.setCMYKImagesSupported(value); + } + + /** {@inheritDoc} */ public void setShadingMode(AFPShadingMode shadingMode) { this.shadingMode = shadingMode; } diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java index 99ede8e79..fcfc9c64c 100644 --- a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java @@ -24,6 +24,7 @@ import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS; import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; +import org.apache.xmlgraphics.util.MimeConstants; import org.apache.fop.afp.AFPDataObjectInfo; import org.apache.fop.render.RenderingContext; @@ -35,6 +36,7 @@ public class AFPImageHandlerRawStream extends AbstractAFPImageHandlerRawStream { private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { ImageFlavor.RAW_JPEG, + ImageFlavor.RAW_TIFF, ImageFlavor.RAW_EPS, }; @@ -63,7 +65,12 @@ public class AFPImageHandlerRawStream extends AbstractAFPImageHandlerRawStream { if (targetContext instanceof AFPRenderingContext) { AFPRenderingContext afpContext = (AFPRenderingContext)targetContext; return (afpContext.getPaintingState().isNativeImagesSupported()) - && (image == null || image instanceof ImageRawJPEG || image instanceof ImageRawEPS); + && (image == null + || image instanceof ImageRawJPEG + || image instanceof ImageRawEPS + || ((image instanceof ImageRawStream) + && (MimeConstants.MIME_TIFF.equals( + ((ImageRawStream)image).getMimeType())))); } return false; } diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java index 8f7918583..b0988e754 100644 --- a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java @@ -89,7 +89,11 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima int resolution = paintingState.getResolution(); int maxPixelSize = paintingState.getBitsPerPixel(); if (paintingState.isColorImages()) { - maxPixelSize *= 3; //RGB only at the moment + if (paintingState.isCMYKImagesSupported()) { + maxPixelSize *= 4; //CMYK is maximum + } else { + maxPixelSize *= 3; //RGB is maximum + } } RenderedImage renderedImage = imageRendered.getRenderedImage(); @@ -97,6 +101,7 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima ImageSize intrinsicSize = imageInfo.getSize(); boolean useFS10 = (maxPixelSize == 1) || BitmapImageUtil.isMonochromeImage(renderedImage); + int functionSet = useFS10 ? 10 : 11; boolean usePageSegments = useFS10 && !imageObjectInfo.getResourceInfo().getLevel().isInline(); @@ -124,11 +129,6 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima resampledDim.width, resampledDim.height, resolution); } } - if (useFS10) { - imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS10); - } else { - imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11); - } imageObjectInfo.setDataHeightRes((int)Math.round( effIntrinsicSize.getDpiHorizontal() * 10)); @@ -156,9 +156,9 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima byte[] imageData = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); boolean allowDirectEncoding = true; - if (allowDirectEncoding && pixelSize <= maxPixelSize) { + if (allowDirectEncoding && (pixelSize <= maxPixelSize)) { //Attempt to encode without resampling the image - ImageEncodingHelper helper = new ImageEncodingHelper(renderedImage); + ImageEncodingHelper helper = new ImageEncodingHelper(renderedImage, pixelSize == 32); ColorModel encodedColorModel = helper.getEncodedColorModel(); boolean directEncode = true; if (helper.getEncodedColorModel().getPixelSize() > maxPixelSize) { @@ -180,6 +180,9 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima log.trace("set subtractive mode"); imageObjectInfo.setSubtractive(true); } + if (pixelSize == 32) { + functionSet = 45; //IOCA FS45 required for CMYK + } helper.encode(baos); imageData = baos.toByteArray(); @@ -191,6 +194,7 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima //Convert image to 24bit RGB ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos); imageData = baos.toByteArray(); + imageObjectInfo.setBitsPerPixel(24); boolean colorImages = paintingState.isColorImages(); imageObjectInfo.setColor(colorImages); @@ -212,6 +216,20 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima } } + switch (functionSet) { + case 10: + imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS10); + break; + case 11: + imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11); + break; + case 45: + imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45); + break; + default: + throw new IllegalStateException("Invalid IOCA function set: " + functionSet); + } + imageObjectInfo.setData(imageData); // set object area info diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index f019c6a47..250ff9624 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -90,8 +90,8 @@ import org.apache.fop.render.afp.extensions.AFPElementMapping; import org.apache.fop.render.afp.extensions.AFPExtensionAttachment; 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; /** * This is an implementation of a FOP Renderer that renders areas to AFP. @@ -444,6 +444,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust ImageFlavor.XML_DOM, /*ImageFlavor.RAW_PNG, */ // PNG not natively supported in AFP ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS, + ImageFlavor.RAW_TIFF, ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE }; private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { @@ -831,6 +832,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust } /** {@inheritDoc} */ + public void setCMYKImagesSupported(boolean value) { + paintingState.setCMYKImagesSupported(value); + } + + /** {@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 49e51b3d1..1e15d4c72 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -318,6 +318,9 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator String imagesMode = imagesCfg.getAttribute("mode", IMAGES_MODE_GRAYSCALE); if (IMAGES_MODE_COLOR.equals(imagesMode)) { customizable.setColorImages(true); + + boolean cmyk = imagesCfg.getAttributeAsBoolean("cmyk", false); + customizable.setCMYKImagesSupported(cmyk); } else { customizable.setColorImages(false); // default to 8 bits per pixel diff --git a/status.xml b/status.xml index 2aab61b1e..31afd446b 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,9 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> <release version="FOP Trunk" date="TBD"> + <action context="Code" dev="JM" type="add"> + Added support for encoding CMYK bitmap images (IOCA FS45) and TIFF images as embedded objects. + </action> <action context="Code" dev="AC" type="add"> Added support for xmlfile and xsltfile parameters in FOP's Ant Task. </action> |