You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2008/03/27 15:29:47 UTC

svn commit: r641827 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java status.xml

Author: jeremias
Date: Thu Mar 27 07:29:44 2008
New Revision: 641827

URL: http://svn.apache.org/viewvc?rev=641827&view=rev
Log:
When a JPEG image is embedded, an optionally embedded color profile is filtered out as it's already embedded separately in the PDF file.
Worked around a problem (PDF renderer) with JPEG image containing RGB color profiles which are not sRGB. The images drifted into yellow. The color profile is simply disabled in this case. Please let us know if you know what the problem could be.

Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java
    xmlgraphics/fop/trunk/status.xml

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java?rev=641827&r1=641826&r2=641827&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java Thu Mar 27 07:29:44 2008
@@ -81,7 +81,7 @@
     /** {@inheritDoc} */
     public void setup(PDFDocument doc) {
 
-        ICC_Profile prof = image.getICCProfile();
+        ICC_Profile prof = getEffectiveICCProfile();
         PDFDeviceColorSpace pdfCS = toPDFColorSpace(getImageColorSpace());
         if (prof != null) {
             pdfICCStream = setupColorProfile(doc, prof, pdfCS);
@@ -100,6 +100,14 @@
         }
     }
 
+    /**
+     * Returns the effective ICC profile for the image.
+     * @return an ICC profile or null
+     */
+    protected ICC_Profile getEffectiveICCProfile() {
+        return image.getICCProfile();
+    }
+    
     private static PDFICCStream setupColorProfile(PDFDocument doc,
                 ICC_Profile prof, PDFDeviceColorSpace pdfCS) {
         boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof);

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java?rev=641827&r1=641826&r2=641827&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java Thu Mar 27 07:29:44 2008
@@ -18,19 +18,33 @@
 /* $Id$ */
 
 package org.apache.fop.render.pdf;
+import java.awt.color.ICC_Profile;
+import java.io.DataInput;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 
+import org.apache.commons.io.IOUtils;
+
 import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.JPEGConstants;
+import org.apache.xmlgraphics.image.loader.impl.JPEGFile;
+import org.apache.xmlgraphics.image.loader.util.ImageUtil;
 
 import org.apache.fop.pdf.DCTFilter;
 import org.apache.fop.pdf.PDFDeviceColorSpace;
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFFilter;
 import org.apache.fop.pdf.PDFFilterList;
+import org.apache.fop.util.ColorProfileUtil;
 
 /**
  * PDFImage implementation for the PDF renderer which handles raw JPEG images.
+ * <p>
+ * The JPEG is copied to the XObject's stream as-is but some elements (marker segments) are
+ * filtered. For example, an embedded color profile is filtered since it is already added as
+ * a PDF object and associated with the XObject. This way, the PDF file size is kept as small
+ * as possible.
  */
 public class ImageRawJPEGAdapter extends AbstractImageAdapter {
 
@@ -68,6 +82,21 @@
     }
 
     /** {@inheritDoc} */
+    protected ICC_Profile getEffectiveICCProfile() {
+        ICC_Profile profile = super.getEffectiveICCProfile();
+        if (profile != null 
+                && profile.getNumComponents() == 3
+                && !ColorProfileUtil.isDefaultsRGB(profile)) {
+            //RGB profiles which are not sRGB don't seem to work.
+            //Without this override, the image drifts into yellow for an unknown reason.
+            //TODO Find out why this happens.
+            //Test using a JPEG images with, for example, "Adobe RGB 1998" color profile.
+            profile = null;
+        }
+        return profile;
+    }
+    
+    /** {@inheritDoc} */
     public int getBitsPerComponent() {
         return 8;
     }
@@ -84,7 +113,77 @@
     
     /** {@inheritDoc} */
     public void outputContents(OutputStream out) throws IOException {
-        getImage().writeTo(out);
+        InputStream in = getImage().createInputStream();
+        in = ImageUtil.decorateMarkSupported(in);
+        try {
+            JPEGFile jpeg = new JPEGFile(in);
+            DataInput din = jpeg.getDataInput();
+            
+            //Copy the whole JPEG file except:
+            // - the ICC profile
+            //TODO Thumbnails could safely be skipped, too.
+            //TODO Metadata (XMP, IPTC, EXIF) could safely be skipped, too.
+            while (true) {
+                int reclen;
+                int segID = jpeg.readMarkerSegment();
+                switch (segID) {
+                case JPEGConstants.SOI:
+                    out.write(0xFF);
+                    out.write(segID);
+                    break;
+                case JPEGConstants.EOI:
+                case JPEGConstants.SOS:
+                    out.write(0xFF);
+                    out.write(segID);
+                    IOUtils.copy(in, out); //Just copy the rest!
+                    return;
+                /*
+                case JPEGConstants.APP1: //Metadata
+                case JPEGConstants.APPD:
+                    jpeg.skipCurrentMarkerSegment();
+                    break;*/
+                case JPEGConstants.APP2: //ICC (see ICC1V42.pdf)
+                    boolean skipICCProfile = false;
+                    in.mark(16);
+                    try {
+                        reclen = jpeg.readSegmentLength();
+                        // Check for ICC profile
+                        byte[] iccString = new byte[11];
+                        din.readFully(iccString);
+                        din.skipBytes(1); //string terminator (null byte)
+
+                        if ("ICC_PROFILE".equals(new String(iccString, "US-ASCII"))) {
+                            skipICCProfile = (this.image.getICCProfile() != null);
+                        }
+                    } finally {
+                        in.reset();
+                    }
+                    if (skipICCProfile) {
+                        //ICC profile is skipped as it is already embedded as a PDF object
+                        jpeg.skipCurrentMarkerSegment();
+                        break;
+                    }
+                default:
+                    out.write(0xFF);
+                    out.write(segID);
+                    
+                    reclen = jpeg.readSegmentLength();
+                    //write short
+                    out.write((reclen >>> 8) & 0xFF);
+                    out.write((reclen >>> 0) & 0xFF);
+                    int left = reclen - 2;
+                    byte[] buf = new byte[2048];
+                    while (left > 0) {
+                        int part = Math.min(buf.length, left);
+                        din.readFully(buf, 0, part);
+                        out.write(buf, 0, part);
+                        left -= part;
+                    }
+                }
+            }
+        } finally {
+            IOUtils.closeQuietly(in);
+        }
     }
 
     /** {@inheritDoc} */

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=641827&r1=641826&r2=641827&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Thu Mar 27 07:29:44 2008
@@ -58,6 +58,15 @@
         Added SVG support for AFP (GOCA).
         </action>
       -->
+      <action context="Renderers" dev="JM" type="update">
+        When a JPEG image is embedded, an optionally embedded color profile is filtered out
+        as it's already embedded separately in the PDF file.
+      </action>
+      <action context="Renderers" dev="JM" type="fix">
+        Worked around a problem (PDF renderer) with JPEG image containing RGB color profiles which
+        are not sRGB. The images drifted into yellow. The color profile is simply disabled in this
+        case. Please let us know if you know what the problem could be.
+      </action>
       <action context="Fonts" dev="JM" type="add">
         Added support for addressing all glyphs available in a Type 1 font, not just the ones
         in the font's primary encoding.



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org