pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From til...@apache.org
Subject svn commit: r1584105 - in /pdfbox/branches/1.8/pdfbox: ./ src/main/java/org/apache/pdfbox/util/ src/test/java/org/apache/pdfbox/util/ src/test/resources/input/rendering/
Date Wed, 02 Apr 2014 17:47:01 GMT
Author: tilman
Date: Wed Apr  2 17:47:00 2014
New Revision: 1584105

URL: http://svn.apache.org/r1584105
Log:
PDFBOX-1975: Transferred the improved ImageIOUtils and its tests from the trunk, modified for the pre-refactoring API; modified the POM to get the two "wrong license" ImageWriter plugins (levigo and jai_imageio) for test only

Added:
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/JPEGUtil.java
      - copied unchanged from r1582205, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/JPEGUtil.java
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/MetaUtil.java
      - copied unchanged from r1582205, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/MetaUtil.java
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/NullOutputStream.java   (with props)
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java
      - copied unchanged from r1582205, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JBIG2Image.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestCMYK.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestGrey.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestRGB.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/ccitt4-cib-test.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/jpeg_demo.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/png_demo.pdf   (with props)
    pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/raw_image_demo.pdf   (with props)
Modified:
    pdfbox/branches/1.8/pdfbox/pom.xml
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java
    pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java

Modified: pdfbox/branches/1.8/pdfbox/pom.xml
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/pom.xml?rev=1584105&r1=1584104&r2=1584105&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/pom.xml (original)
+++ pdfbox/branches/1.8/pdfbox/pom.xml Wed Apr  2 17:47:00 2014
@@ -1,158 +1,187 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
- ! 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.
- !-->
+! 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.
+!-->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
+    <modelVersion>4.0.0</modelVersion>
 
-  <parent>
-    <groupId>org.apache.pdfbox</groupId>
-    <artifactId>pdfbox-parent</artifactId>
-    <version>1.8.5-SNAPSHOT</version>
-    <relativePath>../parent/pom.xml</relativePath>
-  </parent>
-
-  <artifactId>pdfbox</artifactId>
-  <packaging>bundle</packaging>
-
-  <name>Apache PDFBox</name>
-  <description>
-    The Apache PDFBox library is an open source Java tool for working with PDF documents.
-  </description>
-  <inceptionYear>2002</inceptionYear>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.pdfbox</groupId>
-      <artifactId>fontbox</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.pdfbox</groupId>
-      <artifactId>jempbox</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>commons-logging</groupId>
-      <artifactId>commons-logging</artifactId>
-      <version>1.1.1</version>
-    </dependency>
-    <dependency>
-      <groupId>org.bouncycastle</groupId>
-      <artifactId>bcmail-jdk15</artifactId>
-      <version>1.44</version>
-      <optional>true</optional>
-    </dependency>
-    <dependency>
-      <groupId>org.bouncycastle</groupId>
-      <artifactId>bcprov-jdk15</artifactId>
-      <version>1.44</version>
-      <optional>true</optional>
-    </dependency>
-    <dependency>
-      <groupId>com.ibm.icu</groupId>
-      <artifactId>icu4j</artifactId>
-      <version>3.8</version>
-      <optional>true</optional>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.8.1</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <resources>
-      <resource>
-        <directory>src/main/resources</directory>
-        <filtering>true</filtering>
-      </resource>
-    </resources>
-    <plugins>
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>generate-resources</phase>
-            <configuration>
-              <target>
-                <ant antfile="build.xml" target="get.adobefiles" />
-              </target>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-        </executions>
-        <dependencies>
-          <dependency>
-            <groupId>org.apache.ant</groupId>
-            <artifactId>ant-nodeps</artifactId>
-            <version>1.8.1</version>
-          </dependency>
-        </dependencies>
-      </plugin>
-      <plugin>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <argLine>-Xmx64m</argLine>
-          <includes>
-            <include>org/apache/pdfbox/TestAll.java</include>
-            <include>org/apache/pdfbox/util/TestTextStripper.java</include>
-            <!--
-            <include>org/apache/pdfbox/util/TestPDFToImage.java</include>
-            -->
-          </includes>
-          <systemPropertyVariables>
-            <java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
-          </systemPropertyVariables>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-          <configuration>
-          <instructions>
-            <Include-Resource>
-              {maven-resources},
-              META-INF=target/maven-shared-archive-resources/META-INF,
-              org/apache/pdfbox/resources=target/classes/org/apache/pdfbox/resources
-            </Include-Resource>
-          </instructions>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.rat</groupId>
-        <artifactId>apache-rat-plugin</artifactId>
-        <configuration>
-          <excludes>
-            <exclude>src/main/resources/org/apache/pdfbox/resources/cmap/*</exclude>
-            <exclude>src/test/resources/input/rendering/*.ai</exclude>
-            <exclude>download/glyphlist.txt</exclude>
-            <exclude>release.properties</exclude>
-          </excludes>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+    <parent>
+        <groupId>org.apache.pdfbox</groupId>
+        <artifactId>pdfbox-parent</artifactId>
+        <version>1.8.5-SNAPSHOT</version>
+        <relativePath>../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>pdfbox</artifactId>
+    <packaging>bundle</packaging>
+
+    <name>Apache PDFBox</name>
+    <description>
+        The Apache PDFBox library is an open source Java tool for working with PDF documents.
+    </description>
+    <inceptionYear>2002</inceptionYear>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>fontbox</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>jempbox</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcmail-jdk15</artifactId>
+            <version>1.44</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15</artifactId>
+            <version>1.44</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.ibm.icu</groupId>
+            <artifactId>icu4j</artifactId>
+            <version>3.8</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.1</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- For legal reasons (incompatible license), these two dependencies
+        are to be used only in the tests and may not be distributed.
+        See also LEGAL-195 -->
+        <dependency>
+            <groupId>com.levigo.jbig2</groupId>
+            <artifactId>levigo-jbig2-imageio</artifactId>
+            <version>1.6.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.java.dev.jai-imageio</groupId>
+            <artifactId>jai-imageio-core-standalone</artifactId>
+            <version>1.2-pre-dr-b04-2011-07-04</version>
+            <scope>test</scope>
+        </dependency>    
+    </dependencies>
+  
+    <repositories>
+        <repository>
+            <id>jbig2.googlecode</id>
+            <name>JBIG2 ImageIO-Plugin repository at googlecode.com</name>
+            <url>http://jbig2-imageio.googlecode.com/svn/maven-repository/</url>
+        </repository>
+        <repository>
+            <id>mygrid-repository</id>
+            <name>myGrid Repository</name>
+            <url>http://www.mygrid.org.uk/maven/repository</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>generate-resources</phase>
+                        <configuration>
+                            <target>
+                                <ant antfile="build.xml" target="get.adobefiles" />
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.ant</groupId>
+                        <artifactId>ant-nodeps</artifactId>
+                        <version>1.8.1</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <argLine>-Xmx64m</argLine>
+                    <includes>
+                        <include>org/apache/pdfbox/TestAll.java</include>
+                        <include>org/apache/pdfbox/util/TestTextStripper.java</include>
+                        <!--
+                        <include>org/apache/pdfbox/util/TestPDFToImage.java</include>
+                        -->
+                    </includes>
+                    <systemPropertyVariables>
+                        <java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Include-Resource>
+                            {maven-resources},
+                            META-INF=target/maven-shared-archive-resources/META-INF,
+                            org/apache/pdfbox/resources=target/classes/org/apache/pdfbox/resources
+                        </Include-Resource>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>src/main/resources/org/apache/pdfbox/resources/cmap/*</exclude>
+                        <exclude>src/test/resources/input/rendering/*.ai</exclude>
+                        <exclude>download/glyphlist.txt</exclude>
+                        <exclude>release.properties</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
 

Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java?rev=1584105&r1=1584104&r2=1584105&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java Wed Apr  2 17:47:00 2014
@@ -21,10 +21,8 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.StringWriter;
 import java.util.Iterator;
 
-import javax.imageio.IIOException;
 import javax.imageio.IIOImage;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageTypeSpecifier;
@@ -34,33 +32,21 @@ import javax.imageio.metadata.IIOInvalid
 import javax.imageio.metadata.IIOMetadata;
 import javax.imageio.metadata.IIOMetadataNode;
 import javax.imageio.stream.ImageOutputStream;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.Node;
+import static org.apache.pdfbox.util.MetaUtil.STANDARD_METADATA_FORMAT;
 import org.w3c.dom.NodeList;
 
 /**
- * This class handles some ImageIO operations.
- *
- * @version $Revision$
- * 
+ * Handles some ImageIO operations.
  */
 public class ImageIOUtil
-{   
+{
     /**
-     * Log instance.
+     * Log instance
      */
     private static final Log LOG = LogFactory.getLog(ImageIOUtil.class);
-
+    
     /**
      * Default screen resolution: 72dpi.
      */
@@ -72,57 +58,61 @@ public class ImageIOUtil
     
     private ImageIOUtil()
     {
-        // Default constructor
     }
 
     /**
-     * Writes a buffered image to a file using the given image format.
-     * 
+     * Writes a buffered image to a file using the given image format. See     
+     * {@link #writeImage(BufferedImage image, String formatName, 
+     * OutputStream output, int dpi, float quality)} for more details.
+     *
      * @param image the image to be written
-     * @param formatName the target format (ex. "png")
      * @param filename used to construct the filename for the individual image.
-     * The formatName parameter will be used as the suffix.
-     * @param imageType the image type (see {@link BufferedImage}.TYPE_*)
-     * @param resolution the resolution in dpi (dots per inch)
-     * 
-     * @return true if the images were produced, false if there was an error
-     * 
+     * Its suffix will be used as the image format.
+     * @param dpi the resolution in dpi (dots per inch)
+     * @return true if the image file was produced, false if there was an error.
      * @throws IOException if an I/O error occurs
-     * 
-     * @deprecated use
-     * {@link #writeImage(BufferedImage image, String filename, int dpi)}, which
-     * uses the full filename instead of just the prefix.
      */
-    @Deprecated
-    public static boolean writeImage(BufferedImage image, String formatName, String filename, 
-            int imageType, int resolution)
-    throws IOException
+    public static boolean writeImage(BufferedImage image, String filename,
+            int dpi) throws IOException
     {
-        String fileName = filename + "." + formatName;
-        File file = new File(fileName);
-        return writeImage(image, formatName, file, resolution);
+        File file = new File(filename);
+        FileOutputStream output = new FileOutputStream(file);
+        try
+        {
+            String formatName = filename.substring(filename.lastIndexOf('.') + 1);
+            return writeImage(image, formatName, output, dpi);
+        }
+        finally
+        {
+            output.close();
+        }
     }
-    
+
     /**
-     * Writes a buffered image to a file using the given image format. See     
+     * Writes a buffered image to a file using the given image format. See      
      * {@link #writeImage(BufferedImage image, String formatName, 
      * OutputStream output, int dpi, float quality)} for more details.
      *
      * @param image the image to be written
+     * @param formatName the target format (ex. "png") which is also the suffix
+     * for the filename
      * @param filename used to construct the filename for the individual image.
-     * Its suffix will be used as the image format.
+     * The formatName parameter will be used as the suffix.
      * @param dpi the resolution in dpi (dots per inch)
      * @return true if the image file was produced, false if there was an error.
      * @throws IOException if an I/O error occurs
+     * @deprecated use
+     * {@link #writeImage(BufferedImage image, String filename, int dpi)}, which
+     * uses the full filename instead of just the prefix.
      */
-    public static boolean writeImage(BufferedImage image, String filename,
+    @Deprecated
+    public static boolean writeImage(BufferedImage image, String formatName, String filename,
             int dpi) throws IOException
     {
-        File file = new File(filename);
+        File file = new File(filename + "." + formatName);
         FileOutputStream output = new FileOutputStream(file);
         try
         {
-            String formatName = filename.substring(filename.lastIndexOf('.') + 1);
             return writeImage(image, formatName, output, dpi);
         }
         finally
@@ -132,376 +122,211 @@ public class ImageIOUtil
     }
 
     /**
-     * Writes a buffered image to a file using the given image format.
-     * 
+     * Writes a buffered image to a file using the given image format. See      
+     * {@link #writeImage(BufferedImage image, String formatName, 
+     * OutputStream output, int dpi, float quality)} for more details.
+     *
      * @param image the image to be written
      * @param formatName the target format (ex. "png")
-     * @param outputStream the output stream to be used for writing
-     * 
-     * @return true if the images were produced, false if there was an error
+     * @param output the output stream to be used for writing
+     * @return true if the image file was produced, false if there was an error.
      * @throws IOException if an I/O error occurs
      */
-    public static boolean writeImage(BufferedImage image, String formatName, OutputStream outputStream) 
-    throws IOException
+    public static boolean writeImage(BufferedImage image, String formatName, OutputStream output)
+            throws IOException
     {
-        return writeImage(image, formatName, outputStream, DEFAULT_SCREEN_RESOLUTION);
+        return writeImage(image, formatName, output, DEFAULT_SCREEN_RESOLUTION);
     }
 
     /**
-     * Writes a buffered image to a file using the given image format.
-     * 
+     * Writes a buffered image to a file using the given image format. See      
+     * {@link #writeImage(BufferedImage image, String formatName, 
+     * OutputStream output, int dpi, float quality)} for more details.
+     *
      * @param image the image to be written
      * @param formatName the target format (ex. "png")
-     * @param outputStream the output stream to be used for writing
+     * @param output the output stream to be used for writing
      * @param dpi resolution to be used when writing the image
-     * 
-     * @return true if the images were produced, false if there was an error
+     * @return true if the image file was produced, false if there was an error.
      * @throws IOException if an I/O error occurs
      */
-    public static boolean writeImage(BufferedImage image, String formatName, Object outputStream, int dpi)
-    throws IOException
+    public static boolean writeImage(BufferedImage image, String formatName, OutputStream output,
+            int dpi) throws IOException
     {
-        return writeImage(image, formatName, outputStream, dpi, DEFAULT_COMPRESSION_QUALITY);
+        return writeImage(image, formatName, output, dpi, DEFAULT_COMPRESSION_QUALITY);
     }
-    
+
     /**
      * Writes a buffered image to a file using the given image format.
-     * 
+     * Compression is fixed for PNG, GIF, BMP and WBMP, dependent of the quality
+     * parameter for JPG, and dependent of bit count for TIFF (a bitonal image
+     * will be compressed with CCITT G4, a color image with LZW). Creating a
+     * TIFF image is only supported if the jai_imageio library is in the class
+     * path.
+     *
      * @param image the image to be written
      * @param formatName the target format (ex. "png")
-     * @param outputStream the output stream to be used for writing
+     * @param output the output stream to be used for writing
      * @param dpi resolution to be used when writing the image
      * @param quality quality to be used when compressing the image (0 &lt;
      * quality &lt; 1.0f)
-     * 
-     * @return true if the images were produced, false if there was an error
+     * @return true if the image file was produced, false if there was an error.
      * @throws IOException if an I/O error occurs
      */
-    public static boolean writeImage(BufferedImage image, String formatName, Object outputStream, int dpi, 
-            float quality)
-    throws IOException
+    public static boolean writeImage(BufferedImage image, String formatName, OutputStream output,
+            int dpi, float quality) throws IOException
     {
-        boolean bSuccess = true;
-        ImageOutputStream output = null;
-        ImageWriter imageWriter = null;
+        ImageOutputStream imageOutput = null;
+        ImageWriter writer = null;
         try
         {
-            output = ImageIO.createImageOutputStream(outputStream);
-    
-            boolean foundWriter = false;
-            Iterator<ImageWriter> writerIter = ImageIO.getImageWritersByFormatName(formatName);
-            while (writerIter.hasNext() && !foundWriter)
+            // find suitable image writer
+            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+            ImageWriteParam param = null;
+            IIOMetadata metadata = null;
+            // Loop until we get the best driver, i.e. one that supports
+            // setting dpi in the standard metadata format; however we'd also 
+            // accept a driver that can't, if a better one can't be found
+            while (writers.hasNext())
             {
-                try
+                if (writer != null)
                 {
-                    imageWriter = (ImageWriter) writerIter.next();
-                    ImageWriteParam writerParams = imageWriter.getDefaultWriteParam();
-                    if (writerParams.canWriteCompressed())
-                    {
-                        writerParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
-                        // reset the compression type if overwritten by setCompressionMode
-
-                        if (writerParams.getCompressionType() == null)
-                        {
-                            if (formatName.toLowerCase().startsWith("tif"))
-                            {
-                                // avoid error: first compression type is RLE, not optimal and incorrect for color images
-                                //TODO? another writeImage() call with extra compression param so user can decide
-                                if (image.getType() == BufferedImage.TYPE_BYTE_BINARY && image.getColorModel().getPixelSize() == 1)
-                                {
-                                    writerParams.setCompressionType("CCITT T.6");
-                                }
-                                else
-                                {
-                                    writerParams.setCompressionType("LZW");
-                                }
-                            }
-                            else
-                            {
-                                writerParams.setCompressionType(writerParams.getCompressionTypes()[0]);
-                            }
-                        }
-                        writerParams.setCompressionQuality(quality);
-                    }
-                    IIOMetadata meta = createMetadata(image, imageWriter, writerParams, dpi);
-                    if (meta != null)
-                    {
-                        imageWriter.setOutput(output);
-                        imageWriter.write(null, new IIOImage(image, null, meta), writerParams);
-                    	foundWriter = true;
-                    }
+                    writer.dispose();
                 }
-                catch (IIOException io)
+                writer = writers.next();
+                param = writer.getDefaultWriteParam();
+                metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), param);
+                if (metadata != null
+                        && !metadata.isReadOnly()
+                        && metadata.isStandardMetadataFormatSupported())
                 {
-                    LOG.error("IIOException in writeImage()", io);
-                    throw new IOException(io.getMessage());
+                    break;
                 }
-                finally
+            }
+            if (writer == null)
+            {
+                LOG.error("No ImageWriter found for '" + formatName + "' format");
+                StringBuilder sb = new StringBuilder();
+                String[] writerFormatNames = ImageIO.getWriterFormatNames();
+                for (String fmt : writerFormatNames)
                 {
-                    if (imageWriter != null)
-                    {
-                        imageWriter.dispose();
-                    }
+                    sb.append(fmt);
+                    sb.append(' ');
                 }
+                LOG.error("Supported formats: " + sb);
+                return false;
             }
-            if (!foundWriter)
+
+            // compression
+            if (param != null && param.canWriteCompressed())
             {
-                LOG.error("No writer found for format '" + formatName + "'");
-                bSuccess = false;
+                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+                if (formatName.toLowerCase().startsWith("tif"))
+                {
+                    // TIFF compression
+                    TIFFUtil.setCompressionType(param, image);
+                }
+                else
+                {
+                    param.setCompressionType(param.getCompressionTypes()[0]);
+                    param.setCompressionQuality(quality);
+                }
             }
-        }
-        finally
-        {
-            if (output != null)
+
+            if (formatName.toLowerCase().startsWith("tif"))
             {
-                output.flush();
-                output.close();
+                // TIFF metadata
+                TIFFUtil.updateMetadata(metadata, image, dpi);
             }
-        }
-        return bSuccess;
-    }
-
-    private static IIOMetadata createMetadata(BufferedImage image, ImageWriter imageWriter,
-            ImageWriteParam writerParams, int dpi)
-    {
-        ImageTypeSpecifier type;
-        if (writerParams.getDestinationType() != null)
-        {
-            type = writerParams.getDestinationType();
-        }
-        else
-        {
-            type = ImageTypeSpecifier.createFromRenderedImage( image );
-        }
-        IIOMetadata meta = imageWriter.getDefaultImageMetadata(type, writerParams);
-        logMeta(meta, STANDARD_METADATA_FORMAT);
-        if (imageWriter.getClass().getName().toUpperCase().contains("TIFF"))
-        {
-            updateMetadata(image, meta, dpi);
-        }
-        else
-        {
-            if (!addResolution(meta, dpi))
+            else if ("jpeg".equals(formatName.toLowerCase())
+                    || "jpg".equals(formatName.toLowerCase()))
             {
-                meta = null;
+                // This segment must be run before other meta operations,
+                // or else "IIOInvalidTreeException: Invalid node: app0JFIF"
+                // The other (general) "meta" methods may not be used, because
+                // this will break the reading of the meta data in tests
+                JPEGUtil.updateMetadata(metadata, dpi);
+            }
+            else
+            {
+                // write metadata is possible
+                if (metadata != null
+                        && !metadata.isReadOnly()
+                        && metadata.isStandardMetadataFormatSupported())
+                {
+                    setDPI(metadata, dpi, formatName);
+                }
             }
-        }
-        logMeta(meta, STANDARD_METADATA_FORMAT);
-        return meta;
-    }
-
-    /**
-     * log the meta data as an XML tree if debug is enabled.
-     * 
-     * @param meta meta data.
-     * @param format the XML format to be used.
-     */
-    private static void logMeta(IIOMetadata meta, String format)
-    {
-        if (!LOG.isDebugEnabled())
-        {
-            return;
-        }
-        if (meta == null)
-        {
-            LOG.debug("meta is null");
-            return;
-        }
-        IIOMetadataNode root = (IIOMetadataNode) meta.getAsTree(format);
-        // http://download.java.net/jdk8/docs/api/javax/imageio/metadata/doc-files/standard_metadata.html
-        // http://www.java-forum.org/java-basics-anfaenger-themen/96982-aufloesung-dpi-tiff-png-bildern-auslesen.html#post617178
 
-        try
-        {
-            StringWriter xmlStringWriter = new StringWriter();
-            StreamResult streamResult = new StreamResult(xmlStringWriter);
-            Transformer transformer = TransformerFactory.newInstance().newTransformer();
-            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // http://stackoverflow.com/a/1264872/535646
-            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-            DOMSource domSource = new DOMSource(root);
-            transformer.transform(domSource, streamResult);
-            LOG.debug("\n" + xmlStringWriter);
-        }
-        catch (TransformerFactoryConfigurationError ex)
-        {
-            LOG.error(ex, ex);
-        }
-        catch (IllegalArgumentException ex)
-        {
-            LOG.error(ex, ex);
-        }
-        catch (TransformerException ex)
-        {
-            LOG.error(ex, ex);
+            // write
+            imageOutput = ImageIO.createImageOutputStream(output);
+            writer.setOutput(imageOutput);
+            writer.write(null, new IIOImage(image, null, metadata), param);
         }
-    }
-
-    private static final String STANDARD_METADATA_FORMAT = "javax_imageio_1.0";
-    private static final String SUN_TIFF_NATIVE_FORMAT
-            = "com_sun_media_imageio_plugins_tiff_image_1.0";
-
-    private static boolean addResolution(IIOMetadata meta, int resolution)
-    {
-        if (meta != null && !meta.isReadOnly() && meta.isStandardMetadataFormatSupported())
+        finally
         {
-            IIOMetadataNode root = (IIOMetadataNode)meta.getAsTree(STANDARD_METADATA_FORMAT);
-            IIOMetadataNode dim = getChildNode(root, "Dimension");
-            if (dim == null)
-            {
-                dim = new IIOMetadataNode("Dimension");
-                root.appendChild(dim);
-            }
-            IIOMetadataNode child;
-            child = getChildNode(dim, "HorizontalPixelSize");
-            if (child == null)
-            {
-                child = new IIOMetadataNode("HorizontalPixelSize");
-                dim.appendChild(child);
-            }
-            child.setAttribute("value",
-                    Double.toString(resolution / 25.4));
-            child = getChildNode(dim, "VerticalPixelSize");
-            if (child == null)
-            {
-                child = new IIOMetadataNode("VerticalPixelSize");
-                dim.appendChild(child);
-            }
-            child.setAttribute("value",
-                    Double.toString(resolution / 25.4));
-            try
-            {
-                meta.mergeTree(STANDARD_METADATA_FORMAT, root);
-            }
-            catch (IIOInvalidTreeException e)
+            if (writer != null)
             {
-                throw new RuntimeException("Cannot update image metadata: "
-                        + e.getMessage());
+                writer.dispose();
             }
-            return true;
-        }
-        return false;
-    }
-
-    private static IIOMetadataNode getChildNode(Node n, String name)
-    {
-        NodeList nodes = n.getChildNodes();
-        for (int i = 0; i < nodes.getLength(); i++)
-        {
-            Node child = nodes.item(i);
-            if (name.equals(child.getNodeName()))
+            if (imageOutput != null)
             {
-                return (IIOMetadataNode)child;
+                imageOutput.close();
             }
         }
-        return null;
+        return true;
     }
     
     /**
-     * Sets the resolution in a TIFF image, the resolution unit (Inches), rows
-     * per strip to the height to get smaller files, and the name of the
-     * software to "PDFBOX".
+     * Gets the named child node, or creates and attaches it.
+     *
+     * @param parentNode the parent node
+     * @param name name of the child node
      *
-     * @param tiffImage the TIFF Image
-     * @param meta the meta data that is to be set
-     * @param resolution in dots per inch
+     * @return the existing or just created child node
      */
-    protected static void updateMetadata(BufferedImage tiffImage, IIOMetadata meta, int resolution)
+    private static IIOMetadataNode getOrCreateChildNode(IIOMetadataNode parentNode, String name)
     {
-        // Code inspired by Apache XML graphics
-        // https://svn.apache.org/repos/asf/xmlgraphics/commons/tags/commons-1_3_1/src/java/org/apache/xmlgraphics/image/writer/imageio/ImageIOTIFFImageWriter.java
-        // DTD:
-        // http://download.java.net/media/jai-imageio/javadoc/1.0_01/com/sun/media/imageio/plugins/tiff/package-summary.html
-        // TIFF6 Spec:
-        // http://partners.adobe.com/public/developer/tiff/index.html
-        // We set the resolution manually using the native format since it appears that
-        // it doesn't work properly through the standard metadata. Haven't figured out why
-        // that happens.
-        if (SUN_TIFF_NATIVE_FORMAT.equals(meta.getNativeMetadataFormatName()))
+        NodeList nodeList = parentNode.getElementsByTagName(name);
+        if (nodeList != null && nodeList.getLength() > 0)
         {
-            IIOMetadataNode root = new IIOMetadataNode(SUN_TIFF_NATIVE_FORMAT);
-            IIOMetadataNode ifd = getChildNode(root, "TIFFIFD");
-            if (ifd == null)
-            {
-                ifd = new IIOMetadataNode("TIFFIFD");
-                ifd.setAttribute("tagSets",
-                        "com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet");
-                root.appendChild(ifd);
-            }
-
-            ifd.appendChild(createRationalField(282, "XResolution", resolution, 1));
-            ifd.appendChild(createRationalField(283, "YResolution", resolution, 1));
-            ifd.appendChild(createShortField(296, "ResolutionUnit", 2)); // Inch
-
-            ifd.appendChild(createLongField(278, "RowsPerStrip", tiffImage.getHeight()));
-
-            ifd.appendChild(createAsciiField(305, "Software", "PDFBOX"));
-
-            try
-            {
-                meta.mergeTree(SUN_TIFF_NATIVE_FORMAT, root);
-            }
-            catch (IIOInvalidTreeException e)
-            {
-                throw new RuntimeException("Cannot update image metadata: "
-                        + e.getMessage(), e);
-            }
+            return (IIOMetadataNode) nodeList.item(0);
         }
+        IIOMetadataNode childNode = new IIOMetadataNode(name);
+        parentNode.appendChild(childNode);
+        return childNode;
     }
 
-    private static IIOMetadataNode createShortField(int tiffTagNumber, String name, int val)
+    // sets the DPI metadata
+    private static void setDPI(IIOMetadata metadata, int dpi, String formatName)
     {
-        IIOMetadataNode field, arrayNode, valueNode;
-        field = new IIOMetadataNode("TIFFField");
-        field.setAttribute("number", Integer.toString(tiffTagNumber));
-        field.setAttribute("name", name);
-        arrayNode = new IIOMetadataNode("TIFFShorts");
-        field.appendChild(arrayNode);
-        valueNode = new IIOMetadataNode("TIFFShort");
-        arrayNode.appendChild(valueNode);
-        valueNode.setAttribute("value", Integer.toString(val));
-        return field;
-    }
+        IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(STANDARD_METADATA_FORMAT);
 
-    private static IIOMetadataNode createAsciiField(int number, String name, String val)
-    {
-        IIOMetadataNode field, arrayNode, valueNode;
-        field = new IIOMetadataNode("TIFFField");
-        field.setAttribute("number", Integer.toString(number));
-        field.setAttribute("name", name);
-        arrayNode = new IIOMetadataNode("TIFFAsciis");
-        field.appendChild(arrayNode);
-        valueNode = new IIOMetadataNode("TIFFAscii");
-        arrayNode.appendChild(valueNode);
-        valueNode.setAttribute("value", val);
-        return field;
-    }
+        IIOMetadataNode dimension = getOrCreateChildNode(root, "Dimension");
 
-    private static IIOMetadataNode createLongField(int number, String name, long val)
-    {
-        IIOMetadataNode field, arrayNode, valueNode;
-        field = new IIOMetadataNode("TIFFField");
-        field.setAttribute("number", Integer.toString(number));
-        field.setAttribute("name", name);
-        arrayNode = new IIOMetadataNode("TIFFLongs");
-        field.appendChild(arrayNode);
-        valueNode = new IIOMetadataNode("TIFFLong");
-        arrayNode.appendChild(valueNode);
-        valueNode.setAttribute("value", Long.toString(val));
-        return field;
-    }
+        // PNG writer doesn't conform to the spec which is
+        // "The width of a pixel, in millimeters"
+        // but instead counts the pixels per millimeter
+        float res = "PNG".equals(formatName.toUpperCase())
+                    ? dpi / 25.4f
+                    : 25.4f / dpi;
 
-    private static IIOMetadataNode createRationalField(int number, String name, int numerator, int denominator)
-    {
-        IIOMetadataNode field, arrayNode, valueNode;
-        field = new IIOMetadataNode("TIFFField");
-        field.setAttribute("number", Integer.toString(number));
-        field.setAttribute("name", name);
-        arrayNode = new IIOMetadataNode("TIFFRationals");
-        field.appendChild(arrayNode);
-        valueNode = new IIOMetadataNode("TIFFRational");
-        arrayNode.appendChild(valueNode);
-        valueNode.setAttribute("value", numerator + "/" + denominator);
-        return field;
-    }
+        IIOMetadataNode child;
+
+        child = getOrCreateChildNode(dimension, "HorizontalPixelSize");
+        child.setAttribute("value", Double.toString(res));
+
+        child = getOrCreateChildNode(dimension, "VerticalPixelSize");
+        child.setAttribute("value", Double.toString(res));
 
+        try
+        {
+            metadata.mergeTree(STANDARD_METADATA_FORMAT, root);
+        }
+        catch (IIOInvalidTreeException e)
+        {
+            // should never happen
+            throw new RuntimeException(e);
+        }
+    }
 }

Added: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/NullOutputStream.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/NullOutputStream.java?rev=1584105&view=auto
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/NullOutputStream.java (added)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/NullOutputStream.java Wed Apr  2 17:47:00 2014
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+package org.apache.pdfbox.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Dummy output stream, everything written there gets lost.
+ *
+ * @author Tilman Hausherr
+ */
+public class NullOutputStream extends OutputStream
+{
+    @Override
+    public void write(int b) throws IOException
+    {
+    }
+
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+    }
+
+    @Override
+    public void write(byte[] b) throws IOException
+    {
+    }
+}

Propchange: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/util/NullOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java?rev=1584105&r1=1584104&r2=1584105&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java Wed Apr  2 17:47:00 2014
@@ -16,93 +16,237 @@
  */
 package org.apache.pdfbox.util;
 
+import java.awt.Color;
 import java.awt.image.BufferedImage;
+import java.io.DataInputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.stream.ImageInputStream;
 
 import junit.framework.TestCase;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * Test suite for ImageIOUtil.
- *
- * @version $Revision: 1.0 $
  */
 public class TestImageIOUtils extends TestCase
 {
+    private static final Log LOG = LogFactory.getLog(TestImageIOUtils.class);
 
+    
     /**
-     * Logger instance.
+     * Check whether the resource images can be saved.
+     * 
+     * @param resources
+     * @throws IOException 
      */
-    private static final Log LOG = LogFactory.getLog(TestImageIOUtils.class);
-
-    private boolean testFailed = false;
+    void checkSaveResources(PDResources resources) throws IOException
+    {
+        if (resources == null)
+        {
+            return;
+        }
+        Map<String, PDXObject> xobjects = resources.getXObjects();
+        if (xobjects != null)
+        {
+            for (String key : xobjects.keySet())
+            {
+                PDXObject xobject = xobjects.get(key);
+                if (xobject instanceof PDXObjectImage)
+                {
+                    PDXObjectImage imageObject = (PDXObjectImage) xobject;
+                    String suffix = imageObject.getSuffix();
+                    if (suffix != null)
+                    {
+                        if ("jpx".equals(suffix))
+                        {
+                            suffix = "JPEG2000";
+                        }
+                        boolean writeOK = ImageIOUtil.writeImage(imageObject.getRGBImage(), suffix, new NullOutputStream());
+                        assertTrue(writeOK);
+                    }
+                }
+                else if (xobject instanceof PDXObjectForm)
+                {
+                    checkSaveResources(((PDXObjectForm) xobject).getResources());
+                }
+            }
+        }
+    }
 
     /**
      * Validate page rendering for all supported image formats (JDK5).
      *
      * @param file The file to validate
-     * @param inDir Name of the input directory
      * @param outDir Name of the output directory
-     * @throws Exception when there is an exception
+     * @throws IOException when there is an exception
      */
-    private void doTestFile(File file, String inDir, String outDir)
-        throws Exception
+    private void doTestFile(File file, String outDir) throws IOException
     {
         PDDocument document = null;
         String imageType = "png";
         LOG.info("Preparing to convert " + file.getName());
         try
         {
-            int resolution = 120;
-            document =  PDDocument.load(file);
+            float dpi = 120;
+            document = PDDocument.load(file);
+
+            // Save image resources of first page
+            List<PDPage> pdPages = document.getDocumentCatalog().getAllPages();
+            checkSaveResources(pdPages.get(0).getResources());
+
             // testing PNG
-            writeImage(document, imageType, outDir + file.getName() + "-", 
-                    BufferedImage.TYPE_INT_RGB, resolution);
+            writeImage(document, imageType, outDir + file.getName() + "-", BufferedImage.TYPE_INT_RGB, dpi);
+            checkResolution(outDir + file.getName() + "-1." + imageType, (int) dpi);
+
             // testing JPG/JPEG
             imageType = "jpg";
-            writeImage(document, imageType, outDir + file.getName() + "-", 
-                    BufferedImage.TYPE_INT_RGB, resolution);
+            writeImage(document, imageType, outDir + file.getName() + "-", BufferedImage.TYPE_INT_RGB, dpi);
+            checkResolution(outDir + file.getName() + "-1." + imageType, (int) dpi);
+
             // testing BMP
             imageType = "bmp";
-            writeImage(document, imageType, outDir + file.getName() + "-", 
-                    BufferedImage.TYPE_INT_RGB, resolution);
+            writeImage(document, imageType, outDir + file.getName() + "-", BufferedImage.TYPE_INT_RGB, dpi);
+            checkResolution(outDir + file.getName() + "-1." + imageType, (int) dpi);
+
+            // testing GIF
+            imageType = "gif";
+            writeImage(document, imageType, outDir + file.getName() + "-", BufferedImage.TYPE_INT_RGB, dpi);
+            // no META data posible for GIF, thus no test
+
             // testing WBMP
             imageType = "wbmp";
-            writeImage(document, imageType, outDir + file.getName() + "-", 
-                    BufferedImage.TYPE_BYTE_BINARY, resolution);
+            writeImage(document, imageType, outDir + file.getName() + "-", BufferedImage.TYPE_BYTE_BINARY, dpi);
+            // no META data posible for WBMP, thus no test
+
             // testing TIFF
             imageType = "tif";
-            writeImage(document, imageType, outDir + file.getName() + "-bw-", BufferedImage.TYPE_BYTE_BINARY, resolution);
-            writeImage(document, imageType, outDir + file.getName() + "-co-", BufferedImage.TYPE_INT_RGB, resolution);
-        }
-        catch(Exception e)
-        { 
-            testFailed = true;
-            LOG.error("Error converting file " + file.getName() + " using image type " + imageType, e);
+            writeImage(document, imageType, outDir + file.getName() + "-bw-", BufferedImage.TYPE_BYTE_BINARY, dpi);
+            checkResolution(outDir + file.getName() + "-bw-1." + imageType, (int) dpi);
+            checkTiffCompression(outDir + file.getName() + "-bw-1." + imageType, "CCITT T.6");
+            writeImage(document, imageType, outDir + file.getName() + "-co-", BufferedImage.TYPE_INT_RGB, dpi);
+            checkResolution(outDir + file.getName() + "-co-1." + imageType, (int) dpi);
+            checkTiffCompression(outDir + file.getName() + "-co-1." + imageType, "LZW");
         }
         finally
         {
-            document.close();
+            if (document != null)
+            {
+                document.close();
+            }
         }
+    }
+
+    /**
+     * Checks whether file image size and content are identical
+     *
+     * @param filename the filename where we just wrote to
+     * @param image the image that is to be checked
+     * @throws IOException if something goes wrong
+     */
+    private void checkImageFileSizeAndContent(String filename, BufferedImage image)
+            throws IOException
+    {
+        BufferedImage newImage = ImageIO.read(new File(filename));
+        assertNotNull("File '" + filename + "' could not be read", newImage);
+        checkNotBlank(filename, newImage);
+        checkBufferedImageSize(filename, image, newImage);
+        for (int x = 0; x < image.getWidth(); ++x)
+        {
+            for (int y = 0; y < image.getHeight(); ++y)
+            {
+                if (image.getRGB(x, y) != newImage.getRGB(x, y))
+                {
+                    assertEquals("\"File '" + filename + "' has different pixel at (" + x + "," + y + ")", new Color(image.getRGB(x, y)), new Color(newImage.getRGB(x, y)));
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks whether file image size is identical
+     *
+     * @param filename the filename where we just wrote to
+     * @param image the image that is to be checked
+     * @throws IOException if something goes wrong
+     */
+    private void checkImageFileSize(String filename, BufferedImage image)
+            throws IOException
+    {
+        BufferedImage newImage = ImageIO.read(new File(filename));
+        assertNotNull("File '" + filename + "' could not be read", newImage);
+        checkNotBlank(filename, newImage);
+        checkBufferedImageSize(filename, image, newImage);
+    }
+
+    private void checkBufferedImageSize(String filename,
+            BufferedImage image, BufferedImage newImage) throws IOException
+    {
+        assertEquals("File '" + filename + "' has different height after read", image.getHeight(), newImage.getHeight());
+        assertEquals("File '" + filename + "' has different width after read", image.getWidth(), newImage.getWidth());
+    }
 
+    private void checkNotBlank(String filename, BufferedImage newImage)
+    {
+        // http://stackoverflow.com/a/5253698/535646
+        Set<Integer> colors = new HashSet<Integer>();
+        int w = newImage.getWidth();
+        int h = newImage.getHeight();
+        for (int x = 0; x < w; x++)
+        {
+            for (int y = 0; y < h; y++)
+            {
+                colors.add(newImage.getRGB(x, y));
+            }
+        }
+        assertFalse("File '" + filename + "' has less than two colors", colors.size() < 2);
     }
 
-    private void writeImage(PDDocument document, String imageFormat, String outputPrefix, int imageType, int resolution)
-    throws IOException
+    private void writeImage(PDDocument document, String imageFormat, String outputPrefix,
+            int imageType, float dpi) throws IOException
     {
         List pages = document.getDocumentCatalog().getAllPages();
-        PDPage page = (PDPage)pages.get( 0 );
-        BufferedImage image = page.convertToImage(imageType, resolution);
-        String fileName = outputPrefix + "1." +imageFormat;
-        System.out.println( "Writing: " + fileName);
-        ImageIOUtil.writeImage(image, fileName, resolution);
+        PDPage page = (PDPage) pages.get(0);
+        BufferedImage image = page.convertToImage(imageType, Math.round(dpi));
+        String fileName = outputPrefix + "1." + imageFormat;
+        System.out.println("Writing: " + fileName);
+        boolean res = ImageIOUtil.writeImage(image, fileName, Math.round(dpi));
+        assertTrue("ImageIOUtil.writeImage() failed for file " + fileName, res);
+        if ("jpg".equals(imageFormat) || "gif".equals(imageFormat))
+        {
+            // jpeg is lossy, gif has 256 colors, 
+            // so we can't check for content identity
+            checkImageFileSize(fileName, image);
+        }
+        else
+        {
+            checkImageFileSizeAndContent(fileName, image);
+        }
     }
 
     /**
@@ -110,29 +254,132 @@ public class TestImageIOUtils extends Te
      *
      * @throws Exception when there is an exception
      */
-    public void testRenderImage()
-        throws Exception
+    public void testRenderImage() throws Exception
     {
         String inDir = "src/test/resources/input/rendering";
-        String outDir = "target/test-output/";
+        String outDir = "target/test-output/";        
 
-            File[] testFiles = new File(inDir).listFiles(new FilenameFilter()
-            {
-                public boolean accept(File dir, String name)
-                {
-                    return (name.endsWith(".pdf") || name.endsWith(".ai"));
-                }
-            });
+        new File(outDir).mkdirs();
+        if (!new File(outDir).exists())
+        {
+            throw new IOException("could not create output directory");
+        }
 
-            for (int n = 0; n < testFiles.length; n++)
+        File[] testFiles = new File(inDir).listFiles(new FilenameFilter()
+        {
+            public boolean accept(File dir, String name)
             {
-                doTestFile(testFiles[n], inDir, outDir);
+                return (name.endsWith(".pdf") || name.endsWith(".ai"));
             }
+        });
 
-            if (testFailed)
-            {
-                fail("One or more failures, see test log for details");
-            }
+        for (File file : testFiles)
+        {
+            doTestFile(file, outDir);
+        }
+    }
+
+    private static final String STANDARD_METADATA_FORMAT = "javax_imageio_1.0";
+
+    /**
+     * checks whether the resolution of an image file is as expected.
+     *
+     * @param filename the name of the file
+     * @param expectedResolution the expected resolution
+     *
+     * @throws IOException if something goes wrong
+     */
+    private void checkResolution(String filename, int expectedResolution)
+            throws IOException
+    {
+        assertFalse("Empty file " + filename, new File(filename).length() == 0);
+        String suffix = filename.substring(filename.lastIndexOf('.') + 1);
+        if ("BMP".equals(suffix.toUpperCase()))
+        {
+            // BMP reader doesn't work
+            checkBmpResolution(filename, expectedResolution);
+            return;
+        }
+        Iterator readers = ImageIO.getImageReadersBySuffix(suffix);
+        assertTrue("No image reader found for suffix " + suffix, readers.hasNext());
+        ImageReader reader = (ImageReader) readers.next();
+        ImageInputStream iis = ImageIO.createImageInputStream(new File(filename));
+        assertNotNull("No ImageInputStream created for file " + filename, iis);
+        reader.setInput(iis);
+        IIOMetadata imageMetadata = reader.getImageMetadata(0);
+        Element root = (Element) imageMetadata.getAsTree(STANDARD_METADATA_FORMAT);
+        NodeList dimensionNodes = root.getElementsByTagName("Dimension");
+        assertTrue("No resolution found in image file " + filename, dimensionNodes.getLength() > 0);
+        Element dimensionElement = (Element) dimensionNodes.item(0);
+
+        NodeList pixelSizeNodes = dimensionElement.getElementsByTagName("HorizontalPixelSize");
+        assertTrue("No X resolution found in image file " + filename, pixelSizeNodes.getLength() > 0);
+        Node pixelSizeNode = pixelSizeNodes.item(0);
+        String val = pixelSizeNode.getAttributes().getNamedItem("value").getNodeValue();
+        int actualResolution = (int) Math.round(25.4 / Double.parseDouble(val));
+        assertEquals("X resolution doesn't match in image file " + filename, expectedResolution, actualResolution);
+
+        pixelSizeNodes = dimensionElement.getElementsByTagName("VerticalPixelSize");
+        assertTrue("No Y resolution found in image file " + filename, pixelSizeNodes.getLength() > 0);
+        pixelSizeNode = pixelSizeNodes.item(0);
+        val = pixelSizeNode.getAttributes().getNamedItem("value").getNodeValue();
+        actualResolution = (int) Math.round(25.4 / Double.parseDouble(val));
+        assertEquals("Y resolution doesn't match", expectedResolution, actualResolution);
+
+        iis.close();
+        reader.dispose();
+    }
+
+    /**
+     * checks whether the resolution of a BMP image file is as expected.
+     *
+     * @param filename the name of the BMP file
+     * @param expectedResolution the expected resolution
+     *
+     * @throws IOException if something goes wrong
+     */
+    private void checkBmpResolution(String filename, int expectedResolution)
+            throws FileNotFoundException, IOException
+    {
+        // BMP format explained here:
+        // http://www.javaworld.com/article/2077561/learn-java/java-tip-60--saving-bitmap-files-in-java.html
+        // we skip 38 bytes and then read two 4 byte-integers and reverse the bytes
+        DataInputStream dis = new DataInputStream(new FileInputStream(new File(filename)));
+        int skipped = dis.skipBytes(38);
+        assertEquals("Can't skip 38 bytes in image file " + filename, 38, skipped);
+        int pixelsPerMeter = Integer.reverseBytes(dis.readInt());
+        int actualResolution = (int) Math.round(pixelsPerMeter / 100.0 * 2.54);
+        assertEquals("X resolution doesn't match in image file " + filename,
+                expectedResolution, actualResolution);
+        pixelsPerMeter = Integer.reverseBytes(dis.readInt());
+        actualResolution = (int) Math.round(pixelsPerMeter / 100.0 * 2.54);
+        assertEquals("Y resolution doesn't match in image file " + filename,
+                expectedResolution, actualResolution);
+        dis.close();
+    }
+
+    /**
+     * checks whether the compression of a TIFF file is as expected.
+     *
+     * @param filename Filename
+     * @param expectedCompression expected TIFF compression
+     *
+     * @throws IOException if something goes wrong
+     */
+    void checkTiffCompression(String filename, String expectedCompression) throws IOException
+    {
+        Iterator readers = ImageIO.getImageReadersBySuffix("tiff");
+        ImageReader reader = (ImageReader) readers.next();
+        ImageInputStream iis = ImageIO.createImageInputStream(new File(filename));
+        reader.setInput(iis);
+        IIOMetadata imageMetadata = reader.getImageMetadata(0);
+        Element root = (Element) imageMetadata.getAsTree(STANDARD_METADATA_FORMAT);
+        Element comprElement = (Element) root.getElementsByTagName("Compression").item(0);
+        Node comprTypeNode = comprElement.getElementsByTagName("CompressionTypeName").item(0);
+        String actualCompression = comprTypeNode.getAttributes().getNamedItem("value").getNodeValue();
+        assertEquals("Incorrect TIFF compression in file " + filename, expectedCompression, actualCompression);
+        iis.close();
+        reader.dispose();
     }
 
 }

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JBIG2Image.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JBIG2Image.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JBIG2Image.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestCMYK.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestCMYK.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestCMYK.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestGrey.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestGrey.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestGrey.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestRGB.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestRGB.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/JPXTestRGB.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/ccitt4-cib-test.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/ccitt4-cib-test.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/ccitt4-cib-test.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/jpeg_demo.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/jpeg_demo.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/jpeg_demo.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/png_demo.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/png_demo.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/png_demo.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf

Added: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/raw_image_demo.pdf
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/raw_image_demo.pdf?rev=1584105&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/branches/1.8/pdfbox/src/test/resources/input/rendering/raw_image_demo.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf



Mime
View raw message