From c2b9bd06f74bdbb50b51297eb355bba5e0d83708 Mon Sep 17 00:00:00 2001 From: Keiron Liddle Date: Tue, 18 Sep 2001 08:17:08 +0000 Subject: [PATCH] Patch to handle direct embedding of jpeg images into pdf Submitted by: Eric Dalquist ebdalqui@mtu.edu Reviewed by: Keiron git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194467 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/image/AbstractFopImage.java | 18 ++- src/org/apache/fop/image/FopImageFactory.java | 4 +- .../{GifJpegImage.java => GifImage.java} | 13 +- src/org/apache/fop/image/JpegImage.java | 136 ++++++++++++++++++ src/org/apache/fop/pdf/DCTFilter.java | 35 +++++ src/org/apache/fop/pdf/PDFXObject.java | 12 +- 6 files changed, 208 insertions(+), 10 deletions(-) rename src/org/apache/fop/image/{GifJpegImage.java => GifImage.java} (94%) create mode 100644 src/org/apache/fop/image/JpegImage.java create mode 100644 src/org/apache/fop/pdf/DCTFilter.java diff --git a/src/org/apache/fop/image/AbstractFopImage.java b/src/org/apache/fop/image/AbstractFopImage.java index 9617a7ca6..4669758c7 100644 --- a/src/org/apache/fop/image/AbstractFopImage.java +++ b/src/org/apache/fop/image/AbstractFopImage.java @@ -21,6 +21,7 @@ import org.apache.fop.image.analyser.ImageReader; /** * Base class to implement the FopImage interface. * @author Eric SCHAEFFER + * @author Modified by Eric Dalquist - 9/14/2001 - ebdalqui@mtu.edu * @see FopImage */ public abstract class AbstractFopImage implements FopImage { @@ -75,6 +76,12 @@ public abstract class AbstractFopImage implements FopImage { */ protected PDFColor m_transparentColor = null; + /** + * Image compression type. + * Added by Eric Dalquist + */ + protected PDFFilter m_compressionType = null; + /** * Constructor. * Construct a new FopImage object and initialize its default properties: @@ -250,7 +257,16 @@ public abstract class AbstractFopImage implements FopImage { * @exception FopImageException an error occured during loading */ public PDFFilter getPDFFilter() throws FopImageException { - return null; + + /* + * Added by Eric Dalquist + * Using the bitsPerPixel var as our flag since many imges will + * have a null m_compressionType even after being loaded + */ + if (this.m_bitsPerPixel == 0) + this.loadImage(); + + return m_compressionType; } /** diff --git a/src/org/apache/fop/image/FopImageFactory.java b/src/org/apache/fop/image/FopImageFactory.java index 69d4a57e7..9a2650c07 100644 --- a/src/org/apache/fop/image/FopImageFactory.java +++ b/src/org/apache/fop/image/FopImageFactory.java @@ -118,10 +118,10 @@ public class FopImageFactory { String imgMimeType = imgReader.getMimeType(); String imgClassName = null; if ("image/gif".equals(imgMimeType)) { - imgClassName = "org.apache.fop.image.GifJpegImage"; + imgClassName = "org.apache.fop.image.GifImage"; // imgClassName = "org.apache.fop.image.JAIImage"; } else if ("image/jpeg".equals(imgMimeType)) { - imgClassName = "org.apache.fop.image.GifJpegImage"; + imgClassName = "org.apache.fop.image.JpegImage"; // imgClassName = "org.apache.fop.image.JAIImage"; } else if ("image/bmp".equals(imgMimeType)) { imgClassName = "org.apache.fop.image.BmpImage"; diff --git a/src/org/apache/fop/image/GifJpegImage.java b/src/org/apache/fop/image/GifImage.java similarity index 94% rename from src/org/apache/fop/image/GifJpegImage.java rename to src/org/apache/fop/image/GifImage.java index 77d591544..5c64b0bfb 100644 --- a/src/org/apache/fop/image/GifJpegImage.java +++ b/src/org/apache/fop/image/GifImage.java @@ -19,17 +19,18 @@ import org.apache.fop.pdf.PDFColor; import org.apache.fop.image.analyser.ImageReader; /** - * FopImage object for GIF or JPEG images, using Java native classes. + * FopImage object for GIF images, using Java native classes. * @author Eric SCHAEFFER + * @author Modified by Eric Dalquist - 9/14/2001 - ebdalqui@mtu.edu * @see AbstractFopImage * @see FopImage */ -public class GifJpegImage extends AbstractFopImage { - public GifJpegImage(URL href) throws FopImageException { +public class GifImage extends AbstractFopImage { + public GifImage(URL href) throws FopImageException { super(href); } - public GifJpegImage(URL href, + public GifImage(URL href, ImageReader imgReader) throws FopImageException { super(href, imgReader); } @@ -41,9 +42,12 @@ public class GifJpegImage extends AbstractFopImage { FopImageConsumer consumer = new FopImageConsumer(ip); ip.startProduction(consumer); + + //Load the image into memory while (!consumer.isImageReady()) { Thread.sleep(500); } + this.m_height = consumer.getHeight(); this.m_width = consumer.getWidth(); @@ -118,7 +122,6 @@ public class GifJpegImage extends AbstractFopImage { + ex.getMessage()); } - // Should take care of the ColorSpace and bitsPerPixel this.m_bitmapsSize = this.m_width * this.m_height * 3; this.m_bitmaps = new byte[this.m_bitmapsSize]; diff --git a/src/org/apache/fop/image/JpegImage.java b/src/org/apache/fop/image/JpegImage.java new file mode 100644 index 000000000..e725b79f5 --- /dev/null +++ b/src/org/apache/fop/image/JpegImage.java @@ -0,0 +1,136 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.image; + +// Java +import java.net.URL; +import java.awt.image.ImageProducer; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +// FOP +import org.apache.fop.datatypes.ColorSpace; +import org.apache.fop.pdf.PDFColor; +import org.apache.fop.pdf.DCTFilter; +import org.apache.fop.image.analyser.ImageReader; + +/** + * FopImage object for JPEG images, Using Java native classes. + * @author Eric Dalquist + * @see AbstractFopImage + * @see FopImage + */ +public class JpegImage extends AbstractFopImage { + public JpegImage(URL href) throws FopImageException { + super(href); + } + + public JpegImage(URL href, + ImageReader imgReader) throws FopImageException { + super(href, imgReader); + } + + protected void loadImage() throws FopImageException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream inStream; + + byte[] readBuf = new byte[4096]; + int bytes_read; + int index = 0; + boolean cont = true; + + this.m_compressionType = new DCTFilter(); + this.m_compressionType.setApplied(true); + + try { + inStream = this.m_href.openStream(); + + while ((bytes_read = inStream.read(readBuf)) != -1) { + baos.write(readBuf, 0, bytes_read); + } + } catch (java.io.IOException ex) { + throw new FopImageException("Error while loading image " + + this.m_href.toString() + " : " + ex.getClass() + + " - " + ex.getMessage()); + } + + this.m_bitmaps = baos.toByteArray(); + this.m_bitsPerPixel = 8; + this.m_isTransparent = false; + + if (this.m_bitmaps.length > (index + 2) && + uByte(this.m_bitmaps[index]) == 255 && + uByte(this.m_bitmaps[index + 1]) == 216) { + index += 2; + + while (index < this.m_bitmaps.length && cont) { + //check to be sure this is the begining of a header + if (this.m_bitmaps.length > (index + 2) && + uByte(this.m_bitmaps[index]) == 255) { + + //192 or 194 are the header bytes that contain the jpeg width height and color depth. + if (uByte(this.m_bitmaps[index + 1]) == 192 || + uByte(this.m_bitmaps[index + 1]) == 194) { + + this.m_height = calcBytes(this.m_bitmaps[index + 5], + this.m_bitmaps[index + 6]); + this.m_width = calcBytes(this.m_bitmaps[index + 7], + this.m_bitmaps[index + 8]); + + if (this.m_bitmaps[index + 9] == 1) { + this.m_colorSpace = new ColorSpace( + ColorSpace.DEVICE_GRAY); + } else if (this.m_bitmaps[index + 9] == 3) { + this.m_colorSpace = + new ColorSpace(ColorSpace.DEVICE_RGB); + } else { + cont = false; + throw new FopImageException( + "\n2 Error while loading image " + + this.m_href.toString() + + " : JpegImage - Invalid JPEG Header (bad color space " + + this.m_bitmaps[index + 9] + ")."); + } + + cont = false; + break; + + } else { // if (uByte(this.m_bitmaps[index + 1]) == headers[headerIndex]) { + index += calcBytes(this.m_bitmaps[index + 2], + this.m_bitmaps[index + 3]) + 2; + } + + } else { + cont = false; + throw new FopImageException( + "\n2 Error while loading image " + + this.m_href.toString() + " : JpegImage - Invalid JPEG Header (bad header byte)."); + } + } + } else { + throw new FopImageException( "\n1 Error while loading image " + + this.m_href.toString() + " : JpegImage - Invalid JPEG Header."); + } + } + + private int calcBytes(byte bOne, byte bTwo) { + return (uByte(bOne) * 256) + uByte(bTwo); + } + + private int uByte(byte bIn) { + if (bIn < 0) { + return 256 + bIn; + } else { + return bIn; + } + } +} + + diff --git a/src/org/apache/fop/pdf/DCTFilter.java b/src/org/apache/fop/pdf/DCTFilter.java new file mode 100644 index 000000000..9d59a676c --- /dev/null +++ b/src/org/apache/fop/pdf/DCTFilter.java @@ -0,0 +1,35 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.pdf; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + + +/** + * DCT Filter class. Right now it is just used as a dummy filter flag so + * we can write JPG images to the PDF. The encode method just returns the + * data passed to it. In the future an actual JPEG compression should be + * added to the encode method so other images can be compressed. + * + * @author Eric Dalquist + */ +public class DCTFilter extends PDFFilter { + public String getName() { + return "/DCTDecode"; + } + + public String getDecodeParms() { + return null; + } + + public byte[] encode(byte[] data) { + return data; + } +} + diff --git a/src/org/apache/fop/pdf/PDFXObject.java b/src/org/apache/fop/pdf/PDFXObject.java index 62e964afd..8d670a574 100644 --- a/src/org/apache/fop/pdf/PDFXObject.java +++ b/src/org/apache/fop/pdf/PDFXObject.java @@ -65,7 +65,15 @@ public class PDFXObject extends PDFObject { PDFStream imgStream = new PDFStream(0); imgStream.setData(fopimage.getBitmaps()); - // imgStream.addFilter(new FlateFilter()); + + /* + * Added by Eric Dalquist + * If the DCT filter hasn't been added to the object we add it here + */ + if (fopimage.getPDFFilter() != null) { + imgStream.addFilter(fopimage.getPDFFilter()); + } + imgStream.addDefaultFilters(); String dictEntries = imgStream.applyFilters(); @@ -74,7 +82,7 @@ public class PDFXObject extends PDFObject { p = p + "<