001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: ImageIOImageWriter.java 496561 2007-01-16 01:17:01Z cam $ */
019:
020: package org.apache.xmlgraphics.image.writer.imageio;
021:
022: import java.awt.image.RenderedImage;
023: import java.io.IOException;
024: import java.io.OutputStream;
025: import java.util.Iterator;
026:
027: import javax.imageio.IIOImage;
028: import javax.imageio.ImageIO;
029: import javax.imageio.ImageTypeSpecifier;
030: import javax.imageio.ImageWriteParam;
031: import javax.imageio.event.IIOWriteWarningListener;
032: import javax.imageio.metadata.IIOInvalidTreeException;
033: import javax.imageio.metadata.IIOMetadata;
034: import javax.imageio.metadata.IIOMetadataNode;
035: import javax.imageio.stream.ImageOutputStream;
036:
037: import org.w3c.dom.Node;
038: import org.w3c.dom.NodeList;
039:
040: import org.apache.xmlgraphics.image.writer.ImageWriter;
041: import org.apache.xmlgraphics.image.writer.ImageWriterParams;
042: import org.apache.xmlgraphics.image.writer.MultiImageWriter;
043:
044: /**
045: * ImageWriter implementation that uses Image I/O to write images.
046: *
047: * @version $Id: ImageIOImageWriter.java 496561 2007-01-16 01:17:01Z cam $
048: */
049: public class ImageIOImageWriter implements ImageWriter,
050: IIOWriteWarningListener {
051:
052: private static final String STANDARD_METADATA_FORMAT = "javax_imageio_1.0";
053:
054: private String targetMIME;
055:
056: /**
057: * Main constructor.
058: * @param mime the MIME type of the image format
059: */
060: public ImageIOImageWriter(String mime) {
061: this .targetMIME = mime;
062: }
063:
064: /**
065: * @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream)
066: */
067: public void writeImage(RenderedImage image, OutputStream out)
068: throws IOException {
069: writeImage(image, out, null);
070: }
071:
072: /**
073: * @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream, ImageWriterParams)
074: */
075: public void writeImage(RenderedImage image, OutputStream out,
076: ImageWriterParams params) throws IOException {
077: javax.imageio.ImageWriter iiowriter = getIIOImageWriter();
078: iiowriter.addIIOWriteWarningListener(this );
079:
080: ImageOutputStream imgout = ImageIO.createImageOutputStream(out);
081: try {
082:
083: ImageWriteParam iwParam = getDefaultWriteParam(iiowriter,
084: image, params);
085:
086: ImageTypeSpecifier type;
087: if (iwParam.getDestinationType() != null) {
088: type = iwParam.getDestinationType();
089: } else {
090: type = ImageTypeSpecifier
091: .createFromRenderedImage(image);
092: }
093:
094: //Handle metadata
095: IIOMetadata meta = iiowriter.getDefaultImageMetadata(type,
096: iwParam);
097: //meta might be null for some JAI codecs as they don't support metadata
098: if (params != null && meta != null) {
099: meta = updateMetadata(meta, params);
100: }
101:
102: //Write image
103: iiowriter.setOutput(imgout);
104: IIOImage iioimg = new IIOImage(image, null, meta);
105: iiowriter.write(null, iioimg, iwParam);
106:
107: } finally {
108: imgout.close();
109: iiowriter.dispose();
110: }
111: }
112:
113: private javax.imageio.ImageWriter getIIOImageWriter() {
114: Iterator iter = ImageIO
115: .getImageWritersByMIMEType(getMIMEType());
116: javax.imageio.ImageWriter iiowriter = null;
117: if (iter.hasNext()) {
118: iiowriter = (javax.imageio.ImageWriter) iter.next();
119: }
120: if (iiowriter == null) {
121: throw new UnsupportedOperationException(
122: "No ImageIO codec for writing " + getMIMEType()
123: + " is available!");
124: }
125: return iiowriter;
126: }
127:
128: /**
129: * Returns the default write parameters for encoding the image.
130: * @param iiowriter The IIO ImageWriter that will be used
131: * @param image the image to be encoded
132: * @param params the parameters for this writer instance
133: * @return the IIO ImageWriteParam instance
134: */
135: protected ImageWriteParam getDefaultWriteParam(
136: javax.imageio.ImageWriter iiowriter, RenderedImage image,
137: ImageWriterParams params) {
138: ImageWriteParam param = iiowriter.getDefaultWriteParam();
139: //System.err.println("Param: " + params);
140: if ((params != null) && (params.getCompressionMethod() != null)) {
141: param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
142: param.setCompressionType(params.getCompressionMethod());
143: }
144: return param;
145: }
146:
147: /**
148: * Updates the metadata information based on the parameters to this writer.
149: * @param meta the metadata
150: * @param params the parameters
151: * @return the updated metadata
152: */
153: protected IIOMetadata updateMetadata(IIOMetadata meta,
154: ImageWriterParams params) {
155: if (meta.isStandardMetadataFormatSupported()) {
156: IIOMetadataNode root = (IIOMetadataNode) meta
157: .getAsTree(STANDARD_METADATA_FORMAT);
158: IIOMetadataNode dim = getChildNode(root, "Dimension");
159: IIOMetadataNode child;
160: if (params.getResolution() != null) {
161: child = getChildNode(dim, "HorizontalPixelSize");
162: if (child == null) {
163: child = new IIOMetadataNode("HorizontalPixelSize");
164: dim.appendChild(child);
165: }
166: child.setAttribute("value", Double.toString(params
167: .getResolution().doubleValue() / 25.4));
168: child = getChildNode(dim, "VerticalPixelSize");
169: if (child == null) {
170: child = new IIOMetadataNode("VerticalPixelSize");
171: dim.appendChild(child);
172: }
173: child.setAttribute("value", Double.toString(params
174: .getResolution().doubleValue() / 25.4));
175: }
176: try {
177: meta.mergeTree(STANDARD_METADATA_FORMAT, root);
178: } catch (IIOInvalidTreeException e) {
179: throw new RuntimeException(
180: "Cannot update image metadata: "
181: + e.getMessage());
182: }
183: }
184: return meta;
185: }
186:
187: /**
188: * Returns a specific metadata child node
189: * @param n the base node
190: * @param name the name of the child
191: * @return the requested child node
192: */
193: protected static IIOMetadataNode getChildNode(Node n, String name) {
194: NodeList nodes = n.getChildNodes();
195: for (int i = 0; i < nodes.getLength(); i++) {
196: Node child = nodes.item(i);
197: if (name.equals(child.getNodeName())) {
198: return (IIOMetadataNode) child;
199: }
200: }
201: return null;
202: }
203:
204: /** @see ImageWriter#getMIMEType() */
205: public String getMIMEType() {
206: return this .targetMIME;
207: }
208:
209: /** @see org.apache.xmlgraphics.image.writer.ImageWriter#isFunctional() */
210: public boolean isFunctional() {
211: Iterator iter = ImageIO
212: .getImageWritersByMIMEType(getMIMEType());
213: //Only return true if an IIO ImageWriter is available in the current environment
214: return (iter.hasNext());
215: }
216:
217: /**
218: * @see javax.imageio.event.IIOWriteWarningListener#warningOccurred(
219: * javax.imageio.ImageWriter, int, java.lang.String)
220: */
221: public void warningOccurred(javax.imageio.ImageWriter source,
222: int imageIndex, String warning) {
223: System.err
224: .println("Problem while writing image using ImageI/O: "
225: + warning);
226: }
227:
228: /**
229: * @see org.apache.xmlgraphics.image.writer.ImageWriter#createMultiImageWriter(
230: * java.io.OutputStream)
231: */
232: public MultiImageWriter createMultiImageWriter(OutputStream out)
233: throws IOException {
234: return new IIOMultiImageWriter(out);
235: }
236:
237: /** @see org.apache.xmlgraphics.image.writer.ImageWriter#supportsMultiImageWriter() */
238: public boolean supportsMultiImageWriter() {
239: javax.imageio.ImageWriter iiowriter = getIIOImageWriter();
240: try {
241: return iiowriter.canWriteSequence();
242: } finally {
243: iiowriter.dispose();
244: }
245: }
246:
247: private class IIOMultiImageWriter implements MultiImageWriter {
248:
249: private javax.imageio.ImageWriter iiowriter;
250: private ImageOutputStream imageStream;
251:
252: public IIOMultiImageWriter(OutputStream out) throws IOException {
253: this .iiowriter = getIIOImageWriter();
254: if (!iiowriter.canWriteSequence()) {
255: throw new UnsupportedOperationException(
256: "This ImageWriter does not support writing"
257: + " multiple images to a single image file.");
258: }
259: iiowriter
260: .addIIOWriteWarningListener(ImageIOImageWriter.this );
261:
262: imageStream = ImageIO.createImageOutputStream(out);
263: iiowriter.setOutput(imageStream);
264: iiowriter.prepareWriteSequence(null);
265: }
266:
267: public void writeImage(RenderedImage image,
268: ImageWriterParams params) throws IOException {
269: if (iiowriter == null) {
270: throw new IllegalStateException(
271: "MultiImageWriter already closed!");
272: }
273: ImageWriteParam iwParam = getDefaultWriteParam(iiowriter,
274: image, params);
275:
276: ImageTypeSpecifier type;
277: if (iwParam.getDestinationType() != null) {
278: type = iwParam.getDestinationType();
279: } else {
280: type = ImageTypeSpecifier
281: .createFromRenderedImage(image);
282: }
283:
284: //Handle metadata
285: IIOMetadata meta = iiowriter.getDefaultImageMetadata(type,
286: iwParam);
287: //meta might be null for some JAI codecs as they don't support metadata
288: if (params != null && meta != null) {
289: meta = updateMetadata(meta, params);
290: }
291:
292: //Write image
293: IIOImage iioimg = new IIOImage(image, null, meta);
294: iiowriter.writeToSequence(iioimg, iwParam);
295: }
296:
297: public void close() throws IOException {
298: imageStream.close();
299: imageStream = null;
300: iiowriter.dispose();
301: iiowriter = null;
302: }
303:
304: }
305:
306: }
|