You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by ma...@apache.org on 2009/07/24 14:19:49 UTC

svn commit: r797427 - in /xmlgraphics/commons/trunk: ./ src/java/org/apache/xmlgraphics/image/loader/impl/ src/java/org/apache/xmlgraphics/image/loader/impl/imageio/

Author: maxberger
Date: Fri Jul 24 12:19:49 2009
New Revision: 797427

URL: http://svn.apache.org/viewvc?rev=797427&view=rev
Log:
Support loading of ICC Profiles from PNG and JPEG when used through ImageIO

Modified:
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageBuffered.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterBuffered2Rendered.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterG2D2Bitmap.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageRendered.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java
    xmlgraphics/commons/trunk/status.xml

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageBuffered.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageBuffered.java?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageBuffered.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageBuffered.java Fri Jul 24 12:19:49 2009
@@ -20,6 +20,7 @@
 package org.apache.xmlgraphics.image.loader.impl;
 
 import java.awt.Color;
+import java.awt.color.ICC_Profile;
 import java.awt.image.BufferedImage;
 
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
@@ -35,9 +36,10 @@
      * @param info the image info object
      * @param buffered the BufferedImage instance
      * @param transparentColor the transparent color or null
+     * @param iccProfile an ICC color profile or null if no profile is associated
      */
-    public ImageBuffered(ImageInfo info, BufferedImage buffered, Color transparentColor) {
-        super(info, buffered, transparentColor);
+    public ImageBuffered(ImageInfo info, BufferedImage buffered, Color transparentColor, ICC_Profile iccProfile) {
+        super(info, buffered, transparentColor, iccProfile);
     }
 
     /** {@inheritDoc} */

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterBuffered2Rendered.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterBuffered2Rendered.java?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterBuffered2Rendered.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterBuffered2Rendered.java Fri Jul 24 12:19:49 2009
@@ -34,7 +34,9 @@
     public Image convert(Image src, Map hints) {
         checkSourceFlavor(src);
         ImageBuffered buffered = (ImageBuffered)src;
-        return new ImageRendered(buffered.getInfo(), buffered.getRenderedImage(), null);
+        return new ImageRendered(buffered.getInfo(), buffered
+                .getRenderedImage(), buffered.getTransparentColor(), buffered
+                .getICCProfile());
     }
 
     /** {@inheritDoc} */

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterG2D2Bitmap.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterG2D2Bitmap.java?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterG2D2Bitmap.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageConverterG2D2Bitmap.java Fri Jul 24 12:19:49 2009
@@ -73,7 +73,7 @@
 
         BufferedImage bi = paintToBufferedImage(g2dImage, bitsPerPixel, withAlpha, resolution);
 
-        ImageBuffered bufImage = new ImageBuffered(src.getInfo(), bi, null);
+        ImageBuffered bufImage = new ImageBuffered(src.getInfo(), bi, null, src.getICCProfile());
         return bufImage;
     }
 

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderInternalTIFF.java Fri Jul 24 12:19:49 2009
@@ -70,8 +70,8 @@
         org.apache.xmlgraphics.image.codec.tiff.TIFFImage img
             = new org.apache.xmlgraphics.image.codec.tiff.TIFFImage
                 (seekStream, null, 0);
-
-        return new ImageRendered(info, img, null);
+        // TODO: This may ignore ICC Profiles stored in TIFF images.
+        return new ImageRendered(info, img, null, null);
     }
 
 }

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageRendered.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageRendered.java?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageRendered.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/ImageRendered.java Fri Jul 24 12:19:49 2009
@@ -33,19 +33,33 @@
  */
 public class ImageRendered extends AbstractImage {
 
-    private RenderedImage red;
-    private Color transparentColor;
+    private final RenderedImage red;
+    private final Color transparentColor;
+    private final ColorSpace colorSpace;
+    private final ICC_Profile iccProfile;
 
     /**
      * Main constructor.
      * @param info the image info object
      * @param red the RenderedImage instance
      * @param transparentColor the transparent color or null
+     * @param iccProfile an ICC color profile or null if no profile is associated
      */
-    public ImageRendered(ImageInfo info, RenderedImage red, Color transparentColor) {
+    public ImageRendered(ImageInfo info, RenderedImage red, Color transparentColor, ICC_Profile iccProfile) {
         super(info);
         this.red = red;
         this.transparentColor = transparentColor;
+        this.colorSpace = red.getColorModel().getColorSpace();
+        if (iccProfile == null) {
+            if (this.colorSpace instanceof ICC_ColorSpace) {
+                ICC_ColorSpace icccs = (ICC_ColorSpace)this.colorSpace;
+                this.iccProfile = icccs.getProfile();
+            } else {
+                this.iccProfile = null;
+            }            
+        } else {
+            this.iccProfile = iccProfile;
+        }
     }
 
     /** {@inheritDoc} */
@@ -68,17 +82,12 @@
 
     /** {@inheritDoc} */
     public ColorSpace getColorSpace() {
-        return getRenderedImage().getColorModel().getColorSpace();
+        return this.colorSpace;
     }
 
     /** {@inheritDoc} */
     public ICC_Profile getICCProfile() {
-        ColorSpace cs = getColorSpace();
-        if (cs instanceof ICC_ColorSpace) {
-            ICC_ColorSpace icccs = (ICC_ColorSpace)cs;
-            return icccs.getProfile();
-        }
-        return null;
+        return this.iccProfile;
     }
 
     /**

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java Fri Jul 24 12:19:49 2009
@@ -20,30 +20,33 @@
 package org.apache.xmlgraphics.image.loader.impl.imageio;
 
 import java.awt.Color;
+import java.awt.color.ICC_Profile;
 import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.awt.image.IndexColorModel;
 import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.StringTokenizer;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
 
 import javax.imageio.IIOException;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageReadParam;
 import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
 import javax.imageio.metadata.IIOMetadata;
 import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.metadata.IIOMetadataNode;
 import javax.imageio.stream.ImageInputStream;
 import javax.xml.transform.Source;
 
-import org.w3c.dom.Element;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageException;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
@@ -53,6 +56,7 @@
 import org.apache.xmlgraphics.image.loader.impl.ImageBuffered;
 import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.w3c.dom.Element;
 
 /**
  * An ImageLoader implementation based on ImageIO for loading bitmap images.
@@ -63,6 +67,10 @@
     protected static Log log = LogFactory.getLog(ImageLoaderImageIO.class);
 
     private ImageFlavor targetFlavor;
+    
+    private static final String PNG_METADATA_NODE = "javax_imageio_png_1.0";
+    
+    private static final String JPEG_METADATA_NODE = "javax_imageio_jpeg_image_1.0";
 
     /**
      * Main constructor.
@@ -156,13 +164,15 @@
             throw new ImageException("No ImageIO ImageReader found .");
         }
 
+        ICC_Profile iccProf = null;
+        
         ColorModel cm = imageData.getColorModel();
 
         Color transparentColor = null;
         if (cm instanceof IndexColorModel) {
             //transparent color will be extracted later from the image
         } else {
-            //ImageIOUtil.dumpMetadataToSystemOut(iiometa);
+            ImageIOUtil.dumpMetadataToSystemOut(iiometa);
             //Retrieve the transparent color from the metadata
             if (iiometa != null && iiometa.isStandardMetadataFormatSupported()) {
                 Element metanode = (Element)iiometa.getAsTree(
@@ -187,16 +197,88 @@
                         }
                     }
                 }
+                iccProf = tryToExctractICCProfile(iiometa);
             }
         }
 
         if (ImageFlavor.BUFFERED_IMAGE.equals(this.targetFlavor)) {
-            return new ImageBuffered(info, (BufferedImage)imageData, transparentColor);
+            return new ImageBuffered(info, (BufferedImage)imageData, transparentColor, iccProf);
         } else {
-            return new ImageRendered(info, imageData, transparentColor);
+            return new ImageRendered(info, imageData, transparentColor, iccProf);
         }
     }
 
+    /**
+     * Extract ICC Profile from ImageIO Metadata. This method currently only
+     * supports PNG and JPEG metadata.
+     * 
+     * @param iiometa
+     *            The ImageIO Metadata
+     * @return an ICC Profile or null.
+     */
+    private ICC_Profile tryToExctractICCProfile(IIOMetadata iiometa) {
+        ICC_Profile iccProf = null;
+        String supportedFormats[] = iiometa.getMetadataFormatNames();
+        for (int i = 0; i < supportedFormats.length; i++) {
+            String format = supportedFormats[i];
+            Element root = (Element) iiometa.getAsTree(format);
+            if (PNG_METADATA_NODE.equals(format)) {
+                iccProf = this
+                        .tryToExctractICCProfileFromPNGMetadataNode(root);
+            } else if (JPEG_METADATA_NODE.equals(format)) {
+                iccProf = this.tryToExctractICCProfileFromJPEGMetadataNode(root);
+            }
+        }
+        return iccProf;
+    }
+    
+    private ICC_Profile tryToExctractICCProfileFromPNGMetadataNode(
+            Element pngNode) {
+        ICC_Profile iccProf = null;
+        Element iccpNode = ImageIOUtil.getChild(pngNode, "iCCP");
+        if (iccpNode instanceof IIOMetadataNode) {
+            IIOMetadataNode imn = (IIOMetadataNode) iccpNode;
+            byte[] prof = (byte[]) imn.getUserObject();
+            String comp = imn.getAttribute("compressionMethod");
+            if ("deflate".equalsIgnoreCase(comp)) {
+                Inflater decompresser = new Inflater();
+                decompresser.setInput(prof);
+                byte[] result = new byte[100];
+                ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                while (!decompresser.finished()) {
+                    try {
+                        int resultLength = decompresser.inflate(result);
+                        bos.write(result, 0, resultLength);
+                    } catch (DataFormatException e) {
+                        log.debug("Failed to deflate ICC Profile", e);
+                    }
+                }
+                decompresser.end();
+                try {
+                    iccProf = ICC_Profile.getInstance(bos.toByteArray());
+                } catch (IllegalArgumentException e) {
+                    log.debug("Failed to interpret embedded ICC Profile", e);
+                    iccProf = null;
+                }
+            }
+        }
+        return iccProf;
+    }
+
+    private ICC_Profile tryToExctractICCProfileFromJPEGMetadataNode(
+            Element jpgNode) {
+        ICC_Profile iccProf = null;
+        Element jfifNode = ImageIOUtil.getChild(jpgNode, "app0JFIF");
+        if (jfifNode != null) {
+            Element app2iccNode = ImageIOUtil.getChild(jfifNode, "app2ICC");
+            if (app2iccNode instanceof IIOMetadataNode) {
+                IIOMetadataNode imn = (IIOMetadataNode) app2iccNode;
+                iccProf = (ICC_Profile) imn.getUserObject();
+            }
+        }
+        return iccProf;
+    }
+    
     private BufferedImage getFallbackBufferedImage(ImageReader reader,
             int pageIndex, ImageReadParam param) throws IOException {
         //Work-around found at: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4799903

Modified: xmlgraphics/commons/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/status.xml?rev=797427&r1=797426&r2=797427&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/status.xml (original)
+++ xmlgraphics/commons/trunk/status.xml Fri Jul 24 12:19:49 2009
@@ -40,7 +40,10 @@
   </contexts>
   <changes>
     <release version="Trunk" date="n/a">
-      <action context="Code" dev="JM" type="fix">
+      <action context="Code" dev="MB" type="add">
+        Support loading of ICC Profiles from PNG and JPEG when used through ImageIO.
+      </action>
+       <action context="Code" dev="JM" type="fix">
         Switched from linear RGB to sRGB for the fallback color model, in order to avoid trouble 
         with some images (CMYK TIFF, for example).
       </action>



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