| /* |
| * 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. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.xmlgraphics.image.writer.imageio; |
| |
| import java.awt.image.RenderedImage; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.util.Iterator; |
| |
| import javax.imageio.IIOImage; |
| import javax.imageio.ImageIO; |
| import javax.imageio.ImageTypeSpecifier; |
| import javax.imageio.ImageWriteParam; |
| import javax.imageio.event.IIOWriteWarningListener; |
| import javax.imageio.metadata.IIOInvalidTreeException; |
| import javax.imageio.metadata.IIOMetadata; |
| import javax.imageio.metadata.IIOMetadataNode; |
| import javax.imageio.stream.ImageOutputStream; |
| |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import org.apache.xmlgraphics.image.writer.ImageWriter; |
| import org.apache.xmlgraphics.image.writer.ImageWriterParams; |
| import org.apache.xmlgraphics.image.writer.MultiImageWriter; |
| |
| /** |
| * ImageWriter implementation that uses Image I/O to write images. |
| * |
| * @version $Id$ |
| */ |
| public class ImageIOImageWriter implements ImageWriter, IIOWriteWarningListener { |
| |
| private static final String STANDARD_METADATA_FORMAT = "javax_imageio_1.0"; |
| |
| private String targetMIME; |
| |
| /** |
| * Main constructor. |
| * @param mime the MIME type of the image format |
| */ |
| public ImageIOImageWriter(String mime) { |
| this.targetMIME = mime; |
| } |
| |
| /** |
| * @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream) |
| */ |
| public void writeImage(RenderedImage image, OutputStream out) throws IOException { |
| writeImage(image, out, null); |
| } |
| |
| /** |
| * @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream, ImageWriterParams) |
| */ |
| public void writeImage(RenderedImage image, OutputStream out, |
| ImageWriterParams params) |
| throws IOException { |
| javax.imageio.ImageWriter iiowriter = getIIOImageWriter(); |
| iiowriter.addIIOWriteWarningListener(this); |
| |
| ImageOutputStream imgout = ImageIO.createImageOutputStream(out); |
| try { |
| |
| ImageWriteParam iwParam = getDefaultWriteParam(iiowriter, image, params); |
| |
| ImageTypeSpecifier type; |
| if (iwParam.getDestinationType() != null) { |
| type = iwParam.getDestinationType(); |
| } else { |
| type = ImageTypeSpecifier.createFromRenderedImage(image); |
| } |
| |
| //Handle metadata |
| IIOMetadata meta = iiowriter.getDefaultImageMetadata( |
| type, iwParam); |
| //meta might be null for some JAI codecs as they don't support metadata |
| if (params != null && meta != null) { |
| meta = updateMetadata(meta, params); |
| } |
| |
| //Write image |
| iiowriter.setOutput(imgout); |
| IIOImage iioimg = new IIOImage(image, null, meta); |
| iiowriter.write(null, iioimg, iwParam); |
| |
| } finally { |
| imgout.close(); |
| iiowriter.dispose(); |
| } |
| } |
| |
| private javax.imageio.ImageWriter getIIOImageWriter() { |
| Iterator iter = ImageIO.getImageWritersByMIMEType(getMIMEType()); |
| javax.imageio.ImageWriter iiowriter = null; |
| if (iter.hasNext()) { |
| iiowriter = (javax.imageio.ImageWriter)iter.next(); |
| } |
| if (iiowriter == null) { |
| throw new UnsupportedOperationException("No ImageIO codec for writing " |
| + getMIMEType() + " is available!"); |
| } |
| return iiowriter; |
| } |
| |
| /** |
| * Returns the default write parameters for encoding the image. |
| * @param iiowriter The IIO ImageWriter that will be used |
| * @param image the image to be encoded |
| * @param params the parameters for this writer instance |
| * @return the IIO ImageWriteParam instance |
| */ |
| protected ImageWriteParam getDefaultWriteParam( |
| javax.imageio.ImageWriter iiowriter, RenderedImage image, |
| ImageWriterParams params) { |
| ImageWriteParam param = iiowriter.getDefaultWriteParam(); |
| //System.err.println("Param: " + params); |
| if ((params != null) && (params.getCompressionMethod() != null)) { |
| param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); |
| param.setCompressionType(params.getCompressionMethod()); |
| } |
| return param; |
| } |
| |
| /** |
| * Updates the metadata information based on the parameters to this writer. |
| * @param meta the metadata |
| * @param params the parameters |
| * @return the updated metadata |
| */ |
| protected IIOMetadata updateMetadata(IIOMetadata meta, ImageWriterParams params) { |
| if (meta.isStandardMetadataFormatSupported()) { |
| IIOMetadataNode root = (IIOMetadataNode)meta.getAsTree(STANDARD_METADATA_FORMAT); |
| IIOMetadataNode dim = getChildNode(root, "Dimension"); |
| IIOMetadataNode child; |
| if (params.getResolution() != null) { |
| child = getChildNode(dim, "HorizontalPixelSize"); |
| if (child == null) { |
| child = new IIOMetadataNode("HorizontalPixelSize"); |
| dim.appendChild(child); |
| } |
| child.setAttribute("value", |
| Double.toString(params.getResolution().doubleValue() / 25.4)); |
| child = getChildNode(dim, "VerticalPixelSize"); |
| if (child == null) { |
| child = new IIOMetadataNode("VerticalPixelSize"); |
| dim.appendChild(child); |
| } |
| child.setAttribute("value", |
| Double.toString(params.getResolution().doubleValue() / 25.4)); |
| } |
| try { |
| meta.mergeTree(STANDARD_METADATA_FORMAT, root); |
| } catch (IIOInvalidTreeException e) { |
| throw new RuntimeException("Cannot update image metadata: " |
| + e.getMessage()); |
| } |
| } |
| return meta; |
| } |
| |
| /** |
| * Returns a specific metadata child node |
| * @param n the base node |
| * @param name the name of the child |
| * @return the requested child node |
| */ |
| protected 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())) { |
| return (IIOMetadataNode)child; |
| } |
| } |
| return null; |
| } |
| |
| /** @see ImageWriter#getMIMEType() */ |
| public String getMIMEType() { |
| return this.targetMIME; |
| } |
| |
| /** @see org.apache.xmlgraphics.image.writer.ImageWriter#isFunctional() */ |
| public boolean isFunctional() { |
| Iterator iter = ImageIO.getImageWritersByMIMEType(getMIMEType()); |
| //Only return true if an IIO ImageWriter is available in the current environment |
| return (iter.hasNext()); |
| } |
| |
| /** |
| * @see javax.imageio.event.IIOWriteWarningListener#warningOccurred( |
| * javax.imageio.ImageWriter, int, java.lang.String) |
| */ |
| public void warningOccurred(javax.imageio.ImageWriter source, |
| int imageIndex, String warning) { |
| System.err.println("Problem while writing image using ImageI/O: " |
| + warning); |
| } |
| |
| /** |
| * @see org.apache.xmlgraphics.image.writer.ImageWriter#createMultiImageWriter( |
| * java.io.OutputStream) |
| */ |
| public MultiImageWriter createMultiImageWriter(OutputStream out) throws IOException { |
| return new IIOMultiImageWriter(out); |
| } |
| |
| /** @see org.apache.xmlgraphics.image.writer.ImageWriter#supportsMultiImageWriter() */ |
| public boolean supportsMultiImageWriter() { |
| javax.imageio.ImageWriter iiowriter = getIIOImageWriter(); |
| try { |
| return iiowriter.canWriteSequence(); |
| } finally { |
| iiowriter.dispose(); |
| } |
| } |
| |
| private class IIOMultiImageWriter implements MultiImageWriter { |
| |
| private javax.imageio.ImageWriter iiowriter; |
| private ImageOutputStream imageStream; |
| |
| public IIOMultiImageWriter(OutputStream out) throws IOException { |
| this.iiowriter = getIIOImageWriter(); |
| if (!iiowriter.canWriteSequence()) { |
| throw new UnsupportedOperationException("This ImageWriter does not support writing" |
| + " multiple images to a single image file."); |
| } |
| iiowriter.addIIOWriteWarningListener(ImageIOImageWriter.this); |
| |
| imageStream = ImageIO.createImageOutputStream(out); |
| iiowriter.setOutput(imageStream); |
| iiowriter.prepareWriteSequence(null); |
| } |
| |
| public void writeImage(RenderedImage image, ImageWriterParams params) throws IOException { |
| if (iiowriter == null) { |
| throw new IllegalStateException("MultiImageWriter already closed!"); |
| } |
| ImageWriteParam iwParam = getDefaultWriteParam(iiowriter, image, params); |
| |
| ImageTypeSpecifier type; |
| if (iwParam.getDestinationType() != null) { |
| type = iwParam.getDestinationType(); |
| } else { |
| type = ImageTypeSpecifier.createFromRenderedImage(image); |
| } |
| |
| //Handle metadata |
| IIOMetadata meta = iiowriter.getDefaultImageMetadata( |
| type, iwParam); |
| //meta might be null for some JAI codecs as they don't support metadata |
| if (params != null && meta != null) { |
| meta = updateMetadata(meta, params); |
| } |
| |
| //Write image |
| IIOImage iioimg = new IIOImage(image, null, meta); |
| iiowriter.writeToSequence(iioimg, iwParam); |
| } |
| |
| public void close() throws IOException { |
| imageStream.close(); |
| imageStream = null; |
| iiowriter.dispose(); |
| iiowriter = null; |
| } |
| |
| } |
| |
| } |