You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/03/10 06:36:00 UTC
svn commit: r1575831 - in /pdfbox/trunk:
pdfbox/src/main/java/org/apache/pdfbox/rendering/
pdfbox/src/main/java/org/apache/pdfbox/util/
pdfbox/src/test/java/org/apache/pdfbox/util/
tools/src/main/java/org/apache/pdfbox/tools/
Author: jahewson
Date: Mon Mar 10 05:36:00 2014
New Revision: 1575831
URL: http://svn.apache.org/r1575831
Log:
PDFBOX-1963: restore binary TIFF writing and clean up ImageIOUtil
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/ImageType.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java
pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFReader.java
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/ImageType.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/ImageType.java?rev=1575831&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/ImageType.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/ImageType.java Mon Mar 10 05:36:00 2014
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.rendering;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Image type for rendering.
+ */
+public enum ImageType
+{
+ /** Black or white. */
+ BINARY {
+ @Override
+ int toBufferedImageType()
+ {
+ return BufferedImage.TYPE_BYTE_BINARY;
+ }
+ },
+
+ /** Shades of gray */
+ GRAY {
+ @Override
+ int toBufferedImageType()
+ {
+ return BufferedImage.TYPE_BYTE_GRAY;
+ }
+ },
+
+ /** Red, Green, Blue */
+ RGB {
+ @Override
+ int toBufferedImageType()
+ {
+ return BufferedImage.TYPE_INT_RGB;
+ }
+ },
+
+ /** Alpha, Red, Green, Blue */
+ ARGB {
+ @Override
+ int toBufferedImageType()
+ {
+ return BufferedImage.TYPE_INT_ARGB;
+ }
+ };
+
+ abstract int toBufferedImageType();
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java?rev=1575831&r1=1575830&r2=1575831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java Mon Mar 10 05:36:00 2014
@@ -67,7 +67,7 @@ public class PDFRenderer
*/
public BufferedImage renderImage(int pageIndex, float scale) throws IOException
{
- return renderImage(pageIndex, scale, false);
+ return renderImage(pageIndex, scale, ImageType.RGB);
}
/**
@@ -77,33 +77,34 @@ public class PDFRenderer
* @return the rendered page image
* @throws IOException if the PDF cannot be read
*/
- public BufferedImage renderImageWithDPI(int pageIndex, int dpi) throws IOException
+ public BufferedImage renderImageWithDPI(int pageIndex, float dpi) throws IOException
{
- return renderImage(pageIndex, dpi / 72f, false);
+ return renderImage(pageIndex, dpi / 72f, ImageType.RGB);
}
/**
* Returns the given page as an RGB image at the given DPI.
* @param pageIndex the zero-based index of the page to be converted
* @param dpi the DPI (dots per inch) to render at
+ * @param imageType the type of image to return
* @return the rendered page image
* @throws IOException if the PDF cannot be read
*/
- public BufferedImage renderImageWithDPI(int pageIndex, int dpi, boolean useAlpha)
+ public BufferedImage renderImageWithDPI(int pageIndex, float dpi, ImageType imageType)
throws IOException
{
- return renderImage(pageIndex, dpi / 72f, useAlpha);
+ return renderImage(pageIndex, dpi / 72f, imageType);
}
/**
* Returns the given page as an RGB or ARGB image at the given scale.
* @param pageIndex the zero-based index of the page to be converted
* @param scale the scaling factor, where 1 = 72 DPI
- * @param useAlpha true if an ARGB image is to be returned
+ * @param imageType the type of image to return
* @return the rendered page image
* @throws IOException if the PDF cannot be read
*/
- public BufferedImage renderImage(int pageIndex, float scale, boolean useAlpha)
+ public BufferedImage renderImage(int pageIndex, float scale, ImageType imageType)
throws IOException
{
PDPage page = document.getPage(pageIndex);
@@ -125,24 +126,20 @@ public class PDFRenderer
rotationAngle -= 360;
}
- int imageType = useAlpha ?
- BufferedImage.TYPE_INT_ARGB :
- BufferedImage.TYPE_INT_RGB;
-
// swap width and height
BufferedImage image;
if (rotationAngle == 90 || rotationAngle == 270)
{
- image = new BufferedImage(heightPx, widthPx, imageType);
+ image = new BufferedImage(heightPx, widthPx, imageType.toBufferedImageType());
}
else
{
- image = new BufferedImage(widthPx, heightPx, imageType);
+ image = new BufferedImage(widthPx, heightPx, imageType.toBufferedImageType());
}
// use a transparent background if the imageType supports alpha
Graphics2D g = image.createGraphics();
- if (!useAlpha)
+ if (imageType != ImageType.ARGB)
{
g.setBackground(Color.WHITE);
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java?rev=1575831&r1=1575830&r2=1575831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/ImageIOUtil.java Mon Mar 10 05:36:00 2014
@@ -17,13 +17,11 @@
package org.apache.pdfbox.util;
import java.awt.image.BufferedImage;
-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;
@@ -33,436 +31,175 @@ 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 org.w3c.dom.NodeList;
+import org.apache.pdfbox.filter.MissingImageReaderException;
+import org.w3c.dom.Element;
/**
- * This class handles some ImageIO operations.
- *
- * @version $Revision$
- *
+ * Handles some ImageIO operations.
*/
public class ImageIOUtil
-{
- /**
- * Log instance.
- */
- private static final Log LOG = LogFactory.getLog(ImageIOUtil.class);
-
- /**
- * Default screen resolution: 72dpi.
- */
- public static final int DEFAULT_SCREEN_RESOLUTION = 72;
- /**
- * Default compression quality: 1.0f.
- */
- public static final float DEFAULT_COMPRESSION_QUALITY = 1.0f;
-
+{
private ImageIOUtil()
{
- // Default constructor
}
/**
* Writes a buffered image to a file using the given image format.
- *
* @param image the image to be written
- * @param imageFormat the target format (ex. "png")
+ * @param formatName the target format (ex. "png")
* @param filename used to construct the filename for the individual images
- * @param resolution the resolution in dpi (dots per inch)
- *
+ * @param dpi the resolution in dpi (dots per inch)
* @return true if the images were produced, false if there was an error
* @throws IOException if an I/O error occurs
*/
- public static boolean writeImage(BufferedImage image, String imageFormat, String filename,
- int resolution) throws IOException
+ public static boolean writeImage(BufferedImage image, String formatName, String filename,
+ int dpi) throws IOException
{
- String fileName = filename + "." + imageFormat;
- File file = new File(fileName);
- return writeImage(image, imageFormat, file, resolution);
+ OutputStream output = new FileOutputStream(filename + "." + formatName);
+ try
+ {
+ return writeImage(image, formatName, output, dpi);
+ }
+ finally
+ {
+ output.close();
+ }
}
/**
* Writes a buffered image to a file using the given image format.
- *
* @param image the image to be written
- * @param imageFormat the target format (ex. "png")
- * @param outputStream the output stream to be used for writing
- *
+ * @param formatName the target format (ex. "png")
+ * @param output the output stream to be used for writing
* @return true if the images were produced, false if there was an error
* @throws IOException if an I/O error occurs
*/
- public static boolean writeImage(BufferedImage image, String imageFormat,
- OutputStream outputStream) throws IOException
+ public static boolean writeImage(BufferedImage image, String formatName, OutputStream output)
+ throws IOException
{
- return writeImage(image, imageFormat, outputStream, DEFAULT_SCREEN_RESOLUTION);
+ return writeImage(image, formatName, output, 72);
}
/**
* Writes a buffered image to a file using the given image format.
- *
* @param image the image to be written
- * @param imageFormat the target format (ex. "png")
- * @param outputStream the output stream to be used for writing
- * @param resolution resolution to be used when writing the image
- *
+ * @param formatName the target format (ex. "png")
+ * @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
* @throws IOException if an I/O error occurs
*/
- public static boolean writeImage(BufferedImage image, String imageFormat, Object outputStream,
- int resolution) throws IOException
+ public static boolean writeImage(BufferedImage image, String formatName, OutputStream output,
+ int dpi) throws IOException
{
- return writeImage(image, imageFormat, outputStream, resolution, DEFAULT_COMPRESSION_QUALITY);
+ return writeImage(image, formatName, output, dpi, 1.0f);
}
/**
* Writes a buffered image to a file using the given image format.
- *
* @param image the image to be written
- * @param imageFormat the target format (ex. "png")
- * @param outputStream the output stream to be used for writing
- * @param resolution resolution to be used when writing the image
- * @param quality quality to be used when compressing the image (0 <
- * quality < 1.0f)
- *
+ * @param formatName the target format (ex. "png")
+ * @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 < quality < 1.0f)
* @return true if the images were produced, false if there was an error
* @throws IOException if an I/O error occurs
*/
- public static boolean writeImage(BufferedImage image, String imageFormat, Object outputStream,
- int resolution, 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(imageFormat);
- while (writerIter.hasNext() && !foundWriter)
- {
- try
+ // find suitable image writer
+ Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+ ImageWriteParam param = null;
+ IIOMetadata metadata = null;
+ while (writers.hasNext())
+ {
+ writer = writers.next();
+ param = writer.getDefaultWriteParam();
+ metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), param);
+ if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported())
{
- 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 (imageFormat.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, resolution);
- if (meta != null)
- {
- imageWriter.setOutput(output);
- imageWriter.write(null, new IIOImage(image, null, meta), writerParams);
- foundWriter = true;
- }
+ writer = null;
}
- catch (IIOException io)
+ }
+
+ if (writer == null)
+ {
+ return false;
+ }
+
+ // compression
+ if (param.canWriteCompressed())
+ {
+ if (formatName.toLowerCase().startsWith("tif"))
{
- LOG.error("IIOException in writeImage()", io);
- throw new IOException(io.getMessage());
+ // TIFF compression
+ TIFFUtil.setCompressionType(param, image);
}
- finally
+ else
{
- if (imageWriter != null)
- {
- imageWriter.dispose();
- }
+ // JPEG, PNG compression
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param.setCompressionType(param.getCompressionTypes()[0]);
+ param.setCompressionQuality(quality);
}
}
- if (!foundWriter)
+
+ // metadata
+ setDPI(metadata, dpi);
+
+ // TIFF metadata
+ if (formatName.toLowerCase().startsWith("tif"))
{
- LOG.error("No writer found for format '" + imageFormat + "'");
- bSuccess = false;
+ TIFFUtil.updateMetadata(metadata, image, dpi);
}
+
+ // write
+ imageOutput = ImageIO.createImageOutputStream(output);
+ writer.setOutput(imageOutput);
+ writer.write(null, new IIOImage(image, null, metadata), param);
}
finally
{
- if (output != null)
+ if (writer != null)
{
- output.flush();
- output.close();
+ writer.dispose();
}
- }
- return bSuccess;
- }
-
- private static IIOMetadata createMetadata(BufferedImage image, ImageWriter imageWriter,
- ImageWriteParam writerParams, int resolution)
- {
- 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, resolution);
- }
- else
- {
- if (!addResolution(meta, resolution))
+ if (imageOutput != null)
{
- meta = null;
+ imageOutput.close();
}
}
- logMeta(meta, STANDARD_METADATA_FORMAT);
- return meta;
+ return true;
}
- /**
- * 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)
+ // sets the DPI metadata
+ private static void setDPI(IIOMetadata metadata, int dpi)
{
- 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);
- }
- }
+ IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
+ Element dimension = new IIOMetadataNode("Dimension");
- 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";
+ Element h = new IIOMetadataNode("HorizontalPixelSize");
+ h.setAttribute("value", Double.toString(dpi / 25.4));
+ dimension.appendChild(h);
- private static boolean addResolution(IIOMetadata meta, int resolution)
- {
- if (meta != null && !meta.isReadOnly() && meta.isStandardMetadataFormatSupported())
- {
- 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)
- {
- throw new RuntimeException("Cannot update image metadata: "
- + e.getMessage());
- }
- return true;
- }
- return false;
- }
+ Element v = new IIOMetadataNode("HorizontalPixelSize");
+ v.setAttribute("value", Double.toString(dpi / 25.4));
+ dimension.appendChild(v);
- private static IIOMetadataNode getChildNode(Node n, String name)
- {
- NodeList nodes = n.getChildNodes();
- for (int i = 0; i < nodes.getLength(); i++)
+ try
{
- Node child = nodes.item(i);
- if (name.equals(child.getNodeName()))
- {
- return (IIOMetadataNode)child;
- }
+ metadata.mergeTree("javax_imageio_1.0", root);
}
- return null;
- }
-
- /**
- * 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".
- *
- * @param tiffImage the TIFF Image
- * @param meta the meta data that is to be set
- * @param resolution in dots per inch
- */
- protected static void updateMetadata(BufferedImage tiffImage, IIOMetadata meta, int resolution)
- {
- // 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()))
+ catch (IIOInvalidTreeException e)
{
- 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);
- }
+ // should never happen
+ throw new RuntimeException(e);
}
}
-
- private static IIOMetadataNode createShortField(int tiffTagNumber, String name, int val)
- {
- 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;
- }
-
- 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;
- }
-
- 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;
- }
-
- 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;
- }
-
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java?rev=1575831&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/TIFFUtil.java Mon Mar 10 05:36:00 2014
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.imageio.ImageWriteParam;
+import javax.imageio.metadata.IIOInvalidTreeException;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
+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 java.awt.image.BufferedImage;
+import java.io.StringWriter;
+
+/**
+ * Used by ImageIOUtil to write TIFF files.
+ * @author Tilman Hausherr
+ */
+class TIFFUtil
+{
+ private static final Log LOG = LogFactory.getLog(TIFFUtil.class);
+ private static final String SUN_TIFF_FORMAT = "com_sun_media_imageio_plugins_tiff_image_1.0";
+
+ /**
+ * Sets the ImageIO parameter compression type based on the given image.
+ * @param image buffered image used to decide compression type
+ * @param param ImageIO write parameter to update
+ */
+ public static void setCompressionType(ImageWriteParam param, BufferedImage image)
+ {
+ // avoid error: first compression type is RLE, not optimal and incorrect for color images
+ // TODO expose this choice to the user?
+ if (image.getType() == BufferedImage.TYPE_BYTE_BINARY &&
+ image.getColorModel().getPixelSize() == 1)
+ {
+ param.setCompressionType("CCITT T.6");
+ }
+ else
+ {
+ param.setCompressionType("LZW");
+ }
+ }
+
+ /**
+ * Updates the given ImageIO metadata with Sun's custom TIFF tags.
+ * {@see https://svn.apache.org/repos/asf/xmlgraphics/commons/tags/commons-1_3_1/src/java/org/
+ * apache/xmlgraphics/image/writer/imageio/ImageIOTIFFImageWriter.java}
+ * {@see http://download.java.net/media/jai-imageio/javadoc/1.0_01/com/sun/media/imageio/
+ * plugins/tiff/package-summary.html}
+ * {@see http://partners.adobe.com/public/developer/tiff/index.html}
+ * @param image buffered image which will be written
+ * @param metadata ImageIO metadata
+ * @param dpi image dots per inch
+ */
+ public static void updateMetadata(IIOMetadata metadata, BufferedImage image, int dpi)
+ {
+ debugLogMetadata(metadata);
+
+ if (!SUN_TIFF_FORMAT.equals(metadata.getNativeMetadataFormatName()))
+ {
+ LOG.debug("Using unknown TIFF image writer: " + metadata.getNativeMetadataFormatName());
+ return;
+ }
+
+ IIOMetadataNode root = new IIOMetadataNode(SUN_TIFF_FORMAT);
+ IIOMetadataNode ifd;
+ if (root.getElementsByTagName("TIFFIFD").getLength() == 0)
+ {
+ ifd = (IIOMetadataNode)root.getElementsByTagName("TIFFIFD").item(0);
+ }
+ else
+ {
+ ifd = new IIOMetadataNode("TIFFIFD");
+ ifd.setAttribute("tagSets",
+ "com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet");
+ root.appendChild(ifd);
+ }
+
+ // standard metadata does not work, so we set the DPI manually
+ ifd.appendChild(createRationalField(282, "XResolution", dpi, 1));
+ ifd.appendChild(createRationalField(283, "YResolution", dpi, 1));
+ ifd.appendChild(createShortField(296, "ResolutionUnit", 2)); // Inch
+
+ ifd.appendChild(createLongField(278, "RowsPerStrip", image.getHeight()));
+ ifd.appendChild(createAsciiField(305, "Software", "PDFBOX"));
+
+ try
+ {
+ metadata.mergeTree(SUN_TIFF_FORMAT, root);
+ }
+ catch (IIOInvalidTreeException e)
+ {
+ // should never happen
+ throw new RuntimeException(e);
+ }
+
+ debugLogMetadata(metadata);
+ }
+
+ private static IIOMetadataNode createShortField(int tiffTagNumber, String name, int val)
+ {
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ // logs metadata as an XML tree if debug is enabled
+
+ private static void debugLogMetadata(IIOMetadata metadata)
+ {
+ if (LOG.isDebugEnabled())
+ {
+ return;
+ }
+
+ // see http://docs.oracle.com/javase/7/docs/api/javax/imageio/
+ // metadata/doc-files/standard_metadata.html
+ IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree("javax_imageio_1.0");
+ try
+ {
+ StringWriter xmlStringWriter = new StringWriter();
+ StreamResult streamResult = new StreamResult(xmlStringWriter);
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ // see http://stackoverflow.com/a/1264872/535646
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+ DOMSource domSource = new DOMSource(root);
+ transformer.transform(domSource, streamResult);
+ LOG.debug("\n" + xmlStringWriter);
+ }
+ catch (Exception ex)
+ {
+ LOG.error(ex, ex);
+ }
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java?rev=1575831&r1=1575830&r2=1575831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/util/TestImageIOUtils.java Mon Mar 10 05:36:00 2014
@@ -26,6 +26,7 @@ import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
/**
@@ -52,20 +53,20 @@ public class TestImageIOUtils extends Te
float dpi = 120;
document = PDDocument.load(file);
// testing PNG
- writeImage(document, imageType, outDir + file.getName() + "-", dpi);
+ writeImage(document, imageType, outDir + file.getName() + "-", ImageType.RGB, dpi);
// testing JPG/JPEG
imageType = "jpg";
- writeImage(document, imageType, outDir + file.getName() + "-", dpi);
+ writeImage(document, imageType, outDir + file.getName() + "-", ImageType.RGB, dpi);
// testing BMP
imageType = "bmp";
- writeImage(document, imageType, outDir + file.getName() + "-", dpi);
+ writeImage(document, imageType, outDir + file.getName() + "-", ImageType.RGB, dpi);
// testing WBMP
imageType = "wbmp";
- writeImage(document, imageType, outDir + file.getName() + "-", dpi);
+ writeImage(document, imageType, outDir + file.getName() + "-", ImageType.RGB, dpi);
// testing TIFF
imageType = "tif";
- writeImage(document, imageType, outDir + file.getName() + "-bw-", dpi);
- writeImage(document, imageType, outDir + file.getName() + "-co-", dpi);
+ writeImage(document, imageType, outDir + file.getName() + "-bw-", ImageType.BINARY, dpi);
+ writeImage(document, imageType, outDir + file.getName() + "-co-", ImageType.RGB, dpi);
}
finally
{
@@ -76,11 +77,12 @@ public class TestImageIOUtils extends Te
}
}
- private void writeImage(PDDocument document, String imageFormat, String outputPrefix, float dpi)
+ private void writeImage(PDDocument document, String imageFormat, String outputPrefix,
+ ImageType imageType, float dpi)
throws IOException
{
PDFRenderer renderer = new PDFRenderer(document);
- BufferedImage image = renderer.renderImage(0, dpi / 72f);
+ BufferedImage image = renderer.renderImageWithDPI(0, dpi, imageType);
String fileName = outputPrefix + 1;
LOG.info("Writing: " + fileName + "." + imageFormat);
ImageIOUtil.writeImage(image, imageFormat, fileName, Math.round(dpi));
Modified: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFReader.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFReader.java?rev=1575831&r1=1575830&r2=1575831&view=diff
==============================================================================
--- pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFReader.java (original)
+++ pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFReader.java Mon Mar 10 05:36:00 2014
@@ -356,8 +356,7 @@ public class PDFReader extends JFrame
imageFilename = imageFilename.substring(0, imageFilename.length() - 4);
}
imageFilename += "_" + (currentPage + 1);
- ImageIOUtil.writeImage(pageAsImage, "png", imageFilename,
- BufferedImage.TYPE_USHORT_565_RGB, 300);
+ ImageIOUtil.writeImage(pageAsImage, "png", imageFilename, 300);
}
catch (IOException exception)
{