]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Patch to handle direct embedding of jpeg images into pdf
authorKeiron Liddle <keiron@apache.org>
Tue, 18 Sep 2001 08:17:08 +0000 (08:17 +0000)
committerKeiron Liddle <keiron@apache.org>
Tue, 18 Sep 2001 08:17:08 +0000 (08:17 +0000)
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

src/org/apache/fop/image/AbstractFopImage.java
src/org/apache/fop/image/FopImageFactory.java
src/org/apache/fop/image/GifImage.java [new file with mode: 0644]
src/org/apache/fop/image/GifJpegImage.java [deleted file]
src/org/apache/fop/image/JpegImage.java [new file with mode: 0644]
src/org/apache/fop/pdf/DCTFilter.java [new file with mode: 0644]
src/org/apache/fop/pdf/PDFXObject.java

index 9617a7ca6f9b2124df00180d007be8c615d2729a..4669758c7a0e72d3c470207cb640133bb3d7d011 100644 (file)
@@ -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;
     }
 
     /**
index 69d4a57e716fe3ee55550fd2f8889e058d2eccf5..9a2650c0711eb49079a9370f7d52168d72b44f84 100644 (file)
@@ -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/GifImage.java b/src/org/apache/fop/image/GifImage.java
new file mode 100644 (file)
index 0000000..5c64b0b
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * $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;
+
+// FOP
+import org.apache.fop.datatypes.ColorSpace;
+import org.apache.fop.pdf.PDFColor;
+import org.apache.fop.image.analyser.ImageReader;
+
+/**
+ * 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 GifImage extends AbstractFopImage {
+    public GifImage(URL href) throws FopImageException {
+        super(href);
+    }
+
+    public GifImage(URL href,
+                        ImageReader imgReader) throws FopImageException {
+        super(href, imgReader);
+    }
+
+    protected void loadImage() throws FopImageException {
+        int[] tmpMap = null;
+        try {
+            ImageProducer ip = (ImageProducer)this.m_href.getContent();
+            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();
+
+            try {
+                tmpMap = consumer.getImage();
+            } catch (Exception ex) {
+                throw new FopImageException("Image grabbing interrupted : "
+                                            + ex.getMessage());
+            }
+
+            ColorModel cm = consumer.getColorModel();
+            this.m_bitsPerPixel = 8;
+            // this.m_bitsPerPixel = cm.getPixelSize();
+            this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
+            if (cm.hasAlpha()) {
+                int transparencyType =
+                    cm.getTransparency();    // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT
+                if (transparencyType == java.awt.Transparency.OPAQUE) {
+                    this.m_isTransparent = false;
+                } else if (transparencyType
+                           == java.awt.Transparency.BITMASK) {
+                    if (cm instanceof IndexColorModel) {
+                        this.m_isTransparent = false;
+                        byte[] alphas =
+                            new byte[((IndexColorModel)cm).getMapSize()];
+                        byte[] reds =
+                            new byte[((IndexColorModel)cm).getMapSize()];
+                        byte[] greens =
+                            new byte[((IndexColorModel)cm).getMapSize()];
+                        byte[] blues =
+                            new byte[((IndexColorModel)cm).getMapSize()];
+                        ((IndexColorModel)cm).getAlphas(alphas);
+                        ((IndexColorModel)cm).getReds(reds);
+                        ((IndexColorModel)cm).getGreens(greens);
+                        ((IndexColorModel)cm).getBlues(blues);
+                        for (int i = 0;
+                                i < ((IndexColorModel)cm).getMapSize(); i++) {
+                            if ((alphas[i] & 0xFF) == 0) {
+                                this.m_isTransparent = true;
+                                this.m_transparentColor =
+                                    new PDFColor((int)(reds[i] & 0xFF),
+                                                 (int)(greens[i] & 0xFF),
+                                                 (int)(blues[i] & 0xFF));
+                                break;
+                            }
+                        }
+                    } else {
+                        // TRANSLUCENT
+                        /*
+                         * this.m_isTransparent = false;
+                         * for (int i = 0; i < this.m_width * this.m_height; i++) {
+                         * if (cm.getAlpha(tmpMap[i]) == 0) {
+                         * this.m_isTransparent = true;
+                         * this.m_transparentColor = new PDFColor(cm.getRed(tmpMap[i]), cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i]));
+                         * break;
+                         * }
+                         * }
+                         */
+                        // use special API...
+                        this.m_isTransparent = false;
+                    }
+                } else {
+                    this.m_isTransparent = false;
+                }
+            } else {
+                this.m_isTransparent = false;
+            }
+        } catch (Exception ex) {
+            throw new FopImageException("Error while loading image "
+                                        + this.m_href.toString() + " : "
+                                        + ex.getClass() + " - "
+                                        + 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];
+        for (int i = 0; i < this.m_height; i++) {
+            for (int j = 0; j < this.m_width; j++) {
+                int p = tmpMap[i * this.m_width + j];
+                int r = (p >> 16) & 0xFF;
+                int g = (p >> 8) & 0xFF;
+                int b = (p) & 0xFF;
+                this.m_bitmaps[3 * (i * this.m_width + j)] = (byte)(r & 0xFF);
+                this.m_bitmaps[3 * (i * this.m_width + j) + 1] = (byte)(g
+                        & 0xFF);
+                this.m_bitmaps[3 * (i * this.m_width + j) + 2] = (byte)(b
+                        & 0xFF);
+            }
+        }
+    }
+
+}
+
diff --git a/src/org/apache/fop/image/GifJpegImage.java b/src/org/apache/fop/image/GifJpegImage.java
deleted file mode 100644 (file)
index 77d5915..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * $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;
-
-// FOP
-import org.apache.fop.datatypes.ColorSpace;
-import org.apache.fop.pdf.PDFColor;
-import org.apache.fop.image.analyser.ImageReader;
-
-/**
- * FopImage object for GIF or JPEG images, using Java native classes.
- * @author Eric SCHAEFFER
- * @see AbstractFopImage
- * @see FopImage
- */
-public class GifJpegImage extends AbstractFopImage {
-    public GifJpegImage(URL href) throws FopImageException {
-        super(href);
-    }
-
-    public GifJpegImage(URL href,
-                        ImageReader imgReader) throws FopImageException {
-        super(href, imgReader);
-    }
-
-    protected void loadImage() throws FopImageException {
-        int[] tmpMap = null;
-        try {
-            ImageProducer ip = (ImageProducer)this.m_href.getContent();
-            FopImageConsumer consumer = new FopImageConsumer(ip);
-            ip.startProduction(consumer);
-
-            while (!consumer.isImageReady()) {
-                Thread.sleep(500);
-            }
-            this.m_height = consumer.getHeight();
-            this.m_width = consumer.getWidth();
-
-            try {
-                tmpMap = consumer.getImage();
-            } catch (Exception ex) {
-                throw new FopImageException("Image grabbing interrupted : "
-                                            + ex.getMessage());
-            }
-
-            ColorModel cm = consumer.getColorModel();
-            this.m_bitsPerPixel = 8;
-            // this.m_bitsPerPixel = cm.getPixelSize();
-            this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
-            if (cm.hasAlpha()) {
-                int transparencyType =
-                    cm.getTransparency();    // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT
-                if (transparencyType == java.awt.Transparency.OPAQUE) {
-                    this.m_isTransparent = false;
-                } else if (transparencyType
-                           == java.awt.Transparency.BITMASK) {
-                    if (cm instanceof IndexColorModel) {
-                        this.m_isTransparent = false;
-                        byte[] alphas =
-                            new byte[((IndexColorModel)cm).getMapSize()];
-                        byte[] reds =
-                            new byte[((IndexColorModel)cm).getMapSize()];
-                        byte[] greens =
-                            new byte[((IndexColorModel)cm).getMapSize()];
-                        byte[] blues =
-                            new byte[((IndexColorModel)cm).getMapSize()];
-                        ((IndexColorModel)cm).getAlphas(alphas);
-                        ((IndexColorModel)cm).getReds(reds);
-                        ((IndexColorModel)cm).getGreens(greens);
-                        ((IndexColorModel)cm).getBlues(blues);
-                        for (int i = 0;
-                                i < ((IndexColorModel)cm).getMapSize(); i++) {
-                            if ((alphas[i] & 0xFF) == 0) {
-                                this.m_isTransparent = true;
-                                this.m_transparentColor =
-                                    new PDFColor((int)(reds[i] & 0xFF),
-                                                 (int)(greens[i] & 0xFF),
-                                                 (int)(blues[i] & 0xFF));
-                                break;
-                            }
-                        }
-                    } else {
-                        // TRANSLUCENT
-                        /*
-                         * this.m_isTransparent = false;
-                         * for (int i = 0; i < this.m_width * this.m_height; i++) {
-                         * if (cm.getAlpha(tmpMap[i]) == 0) {
-                         * this.m_isTransparent = true;
-                         * this.m_transparentColor = new PDFColor(cm.getRed(tmpMap[i]), cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i]));
-                         * break;
-                         * }
-                         * }
-                         */
-                        // use special API...
-                        this.m_isTransparent = false;
-                    }
-                } else {
-                    this.m_isTransparent = false;
-                }
-            } else {
-                this.m_isTransparent = false;
-            }
-        } catch (Exception ex) {
-            throw new FopImageException("Error while loading image "
-                                        + this.m_href.toString() + " : "
-                                        + ex.getClass() + " - "
-                                        + 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];
-        for (int i = 0; i < this.m_height; i++) {
-            for (int j = 0; j < this.m_width; j++) {
-                int p = tmpMap[i * this.m_width + j];
-                int r = (p >> 16) & 0xFF;
-                int g = (p >> 8) & 0xFF;
-                int b = (p) & 0xFF;
-                this.m_bitmaps[3 * (i * this.m_width + j)] = (byte)(r & 0xFF);
-                this.m_bitmaps[3 * (i * this.m_width + j) + 1] = (byte)(g
-                        & 0xFF);
-                this.m_bitmaps[3 * (i * this.m_width + j) + 2] = (byte)(b
-                        & 0xFF);
-            }
-        }
-    }
-
-}
-
diff --git a/src/org/apache/fop/image/JpegImage.java b/src/org/apache/fop/image/JpegImage.java
new file mode 100644 (file)
index 0000000..e725b79
--- /dev/null
@@ -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 (file)
index 0000000..9d59a67
--- /dev/null
@@ -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;
+    }
+}
+
index 62e964afd031234abe5a58fca510bce5c4207859..8d670a574331e9dbe52ce79d940a204b04217904 100644 (file)
@@ -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 + "<</Type /XObject\n";
             p = p + "/Subtype /Image\n";
             p = p + "/Name /Im" + Xnum + "\n";
-            p = p + "/Length " + imgStream.getDataLength();
+            p = p + "/Length " + imgStream.getDataLength() + "\n";
             p = p + "/Width " + fopimage.getWidth() + "\n";
             p = p + "/Height " + fopimage.getHeight() + "\n";
             p = p + "/BitsPerComponent " + fopimage.getBitsPerPixel() + "\n";