blob: d87624245ebeac6c06908ce130ddb7559c463cdd [file] [log] [blame]
/*
* 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;
}
}
}