Source Code Cross Referenced for ImageWriteDescriptor.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » operator » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » com.sun.media.jai.operator 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: ImageWriteDescriptor.java,v $
0003:         *
0004:         * 
0005:         * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
0006:         * 
0007:         * Redistribution and use in source and binary forms, with or without
0008:         * modification, are permitted provided that the following conditions
0009:         * are met: 
0010:         * 
0011:         * - Redistribution of source code must retain the above copyright 
0012:         *   notice, this  list of conditions and the following disclaimer.
0013:         * 
0014:         * - Redistribution in binary form must reproduce the above copyright
0015:         *   notice, this list of conditions and the following disclaimer in 
0016:         *   the documentation and/or other materials provided with the
0017:         *   distribution.
0018:         * 
0019:         * Neither the name of Sun Microsystems, Inc. or the names of 
0020:         * contributors may be used to endorse or promote products derived 
0021:         * from this software without specific prior written permission.
0022:         * 
0023:         * This software is provided "AS IS," without a warranty of any 
0024:         * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
0025:         * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
0026:         * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0027:         * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
0028:         * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
0029:         * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0030:         * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
0031:         * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0032:         * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0033:         * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0034:         * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0035:         * POSSIBILITY OF SUCH DAMAGES. 
0036:         * 
0037:         * You acknowledge that this software is not designed or intended for 
0038:         * use in the design, construction, operation or maintenance of any 
0039:         * nuclear facility. 
0040:         *
0041:         * $Revision: 1.1 $
0042:         * $Date: 2005/02/11 05:01:56 $
0043:         * $State: Exp $
0044:         */
0045:        package com.sun.media.jai.operator;
0046:
0047:        import java.awt.Dimension;
0048:        import java.awt.RenderingHints;
0049:        import java.awt.image.BufferedImage;
0050:        import java.awt.image.RenderedImage;
0051:        import java.awt.image.renderable.ParameterBlock;
0052:        import java.awt.image.renderable.RenderableImage;
0053:        import java.io.File;
0054:        import java.io.IOException;
0055:        import java.net.Socket;
0056:        import java.util.Collection;
0057:        import java.util.EventListener;
0058:        import java.util.Iterator;
0059:        import java.util.Locale;
0060:        import javax.imageio.ImageIO;
0061:        import javax.imageio.ImageWriteParam;
0062:        import javax.imageio.ImageWriter;
0063:        import javax.imageio.metadata.IIOMetadata;
0064:        import javax.imageio.spi.ImageWriterSpi;
0065:        import javax.imageio.stream.ImageOutputStream;
0066:        import javax.media.jai.CollectionOp;
0067:        import javax.media.jai.JAI;
0068:        import javax.media.jai.OperationDescriptorImpl;
0069:        import javax.media.jai.RenderableOp;
0070:        import javax.media.jai.RenderedOp;
0071:        import javax.media.jai.registry.CollectionRegistryMode;
0072:        import javax.media.jai.registry.RenderableRegistryMode;
0073:        import javax.media.jai.registry.RenderedRegistryMode;
0074:
0075:        /**
0076:         * An <code>OperationDescriptor</code> describing the "ImageWrite" operation.
0077:         *
0078:         * <p>The "ImageWrite" operation uses the
0079:         * <a href="http://java.sun.com/j2se/1.4/docs/guide/imageio/index.html">Java
0080:         * Image I/O Framework</a> to write images to an output destination. Which
0081:         * formats may be written depends on which {@link javax.imageio.ImageWriter}
0082:         * plug-ins are registered with the Image I/O Framework when the operation is
0083:         * invoked.</p>
0084:         *
0085:         * <p>The output destination will usually be an
0086:         * {@link javax.imageio.stream.ImageOutputStream}, but may be a
0087:         * {@link java.io.File}, {@link java.io.RandomAccessFile},
0088:         * {@link java.io.OutputStream}, {@link java.net.Socket},
0089:         * {@link java.nio.channels.WritableByteChannel}, file path represented as a
0090:         * <code>String</code> or some other type compatible with a writer plug-in. The
0091:         * {@link javax.imageio.ImageIO} class should be used to specify the location
0092:         * and enable the use of cache files via its <code>setCacheDirectory()</code>
0093:         * and <code>setUseCache()</code> methods, respectively. Note that this cache
0094:         * pertains to image stream caching and is unrelated to the JAI
0095:         * <code>TileCache</code>. If an {@link javax.imageio.stream.ImageOutputStream}
0096:         * is created internally by the operation, for example from a
0097:         * {@link java.io.File}-valued <a href="#ParamOutput">Output</a> parameter,
0098:         * then it will be flushed automatically if and only if the operation is not
0099:         * in <a href="#CollectionMode">collection mode</a> and pixel replacement is
0100:         * not occurring.</p>
0101:         *
0102:         * <p>The "ImageWrite" operation supports <a href="#RenderedMode">rendered</a>,
0103:         * <a href="#RenderableMode">renderable</a>, and
0104:         * <a href="#CollectionMode">collection</a> modes and requires a single
0105:         * source. The operation is "immediate" for all modes as specified by
0106:         * <code>OperationDescriptor.isImmediate()</code> so that
0107:         * {@link #isImmediate()} returns <code>true</code>. The operation will
0108:         * therefore be rendered when created via either <code>JAI.create[NS]()</code>
0109:         * or <code>JAI.createCollection[NS]()</code>.
0110:         * A {@link java.awt.RenderingHints} object supplied when the
0111:         * operation is created will have no effect except with respect to the
0112:         * mapping of <code>JAI.KEY_INTERPOLATION</code> and then only in renderable
0113:         * mode.</p>
0114:         *
0115:         * <p>Image properties are used to pass metadata and other information to the
0116:         * writer plug-in and to make available metadata as actually written to the
0117:         * output destination. Property handling is mode-specific.</p>
0118:         *
0119:         * <p><table border=1>
0120:         * <caption><b>Resource List</b></caption>
0121:         * <tr><th>Name</th>        <th>Value</th></tr>
0122:         * <tr><td>GlobalName</td>  <td>ImageWrite</td></tr>
0123:         * <tr><td>LocalName</td>   <td>ImageWrite</td></tr>
0124:         * <tr><td>Vendor</td>      <td>com.sun.media.jai</td></tr>
0125:         * <tr><td>Description</td> <td>Writes an image using the Java Image I/O Framework.</td></tr>
0126:         * <tr><td>DocURL</td>      <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-imageio-1_0-rc-docs/com/sun/media/jai/operator/ImageWriteDescriptor.html</td></tr>
0127:         * <tr><td>Version</td>     <td>1.0</td></tr>
0128:         * <tr><td>arg0Desc</td>    <td>The output destination.</td></tr>
0129:         * <tr><td>arg1Desc</td>    <td>The format name of the output.</td></tr>
0130:         * <tr><td>arg2Desc</td>    <td>Whether to use image metadata properties as fallbacks.</td></tr>
0131:         * <tr><td>arg3Desc</td>    <td>Whether to transcode metadata before writing.</td></tr>
0132:         * <tr><td>arg4Desc</td>    <td>Whether to verify the validity of the output destination.</td></tr>
0133:         * <tr><td>arg5Desc</td>    <td>Whether to allow pixel replacement in the output image.</td></tr>
0134:         * <tr><td>arg6Desc</td>    <td>The tile size of the output image.</td></tr>
0135:         * <tr><td>arg7Desc</td>    <td>Stream metadata to write to the output.</td></tr>
0136:         * <tr><td>arg8Desc</td>    <td>Image metadata to write to the output.</td></tr>
0137:         * <tr><td>arg9Desc</td>    <td>Thumbnails to write to the output.</td></tr>
0138:         * <tr><td>arg10Desc</td>    <td>EventListeners to be registered with the ImageWriter.</td></tr>
0139:         * <tr><td>arg11Desc</td>    <td>The Locale for the ImageWriter to use.</td></tr>
0140:         * <tr><td>arg12Desc</td>    <td>Java Image I/O write parameter instance.</td></tr>
0141:         * <tr><td>arg13Desc</td>    <td>Java Image I/O writer instance.</td></tr>
0142:         * </table></p>
0143:         *
0144:         * <h2><a name="RenderedMode"</a>Rendered Mode</h2>
0145:         *
0146:         * In rendered mode the "ImageWrite" operation writes a
0147:         * {@link java.awt.image.RenderedImage} to the specified output destination.
0148:         *
0149:         * <h3><a name="RenderedModeParameters"</a>Rendered Mode Parameters</h3>
0150:         *
0151:         * The parameter list of the "ImageWrite" operation in rendered mode is
0152:         * as in the following table.
0153:         *
0154:         * <p><table border=1>
0155:         * <caption><b>Rendered Mode Parameter List</b></caption>
0156:         * <tr><th>Name</th>           <th>Class Type</th>
0157:         *                             <th>Default Value</th></tr>
0158:         * <tr><td><a href="#ParamOutput">
0159:         *     Output</a></td>          <td>java.lang.Object.class</td>
0160:         *                             <td>NO_PARAMETER_DEFAULT</td>
0161:         * <tr><td><a href="#ParamFormat">
0162:         *     Format</a></td>    <td>java.lang.String</td>
0163:         *                             <td>null</td>
0164:         * <tr><td><a href="#ParamUseProperties">
0165:         *     UseProperties</a></td>   <td>java.lang.Boolean</td>
0166:         *                             <td>TRUE</td>
0167:         * <tr><td><a href="#ParamTranscode">
0168:         *     Transcode</a></td> <td>java.lang.Boolean</td>
0169:         *                             <td>TRUE</td>
0170:         * <tr><td><a href="#ParamVerifyOutput">
0171:         *     VerifyOutput</a></td>    <td>java.lang.Boolean</td>
0172:         *                             <td>TRUE</td>
0173:         * <tr><td><a href="#ParamAllowPixelReplacement">
0174:         *     AllowPixelReplacement</a></td> <td>java.lang.Boolean</td>
0175:         *                             <td>FALSE</td>
0176:         * <tr><td><a href="#ParamTileSize">
0177:         *     TileSize</a></td>    <td>java.awt.Dimension</td>
0178:         *                             <td>null</td>
0179:         * <tr><td><a href="#ParamStreamMetadata">
0180:         *     StreamMetadata</a></td>    <td>javax.imageio.metadata.IIOMetadata</td>
0181:         *                             <td>null</td>
0182:         * <tr><td><a href="#ParamImageMetadata">
0183:         *     ImageMetadata</a></td>    <td>javax.imageio.metadata.IIOMetadata</td>
0184:         *                             <td>null</td>
0185:         * <tr><td><a href="#ParamThumbnails">
0186:         *     Thumbnails</a></td>    <td>java.awt.BufferedImage[]</td>
0187:         *                             <td>null</td>
0188:         * <tr><td><a href="#ParamListeners">
0189:         *     Listeners</a></td>      <td>java.util.EventListener[]</td>
0190:         *                             <td>null</td>
0191:         * <tr><td><a href="#ParamLocale">
0192:         *     Locale</a></td>         <td>java.util.Locale</td>
0193:         *                             <td>null</td>
0194:         * <tr><td><a href="#ParamWriteParam">
0195:         *     WriteParam</a></td>      <td>javax.imageio.ImageWriteParam</td>
0196:         *                             <td>null</td>
0197:         * <tr><td><a href="#ParamWriter">
0198:         *     Writer</a></td>         <td>javax.imageio.ImageWriter</td>
0199:         *                             <td>null</td>
0200:         * </table></p>
0201:         *
0202:         * <p>The rendered mode parameters are handled as follows:
0203:         *
0204:         * <ul>
0205:         * <p><li><a name="ParamOutput"</a>
0206:         * If Output is a String it is assumed to represent a file path.
0207:         * </li></p>
0208:         * <p><li><a name="ParamFormat"</a>
0209:         * Format will be used to obtain an ImageWriter if one is not supplied. If
0210:         * this parameter is null and Writer is non-null and has an originating
0211:         * ImageWriterSpi, then the first format name listed by that provider will be
0212:         * used. If Writer is null and Output is a File or a String, an attempt will
0213:         * be made to derive the format name from the suffix of the file path. If
0214:         * this fails, then the format will default to "PNG" as this is the most
0215:         * versatile writer plug-in in the Java 2 core.
0216:         * </li></p>
0217:         * <p><li><a name="ParamUseProperties"</a>
0218:         * If UseProperties is TRUE, then if stream or image metadata or thumbnails
0219:         * are not provided as parameters, an attempt will be made to derive them
0220:         * from the source image using the respective image properties previously
0221:         * described for the "ImageRead" operation.
0222:         * </li></p>
0223:         * <p><li><a name="ParamTranscode"</a>
0224:         * If Transcode is TRUE, then any stream or metadata derived either from
0225:         * operation parameters or source image properties will be converted using
0226:         * the ImageWriter's implementation of ImageTranscoder.
0227:         * </li></p>
0228:         * <p><li><a name="ParamVerifyOutput"</a>
0229:         * If VerifyOutput is TRUE, then if the Output is a File or a String it will
0230:         * be verified that a file at the specified location may either be overwritten
0231:         * or created. If Output is a Socket, it will be verified that it is bound,
0232:         * connected, not closed, and its write-half is not shut down. If any of
0233:         * these checks fails, an exception will be thrown when the operation is
0234:         * created. This parameter is ignored for other output types.
0235:         * </li></p>
0236:         * <p><li><a name="ParamAllowPixelReplacement"</a>
0237:         * If AllowPixelReplacement is TRUE, and the ImageWriter supports pixel
0238:         * replacement, then a construct will be enabled to allow "live" updating
0239:         * of the output in response to RenderingChangeEvents or "InvalidRegion"
0240:         * events.
0241:         * </li></p>
0242:         * <p><li><a name="ParamTileSize"</a>
0243:         * TileSize specifies the desired tile size; it is used as defined by the
0244:         * <a href="#RenderedModeTiling">tiling algorithm</a>. This parameter is
0245:         * ignored if the ImageWriter does not support tiling.
0246:         * Regardless of the capabilities of the writer, an exception will be thrown
0247:         * when the operation is created if this parameter is non-null and either
0248:         * its width or height is not positive.
0249:         * </li></p>
0250:         * <p><li><a name="ParamStreamMetadata"</a>
0251:         * If StreamMetadata is non-null, then the parameter will take priority over
0252:         * the corresponding image property as the source of stream metadata to
0253:         * be written.
0254:         * </li></p>
0255:         * <p><li><a name="ParamImageMetadata"</a>
0256:         * If ImageMetadata is non-null, then the parameter will take priority over
0257:         * the corresponding image property as the source of image metadata to
0258:         * be written.
0259:         * </li></p>
0260:         * <p><li><a name="ParamThumbnails"</a>
0261:         * If Thumbnails is non-null, then the parameter will take priority over
0262:         * the corresponding image property as the source of image thumbnails to
0263:         * be written.
0264:         * </li></p>
0265:         * <p><li><a name="ParamListeners"</a>
0266:         * Listeners will be used to set any progress or warning listeners of the
0267:         * ImageWriter. Each element in the java.util.EventListener array will be
0268:         * added for all types of listener it implements. For example if a listener
0269:         * object implements all of the javax.imageio.event.IIOWrite*Listeners
0270:         * interfaces then it will be added as a listener of each of the three types.
0271:         * Any elements in the array which do not implement any of the
0272:         * IIOWrite*Listeners will be ignored.
0273:         * </li></p>
0274:         * <p><li><a name="ParamLocale"</a>
0275:         * Locale will be used to set the Locale of the ImageWriter. This parameter
0276:         * overrides the equivalent setting of the Writer parameter if the latter is
0277:         * also supplied.
0278:         * </li></p>
0279:         * <p><li><a name="ParamWriteParam"</a>
0280:         * If WriteParam is null, an ImageWriteParam will be derived internally using
0281:         * ImageWriter.getDefaultWriteParam().
0282:         * </li></p>
0283:         * <p><li><a name="ParamWriter"</a>
0284:         * If Writer is null, an attempt will be made to find an ImageWriter capable
0285:         * of writing the image. If this attempt to obtain an ImageWriter fails, an
0286:         * exception will be thrown.
0287:         * </li></p>
0288:         * </ul>
0289:         * </p>
0290:         *
0291:         * <h4><a name="SyncPolicy"</a>Parameters and Synchronization Policy</h4>
0292:         *
0293:         * Similarly to the case of any ImageReadParam or ImageReader supplied to the
0294:         * "ImageRead" operation, any ImageWriteParam or ImageWriter supplied to the
0295:         * "ImageWrite" operation is subject to modification within the operation
0296:         * classes. A policy similar to the
0297:         * <a href="./ImageReadDescriptor.html#SyncPolicy">"ImageRead"
0298:         * synchronization policy</a> therefore applies as well for "ImageWrite".
0299:         * 
0300:         * <p>In the Sun Microsystems implementation of this operation these potential
0301:         * conflicts have been mitigated to a certain extent:
0302:         * 
0303:         * <ul>
0304:         * <p><li>
0305:         * If the param is cloneable then it is cloned and the clone used internally.
0306:         *  Otherwise if the param is an instance of ImageWriteParam itself rather than
0307:         *   of a subclass thereof, i.e., getClass().getName() invoked on the param
0308:         *   returns "javax.imageio.ImageWriteParam", then a new ImageWriteParam is
0309:         *   constructed and the settings of the original param copied to it. If the
0310:         *   param is not cloneable and is an instance of a proper subclass of
0311:         *   ImageWriteParam then it is used directly.</li></p>
0312:         * 
0313:         * <p><li>
0314:         * The only ImageWriter methods invoked after rendering are
0315:         *   prepareReplacePixels(int,Rectangle), replacePixels(Raster,ImageWriteParam),
0316:         *   and endReplacePixels() and these are invoked within a method synchronized
0317:         *   on the ImageWriter object.</li></p>
0318:         * </ul>
0319:         * </p>
0320:         *
0321:         * <h3><a name="RenderedModeTiling"</a>Tiling</h3>
0322:         *
0323:         * The following algorithm is used to determine the tile size of the
0324:         * image written to the output destination:
0325:         * 
0326:         * <pre>
0327:         * if ImageWriter cannot write tiles
0328:         *    output is untiled
0329:         * else
0330:         *    if TileSize parameter is non-null
0331:         *       set tile size to TileSize
0332:         *    else
0333:         *       if WriteParam is null
0334:         *          set tile size to source tile size
0335:         *       else
0336:         *          if tilingMode is ImageWriteParam.MODE_EXPLICIT
0337:         *             if tile dimension is set in WriteParam
0338:         *                set tile size to tile dimension from WriteParam
0339:         *             else
0340:         *                if preferred tile dimension is set in WriteParam
0341:         * 		  set tile size to average of first two preferred dimensions
0342:         *                else
0343:         *                   set tile size to source tile size
0344:         *          else // tilingMode is not ImageWriteParam.MODE_EXPLICIT
0345:         *             the plug-in decides the tile size
0346:         * </pre>
0347:         * 
0348:         * There is no mechanism to set the tile grid offsets of the output.
0349:         *
0350:         * <h3><a name="RenderedModePixelReplacement"</a>Pixel Replacement</h3>
0351:         *
0352:         * If AllowPixelReplacement is TRUE, the ImageWriter can replace pixels, and
0353:         * the source is a PlanarImage, then the rendering of the operation
0354:         * will respond to RenderingChangeEvents and Shape-valued PropertyChangeEvents
0355:         * named "InvalidRegion". The rendering will be automatically registered as
0356:         * a sink of the rendering of the operation node's source. As the source
0357:         * rendering does not usually generate events, the calling code must also
0358:         * explicitly register the "ImageWrite" rendering as a sink of the source
0359:         * node. By whatever means the event is generated, when the rendering
0360:         * receives such an event, it will determine the indices of all tiles which
0361:         * overlap the invalid region and will replace the pixels of all these tiles
0362:         * in the output.
0363:         * 
0364:         * <p>Note that this behavior differs from what would happen if the RenderedOp
0365:         * created by the operation received a RenderingChangeEvent: in this case a
0366:         * new rendering of the node would be created using the ParameterBlock and
0367:         * RenderingHints currently in effect. This would cause the entire image to be
0368:         * rewritten at the current position of the output. This will also happen
0369:         * when AllowPixelReplacement is FALSE. In effect in both of these cases the
0370:         * behavior in response to a RenderingChangeEvent is unspecified and the result
0371:         * will likely be unexpected.</p>
0372:         * 
0373:         * <p>To avoid any inadvertent overwriting of the destination as a result of
0374:         * events received by the RenderedOp, the following usage is recommended when
0375:         * the objective is automatic pixel replacement:
0376:         * 
0377:         * <pre>
0378:         *        // Sources, parameters, and hints.
0379:         *        ParameterBlock args;
0380:         *        RenderingHints hints;
0381:         * 
0382:         *        // Create the OperationNode.
0383:         *        RenderedOp imageWriteNode = JAI.create("ImageWrite", args, hints);
0384:         * 
0385:         *        // Get the rendering which already exists due to "immediate" status.
0386:         *        RenderedImage imageWriteRendering = imageWriteNode.getRendering();
0387:         * 
0388:         *        // Unhook the OperationNode as a sink of its source OperationNode.
0389:         *        imageWriteNode.getSourceImage(0).removeSink(imageWriteNode);
0390:         *
0391:         *        // Add the rendering as a sink of the source OperationNode.
0392:         *        imageWriteNode.getSourceImage(0).addSink(imageWriteRendering);
0393:         * 
0394:         *        // Free the OperationNode for garbage collection.
0395:         *        imageWriteNode = null;
0396:         * </pre>
0397:         * 
0398:         * At this point a reference to imageWriteRendering must be held as long as the
0399:         * data of the source of the operation may change. Then provided the events are
0400:         * correctly propagated to imageWriteRendering, the data in the output file
0401:         * will be automatically updated to match the source data.</p>
0402:         * 
0403:         * <p>If pixel replacement is not the objective and inadvertent overwriting is
0404:         * to be avoided then the safest approach would be the following:
0405:         * 
0406:         * <pre>
0407:         *        // Create the OperationNode.
0408:         *        RenderedOp imageWriteNode = JAI.create("ImageWrite", args, hints);
0409:         * 
0410:         *        // Unhook the OperationNode as a sink of its source
0411:         *        imageWriteNode.getSourceImage(0).removeSink(imageWriteNode);
0412:         * </pre>
0413:         * 
0414:         * The image is written by the first statement and no reference to the
0415:         * rendering need be retained as before.
0416:         *
0417:         * <h3><a name="RenderedModeProperties"</a>Image Properties in Rendered Mode</h3>
0418:         *
0419:         * Image properties are used for metadata, thumbnails, and writer-related
0420:         * information. The following properties may be set on the RenderedOp created
0421:         * for the "ImageWrite" operation in rendered mode:
0422:         * 
0423:         * <p><table border=1>
0424:         * <caption><b>Rendered Mode Image Properties</b></caption>
0425:         * <tr>
0426:         * <th>Property Name</th>
0427:         * <th>Type</th>
0428:         * <th>Comment</th>
0429:         * </tr>
0430:         * <tr>
0431:         * <td>JAI.ImageWriteParam</td>
0432:         * <td>ImageWriteParam</td>
0433:         * <td>Set to ImageWriteParam actually used which may differ from the one passed in.</td>
0434:         * </tr>
0435:         * <tr>
0436:         * <td>JAI.ImageWriter</td>
0437:         * <td>ImageWriter</td>
0438:         * <td>Set to ImageWriter actually used.</td>
0439:         * </tr>
0440:         * <tr>
0441:         * <td>JAI.ImageMetadata</td>
0442:         * <td>IIOMetadata</td>
0443:         * <td>Set if and only if image metadata are available; may be transcoded.</td>
0444:         * </tr>
0445:         * <tr>
0446:         * <td>JAI.StreamMetadata</td>
0447:         * <td>IIOMetadata</td>
0448:         * <td>Set if and only if stream metadata are available; may be transcoded.</td>
0449:         * </tr>
0450:         * <tr>
0451:         * <td>JAI.Thumbnails</td>
0452:         * <td>BufferedImage[]</td>
0453:         * <td>Set if and only thumbnails are provided and the writer supportes writing them.</td>
0454:         * </tr>
0455:         * </table></p>
0456:         * 
0457:         * <p>If a given property is not set, this implies of course that the names of
0458:         * absent properties will not appear in the array returned by getPropertyNames()
0459:         * and getProperty() invoked to obtain absent properties will return
0460:         * java.awt.Image.UndefinedProperty as usual.</p>
0461:         * 
0462:         * <p>The ImageWriter and ImageWriteParam may be used for subsequent invocations
0463:         * of the operation or for informational purposes. Care should be taken in using
0464:         * these property values with respect to the synchronization issues previously
0465:         * discussed.</p>
0466:         * 
0467:         * <p>Metadata properties will be set to those actually written to the output. They
0468:         * may be derived either from input parameters or source properties depending on
0469:         * the values of the StreamMetadata, ImageMetadata, and UseProperties parameters.
0470:         * They will be transcoded data if Transcode is TRUE and the ImageWriter supports
0471:         * transcoding.</p>
0472:         * 
0473:         * <p>All properties will be set when the node is rendered.</p>
0474:         *
0475:         * <h2><a name="RenderableMode"</a>Renderable Mode</h2>
0476:         *
0477:         * In renderable mode the "ImageWrite" operation requires a
0478:         * {@link java.awt.image.renderable.RenderableImage} source and writes a
0479:         * {@link java.awt.image.RenderedImage} to the specified output destination.
0480:         * As the "immediate" designation specified by {@link #isImmediate()}
0481:         * has no effect in renderable mode, no image will be written without further
0482:         * action by the calling code. To write an image, createRendering(),
0483:         * createScaledRendering(), or createDefaultRendering()
0484:         * must be invoked. Each of these will create a RenderedImage by forwarding the
0485:         * createRendering() or equivalent call to the source image. The resulting
0486:         * RenderedImage will be written to the output according to the
0487:         * <a href="#RenderedMode">rendered mode</a> operation of "ImageWrite".
0488:         * If a mapping of <code>JAI.KEY_INTERPOLATION</code> is supplied via a
0489:         * <code>RenderingHints</code> passed to the operation, then the interpolation
0490:         * type it specifies will be used to create the rendering if interpolation is
0491:         * required.
0492:         *
0493:         * <h3><a name="RenderableModeParameters"</a>Renderable Mode Parameters</h3>
0494:         *
0495:         * The parameter list of the "ImageRead" operation in renderable mode is
0496:         * identical to the <a href="#RenderedModeParameters">rendered mode
0497:         * parameter list</a>.
0498:         *
0499:         * <h3>Pixel Replacement in Renderable Mode</h3>
0500:         *
0501:         * Pixel replacement pertains only to RenderedImages generated by rendering the
0502:         * RenderableOp. It may occur if the same conditions apply as described for
0503:         * pixel replacement in rendered mode. Due to the unspecified nature of the
0504:         * underlying rendered sources of any rendering, this is not a recommended
0505:         * procedure.
0506:         *
0507:         * <h3>Image Properties in Renderable Mode</h3>
0508:         *
0509:         * The RenderableOp node itself does not have any ImageWrite-related
0510:         * properties. Any RenderedImages created by rendering the RenderableOp
0511:         * (thereby writing an image to the output as described), may have
0512:         * <a href="#RenderedModeProperties">rendered mode properties</a> set.
0513:         *
0514:         * <h2><a name="CollectionMode"</a>Collection Mode</h2>
0515:         *
0516:         * In collection mode the "ImageWrite" operation requires a
0517:         * {@link java.util.Collection} source and writes its contents to the
0518:         * specified output destination.
0519:         *
0520:         * <p>The Collection is treated as a sequence of images which will be
0521:         * extracted from the Collection in the order returned by a new Iterator.
0522:         * Elements in the Collection which are not RenderedImages will be ignored.
0523:         * The derived sequence of images will then be written to the output.</p>
0524:         * 
0525:         * <p>If there is only one RenderedImage in the source Collection, this image
0526:         * will be written as done in rendered mode operation. If there is more than
0527:         * one RenderedImage, the sequence of RenderedImages will be written as an
0528:         * image sequence. In the latter case the ImageWriter must be able to write
0529:         * sequences.</p>
0530:         *
0531:         * <h3><a name="CollectionModeParameters"</a>Collection Mode Parameters</h3>
0532:         *
0533:         * Identical parameter list to rendered mode except:
0534:         * 
0535:         * <p><table border=1>
0536:         * <caption><b>Collection Mode Parameter Differences</b></caption>
0537:         * <tr><th>Name</th>           <th>Class Type</th>
0538:         *                             <th>Default Value</th></tr>
0539:         * <tr><td>ImageMetadata</td>  <td>javax.imageio.metadataIIOMetadata[]</td>
0540:         *                             <td>null</td>
0541:         * <tr><td>Thumbnails</td>     <td>java.awt.image.BufferedImage[][]</td>
0542:         *                             <td>null</td>
0543:         * </table></p>
0544:         * 
0545:         * <ul>
0546:         * <p><li>
0547:         * If the source is not a CollectionOp then the number of RenderedImages in
0548:         * the source is counted. If it is not at least one then an exception is
0549:         * thrown when the operation is created. If it is greater than one, then
0550:         * the ImageWriter is checked to determine whether it can write sequences.
0551:         * If it cannot then an exception is thrown when the operation is created.
0552:         * </li></p>
0553:         * <p><li>
0554:         * The first index of the thumbnails array corresponds to the ordinal position
0555:         * of the image in the collection and the second index to the thumbnails of
0556:         * that image.
0557:         * </li></p>
0558:         * </ul>
0559:         * 
0560:         * <p>
0561:         * The change to the ImageMetadata and Thumbnails parameters is that there can
0562:         * now be a distinct image metadata object and thumbnail array for each image
0563:         * in the Collection. The components of these respective arrays will be indexed
0564:         * using the sequence of RenderedImages extracted from the source Collection by
0565:         * the Iterator. It is the responsibility of the caller to ensure that this
0566:         * sequencing is correct. In this context it is advisable to use a source
0567:         * Collection which maintains the order of its elements such as a List.
0568:         * </p>
0569:         *
0570:         * <h3>Pixel Replacement in Collection Mode</h3>
0571:         *
0572:         * If the value of the AllowPixelReplacement parameter is TRUE, then the
0573:         * rendered Collection will contain RenderedImages which are registered as
0574:         * listeners of their respective sources. Each image in the rendered Collection
0575:         * will however be a rendering as opposed to a RenderedOp. This obviates the
0576:         * need to unhook such a RenderedOp from its source as suggested. Two actions
0577:         * on the part of the application are however necessary in this case:  1) the
0578:         * sequence must be manually ended, and 2) the Collection node must be removed
0579:         * as a sink of its source Collection. The first action is necessary as
0580:         * pixels may be replaced at various times in various images in the sequence
0581:         * and it is not possible to terminate the sequence at rendering time, and there
0582:         * is no reliable mechanism to detect programmatically when this may later be
0583:         * effected. The second action is necessary because a CollectionChangeEvent
0584:         * received by the Collection node would cause the node to be re-rendered, i.e.,
0585:         * the collection data to be rewritten using the current state of all parameters.
0586:         * This will in fact also happen when AllowPixelReplacement is FALSE. In effect
0587:         * in both of these cases the behavior in response to a CollectionChangeEvent
0588:         * is unspecified and the result will likely be unexpected.
0589:         * 
0590:         * <p>
0591:         * To ensure proper termination of the image sequence and avoid any inadvertent
0592:         * overwriting of the destination as a result of events received by the
0593:         * CollectionOp, the following usage is recommended when the objective is
0594:         * automatic pixel replacement:
0595:         * 
0596:         * <pre>
0597:         *        // Sources, parameters, and hints.
0598:         *        ParameterBlock args;
0599:         *        RenderingHints hints;
0600:         * 
0601:         *        // Create the Collection.
0602:         *        CollectionImage imageWriteCollection =
0603:         *            (CollectionImage)JAI.createCollection("ImageWrite", args, hints);
0604:         * 
0605:         *        // Unhook the Collection node from the source to avoid
0606:         *        // re-renderings caused by CollectionChangeEvents.
0607:         *        if(args.getSource(0) instanceof CollectionImage) {
0608:         *            CollectionImage sourceCollection =
0609:         * 	       (CollectionImage)args.getSource(0);
0610:         *            sourceCollection.removeSink(imageWriteCollection);
0611:         *        }
0612:         * 
0613:         *        // !!! Pixel replacement activity happens here ... !!!
0614:         * 
0615:         *        // Get the ImageWriter.
0616:         *        ImageWriter writer =
0617:         *            (ImageWriter)imageWriteCollection.getProperty("JAI.ImageWriter");
0618:         * 
0619:         *        // End the sequence if necessary.
0620:         *        if(writer.canWriteSequence()) {
0621:         *            writer.endWriteSequence();
0622:         *        }
0623:         * </pre>
0624:         * </p>
0625:         * 
0626:         * <p>
0627:         * Using the foregoing construct, all pixels in all images written to the output
0628:         * sequence will remain current with the in-memory data of their respective
0629:         * source provided all events are propagated as expected. Note that it is not
0630:         * necessary to end the sequence manually if pixel replacement is not allowed or
0631:         * is not supported. Also the sequence must be manually ended if and only if the
0632:         * writer is capable of writing sequences. This permits pixel replacement to
0633:         * work in the case where the source collection contains only a single image
0634:         * and the writer supports pixel replacement but cannot write sequences.
0635:         * </p>
0636:         * 
0637:         * <p>
0638:         * If pixel replacement is not the objective, i.e., AllowPixelReplacement is
0639:         * FALSE, and inadvertent overwriting is to be avoided then the safest approach
0640:         * would be the following:
0641:         * 
0642:         * <pre>
0643:         *        // Create the Collection.
0644:         *        Collection imageWriteCollection =
0645:         *            JAI.create("ImageWrite", args, hints);
0646:         * 
0647:         *        // Unhook the Collection node from the source to avoid
0648:         *        // re-renderings caused by CollectionChangeEvents.
0649:         *        if(args.getSource(0) instanceof CollectionImage) {
0650:         *            CollectionImage sourceCollection =
0651:         * 	       (CollectionImage)args.getSource(0);
0652:         *            sourceCollection.removeSink(imageWriteCollection);
0653:         *        }
0654:         * </pre>
0655:         * 
0656:         * The image is written by the first statement and no reference to the
0657:         * rendering need be retained.</p>
0658:         *
0659:         * <h3>Image Properties in Collection Mode</h3>
0660:         *
0661:         * Contingent on parameter settings and the presence of the appropriate
0662:         * metadata, the rendered Collection may have the "JAI.StreamMetadata",
0663:         * "JAI.ImageReadParam", and "JAI.ImageReader" properties set. Each
0664:         * RenderedImage in the Collection may contain
0665:         * <a href="#RenderedModeProperties">rendered mode properties</a>
0666:         * contingent on parameter settings and data availability. Metadata
0667:         * properties may be transcoded.
0668:         *
0669:         * @see javax.media.jai.OperationDescriptor
0670:         * @see javax.imageio.ImageWriter
0671:         * @see javax.imageio.ImageWriteParam
0672:         * @see javax.imageio.metadata.IIOMetadata
0673:         * @see javax.imageio.stream.ImageOutputStream
0674:         */
0675:        public class ImageWriteDescriptor extends OperationDescriptorImpl {
0676:
0677:            // Property name constants have package access for image factory use.
0678:
0679:            /** ImageWriteParam property name "JAI.ImageWriteParam". */
0680:            public static final String PROPERTY_NAME_IMAGE_WRITE_PARAM = "JAI.ImageWriteParam";
0681:
0682:            /** ImageWriter property name "JAI.ImageWriter". */
0683:            public static final String PROPERTY_NAME_IMAGE_WRITER = "JAI.ImageWriter";
0684:
0685:            /**
0686:             * Image metadata property name. Set to same value as
0687:             * {@link ImageReadDescriptor#PROPERTY_NAME_METADATA_IMAGE}.
0688:             */
0689:            public static final String PROPERTY_NAME_METADATA_IMAGE = ImageReadDescriptor.PROPERTY_NAME_METADATA_IMAGE;
0690:
0691:            /**
0692:             * Stream metadata property name. Set to same value as
0693:             * {@link ImageReadDescriptor#PROPERTY_NAME_METADATA_STREAM}.
0694:             */
0695:            public static final String PROPERTY_NAME_METADATA_STREAM = ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM;
0696:
0697:            /**
0698:             * Thumbnail property name. Set to same value as
0699:             * {@link ImageReadDescriptor#PROPERTY_NAME_THUMBNAILS}.
0700:             */
0701:            public static final String PROPERTY_NAME_THUMBNAILS = ImageReadDescriptor.PROPERTY_NAME_THUMBNAILS;
0702:
0703:            /**
0704:             * Test method.
0705:             *
0706:             * @param args {inputFile, outputFile [, mode]}
0707:             * @throws Throwable any error.
0708:             */
0709:            /* XXX
0710:            public static void main(String[] args) throws Throwable {
0711:                String inputFile = args[0];
0712:                String outputFile = args[1];
0713:                String modeName = args.length > 2 ?
0714:                    args[2] : RenderedRegistryMode.MODE_NAME;
0715:                String formatName = args.length > 3 ?
0716:                    args[3] : null;
0717:
0718:                ParameterBlock pb = new ParameterBlock();
0719:                pb.set(new java.io.File(outputFile), 0);
0720:                if(formatName != null) {
0721:                    pb.set(formatName, 1);
0722:                }
0723:
0724:                java.awt.image.RenderedImage[] images = null;
0725:                if(modeName.equalsIgnoreCase(RenderedRegistryMode.MODE_NAME)) {
0726:                    pb.addSource(ImageIO.read(new java.io.File(inputFile)));
0727:                    images = new java.awt.image.RenderedImage[1];
0728:                    pb.set(new Dimension(128, 128), 6);
0729:                    images[0] = JAI.create("ImageWrite", pb, null);
0730:                    PrintProps.print((javax.media.jai.PropertySource)images[0]);
0731:                } else if(modeName.equalsIgnoreCase(RenderableRegistryMode.MODE_NAME)) {
0732:                    ParameterBlock renderablePB = new ParameterBlock();
0733:                    renderablePB.addSource(ImageIO.read(new java.io.File(inputFile)));
0734:                    pb.addSource(javax.media.jai.JAI.createRenderable("renderable", renderablePB));
0735:                    java.awt.image.renderable.RenderableImage ri =
0736:                        JAI.createRenderable("ImageWrite", pb, null);
0737:                    PrintProps.print((javax.media.jai.PropertySource)ri);
0738:                    images = new java.awt.image.RenderedImage[1];
0739:                    //java.awt.image.renderable.RenderContext rc =
0740:                    //    new java.awt.image.renderable.RenderContext(
0741:                    //        new java.awt.geom.AffineTransform(42, 0, 0, 42, 0, 0));
0742:                    //images[0] = ri.createRendering(rc);
0743:                    images[0] = ri.createDefaultRendering();
0744:                    PrintProps.print((javax.media.jai.PropertySource)images[0]);
0745:                } else if(modeName.equalsIgnoreCase(CollectionRegistryMode.MODE_NAME)) {
0746:                    java.util.ArrayList sourceCollection = new java.util.ArrayList();
0747:                    Object input =
0748:                        ImageIO.createImageInputStream(new java.io.File(inputFile));
0749:                    javax.imageio.ImageReader reader =
0750:                        (javax.imageio.ImageReader)ImageIO.getImageReaders(input).next();
0751:                    reader.setInput(input);
0752:                    int imageIndex = 0;
0753:                    do {
0754:                        try {
0755:                            RenderedImage nextImage = reader.read(imageIndex);
0756:                            sourceCollection.add(nextImage);
0757:                        } catch(IndexOutOfBoundsException e) {
0758:                            break;
0759:                        }
0760:                        imageIndex++;
0761:                    } while(true);
0762:                    pb.addSource(sourceCollection);
0763:                    java.util.Collection imageCollection =
0764:                        JAI.createCollection("ImageWrite", pb, null);
0765:                    PrintProps.print((javax.media.jai.PropertySource)imageCollection);
0766:                    images = new java.awt.image.RenderedImage[imageCollection.size()];
0767:                    imageCollection.toArray(images);
0768:                } else {
0769:                    throw new UnsupportedOperationException(modeName+" mode not supported");
0770:                }
0771:
0772:                final java.awt.Frame frame = new java.awt.Frame();
0773:                frame.addWindowListener(new java.awt.event.WindowAdapter() {
0774:                        public void windowClosing(java.awt.event.WindowEvent e) {
0775:                            frame.setEnabled(false);
0776:                            frame.dispose();
0777:                        }
0778:                    });
0779:
0780:                int gridSide = (int)(Math.sqrt(images.length) + 0.5);
0781:                frame.setLayout(new java.awt.GridLayout(gridSide, gridSide));
0782:                java.awt.Dimension screenSize =
0783:                    java.awt.Toolkit.getDefaultToolkit().getScreenSize();
0784:                int width =
0785:                    Math.min(screenSize.width/gridSide, images[0].getWidth());
0786:                int height =
0787:                    Math.min(screenSize.height/gridSide, images[0].getHeight());
0788:                for(int i = 0; i < images.length; i++) {
0789:                    javax.media.jai.widget.ScrollingImagePanel panel =
0790:                        new javax.media.jai.widget.ScrollingImagePanel(images[i],
0791:                                                                       width, //image.getWidth(),
0792:                                                                       height);//image.getHeight());
0793:                    frame.add(panel);
0794:                }
0795:                frame.pack();
0796:                frame.show();
0797:            }
0798:             */
0799:
0800:            /**
0801:             * The name of the operation.
0802:             */
0803:            private static final String OPERATION_NAME = "ImageWrite";
0804:
0805:            /**
0806:             * The resource strings that provide the general documentation and
0807:             * specify the parameter list for the "ImageWrite" operation.
0808:             */
0809:            private static final String[][] resources = {
0810:                    { "GlobalName", "ImageWrite" },
0811:                    { "LocalName", "ImageWrite" },
0812:                    { "Vendor", "com.sun.media.jai" },
0813:                    { "Description", I18N.getString("ImageWriteDescriptor0") },
0814:                    {
0815:                            "DocURL",
0816:                            "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ImageWriteDescriptor.html" },
0817:                    { "Version", I18N.getString("DescriptorVersion") },
0818:                    { "arg0Desc", I18N.getString("ImageWriteDescriptor1") },
0819:                    { "arg1Desc", I18N.getString("ImageWriteDescriptor2") },
0820:                    { "arg2Desc", I18N.getString("ImageWriteDescriptor3") },
0821:                    { "arg3Desc", I18N.getString("ImageWriteDescriptor4") },
0822:                    { "arg4Desc", I18N.getString("ImageWriteDescriptor5") },
0823:                    { "arg5Desc", I18N.getString("ImageWriteDescriptor6") },
0824:                    { "arg6Desc", I18N.getString("ImageWriteDescriptor7") },
0825:                    { "arg7Desc", I18N.getString("ImageWriteDescriptor8") },
0826:                    { "arg8Desc", I18N.getString("ImageWriteDescriptor9") },
0827:                    { "arg9Desc", I18N.getString("ImageWriteDescriptor10") },
0828:                    { "arg10Desc", I18N.getString("ImageWriteDescriptor11") },
0829:                    { "arg11Desc", I18N.getString("ImageWriteDescriptor12") },
0830:                    { "arg12Desc", I18N.getString("ImageWriteDescriptor13") },
0831:                    { "arg13Desc", I18N.getString("ImageWriteDescriptor14") } };
0832:
0833:            /** The parameter names for the "ImageWrite" operation. */
0834:            private static final String[] paramNames = { "Output", "Format",
0835:                    "UseProperties", "Transcode", "VerifyOutput",
0836:                    "AllowPixelReplacement", "TileSize", "StreamMetadata",
0837:                    "ImageMetadata", "Thumbnails", "Listeners", "Locale",
0838:                    "WriteParam", "Writer" };
0839:
0840:            /** The parameter class types for rendered mode of "ImageWrite". */
0841:            private static final Class[] renderedParamClasses = {
0842:                    java.lang.Object.class, // Output
0843:                    java.lang.String.class, // Format
0844:                    java.lang.Boolean.class, // UseProperties
0845:                    java.lang.Boolean.class, // Transcode
0846:                    java.lang.Boolean.class, // VerifyOutput
0847:                    java.lang.Boolean.class, // AllowPixelReplacement
0848:                    java.awt.Dimension.class, // TileSize
0849:                    javax.imageio.metadata.IIOMetadata.class, // StreamMetadata
0850:                    javax.imageio.metadata.IIOMetadata.class, // ImageMetadata
0851:                    java.awt.image.BufferedImage[].class, // Thumbnails
0852:                    java.util.EventListener[].class, // Listeners
0853:                    java.util.Locale.class, // Locale
0854:                    javax.imageio.ImageWriteParam.class, // WriteParam
0855:                    javax.imageio.ImageWriter.class // Writer
0856:            };
0857:
0858:            /** The parameter default values for rendered mode of "ImageWrite". */
0859:            private static final Object[] renderedParamDefaults = {
0860:                    NO_PARAMETER_DEFAULT, // Output
0861:                    null, // Format
0862:                    Boolean.TRUE, // UseProperties
0863:                    Boolean.TRUE, // Transcode
0864:                    Boolean.TRUE, // VerifyOutput
0865:                    Boolean.FALSE, // AllowPixelReplacement
0866:                    null, // TileSize
0867:                    null, // StreamMetadata
0868:                    null, // ImageMetadata
0869:                    null, // Thumbnails
0870:                    null, // Listeners
0871:                    null, // Locale
0872:                    null, // WriteParam
0873:                    null // Writer
0874:            };
0875:
0876:            /** The parameter class types for renderable mode of "ImageWrite". */
0877:            private static final Class[] renderableParamClasses = renderedParamClasses;
0878:
0879:            /** The parameter default values for renderable mode of "ImageWrite". */
0880:            private static final Object[] renderableParamDefaults = renderedParamDefaults;
0881:
0882:            /** The parameter class types for collection mode of "ImageWrite". */
0883:            private static final Class[] collectionParamClasses = {
0884:                    java.lang.Object.class, // Output
0885:                    java.lang.String.class, // Format
0886:                    java.lang.Boolean.class, // UseProperties
0887:                    java.lang.Boolean.class, // Transcode
0888:                    java.lang.Boolean.class, // VerifyOutput
0889:                    java.lang.Boolean.class, // AllowPixelReplacement
0890:                    java.awt.Dimension.class, // TileSize
0891:                    javax.imageio.metadata.IIOMetadata.class, // StreamMetadata
0892:                    javax.imageio.metadata.IIOMetadata[].class, // ImageMetadata
0893:                    java.awt.image.BufferedImage[][].class, // Thumbnails
0894:                    java.util.EventListener[].class, // Listeners
0895:                    java.util.Locale.class, // Locale
0896:                    javax.imageio.ImageWriteParam.class, // WriteParam
0897:                    javax.imageio.ImageWriter.class // Writer
0898:            };
0899:
0900:            /** The parameter default values for collection mode of "ImageWrite". */
0901:            private static final Object[] collectionParamDefaults = renderedParamDefaults;
0902:
0903:            /** Constructor. */
0904:            public ImageWriteDescriptor() {
0905:                super (
0906:                        resources,
0907:                        new String[] { RenderedRegistryMode.MODE_NAME,
0908:                                RenderableRegistryMode.MODE_NAME,
0909:                                CollectionRegistryMode.MODE_NAME },
0910:                        null, // sourceNames
0911:                        new Class[][] { { RenderedImage.class },
0912:                                { RenderableImage.class }, { Collection.class } }, // sourceClasses
0913:                        paramNames,
0914:                        new Class[][] { renderedParamClasses,
0915:                                renderableParamClasses, collectionParamClasses },
0916:                        new Object[][] { renderedParamDefaults,
0917:                                renderableParamDefaults,
0918:                                collectionParamDefaults }, new Object[][] {
0919:                                null, null, null }); // validParamValues
0920:            }
0921:
0922:            /**
0923:             * Type-safe convenience method for creating a {@link RenderedOp}
0924:             * representing the "ImageWrite" operation in rendered mode. The
0925:             * method packs the source and parameters into a new
0926:             * <code>ParameterBlock</code> and invokes
0927:             * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
0928:             *
0929:             * @param source The image to be written.
0930:             * @param output The output destination.
0931:             * @param format The format name of the output.
0932:             * @param useProperties Whether to use image metadata properties as
0933:             * fallbacks.
0934:             * @param transcode Whether to transcode metadata before writing.
0935:             * @param verifyOutput Whether to verify the validity of the output
0936:             * destination.
0937:             * @param allowPixelReplacement Whether to allow pixel replacement
0938:             * in the output image.
0939:             * @param tileSize The tile size of the output image.
0940:             * @param streamMetadata Stream metadata to write to the output.
0941:             * @param imageMetadata Image metadata to write to the output.
0942:             * @param thumbnails Thumbnails to write to the output.
0943:             * @param listeners EventListeners to be registered with the ImageWriter.
0944:             * @param locale The Locale for the ImageWriter to use.
0945:             * @param writeParam Java Image I/O write parameter instance.
0946:             * @param writer Java Image I/O writer instance.
0947:             * @param hints Operation hints.
0948:             * @return a reference to the operation source.
0949:             */
0950:            public static RenderedOp create(RenderedImage source,
0951:                    ImageOutputStream output, String format,
0952:                    Boolean useProperties, Boolean transcode,
0953:                    Boolean verifyOutput, Boolean allowPixelReplacement,
0954:                    Dimension tileSize, IIOMetadata streamMetadata,
0955:                    IIOMetadata imageMetadata, BufferedImage[] thumbnails,
0956:                    EventListener[] listeners, Locale locale,
0957:                    ImageWriteParam writeParam, ImageWriter writer,
0958:                    RenderingHints hints) {
0959:
0960:                ParameterBlock args = new ParameterBlock();
0961:
0962:                args.addSource(source);
0963:
0964:                args.add(output);
0965:                args.add(format);
0966:                args.add(useProperties);
0967:                args.add(transcode);
0968:                args.add(verifyOutput);
0969:                args.add(allowPixelReplacement);
0970:                args.add(tileSize);
0971:                args.add(streamMetadata);
0972:                args.add(imageMetadata);
0973:                args.add(thumbnails);
0974:                args.add(listeners);
0975:                args.add(locale);
0976:                args.add(writeParam);
0977:                args.add(writer);
0978:
0979:                return JAI.create(OPERATION_NAME, args, hints);
0980:            }
0981:
0982:            /**
0983:             * Type-safe convenience method for creating a {@link Collection}
0984:             * representing the "ImageWrite" operation in collection mode. The
0985:             * method packs the source and parameters into a new
0986:             * <code>ParameterBlock</code> and invokes
0987:             * {@link JAI#createCollection(String,ParameterBlock,RenderingHints)}.
0988:             *
0989:             * @param source The collection to be written.
0990:             * @param output The output destination.
0991:             * @param format The format name of the output.
0992:             * @param useProperties Whether to use image metadata properties as
0993:             * fallbacks.
0994:             * @param transcode Whether to transcode metadata before writing.
0995:             * @param verifyOutput Whether to verify the validity of the output
0996:             * destination.
0997:             * @param allowPixelReplacement Whether to allow pixel replacement
0998:             * in the output image.
0999:             * @param tileSize The tile size of the output image.
1000:             * @param streamMetadata Stream metadata to write to the output.
1001:             * @param imageMetadata Image metadata to write to the output.
1002:             * @param thumbnails Thumbnails to write to the output.
1003:             * @param listeners EventListeners to be registered with the ImageWriter.
1004:             * @param locale The Locale for the ImageWriter to use.
1005:             * @param writeParam Java Image I/O write parameter instance.
1006:             * @param writer Java Image I/O writer instance.
1007:             * @param hints Operation hints.
1008:             * @return a reference to the operation source.
1009:             */
1010:            public static Collection createCollection(Collection source,
1011:                    ImageOutputStream output, String format,
1012:                    Boolean useProperties, Boolean transcode,
1013:                    Boolean verifyOutput, Boolean allowPixelReplacement,
1014:                    Dimension tileSize, IIOMetadata streamMetadata,
1015:                    IIOMetadata[] imageMetadata, BufferedImage[][] thumbnails,
1016:                    EventListener[] listeners, Locale locale,
1017:                    ImageWriteParam writeParam, ImageWriter writer,
1018:                    RenderingHints hints) {
1019:
1020:                ParameterBlock args = new ParameterBlock();
1021:
1022:                args.addSource(source);
1023:
1024:                args.add(output);
1025:                args.add(format);
1026:                args.add(useProperties);
1027:                args.add(transcode);
1028:                args.add(verifyOutput);
1029:                args.add(allowPixelReplacement);
1030:                args.add(tileSize);
1031:                args.add(streamMetadata);
1032:                args.add(imageMetadata);
1033:                args.add(thumbnails);
1034:                args.add(listeners);
1035:                args.add(locale);
1036:                args.add(writeParam);
1037:                args.add(writer);
1038:
1039:                return JAI.createCollection(OPERATION_NAME, args, hints);
1040:            }
1041:
1042:            /**
1043:             * Type-safe convenience method for creating a {@link RenderableOp}
1044:             * representing the "ImageWrite" operation in renderable mode. The
1045:             * method packs the source and parameters into a new
1046:             * <code>ParameterBlock</code> and invokes
1047:             * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
1048:             *
1049:             * @param source The renderable source to be written.
1050:             * @param output The output destination.
1051:             * @param format The format name of the output.
1052:             * @param useProperties Whether to use image metadata properties as
1053:             * fallbacks.
1054:             * @param transcode Whether to transcode metadata before writing.
1055:             * @param verifyOutput Whether to verify the validity of the output
1056:             * destination.
1057:             * @param allowPixelReplacement Whether to allow pixel replacement
1058:             * in the output image.
1059:             * @param tileSize The tile size of the output image.
1060:             * @param streamMetadata Stream metadata to write to the output.
1061:             * @param imageMetadata Image metadata to write to the output.
1062:             * @param thumbnails Thumbnails to write to the output.
1063:             * @param listeners EventListeners to be registered with the ImageWriter.
1064:             * @param locale The Locale for the ImageWriter to use.
1065:             * @param writeParam Java Image I/O write parameter instance.
1066:             * @param writer Java Image I/O writer instance.
1067:             * @param hints Operation hints.
1068:             * @return a reference to the operation source.
1069:             */
1070:            public static RenderableOp createRenderable(RenderableImage source,
1071:                    ImageOutputStream output, String format,
1072:                    Boolean useProperties, Boolean transcode,
1073:                    Boolean verifyOutput, Boolean allowPixelReplacement,
1074:                    Dimension tileSize, IIOMetadata streamMetadata,
1075:                    IIOMetadata imageMetadata, BufferedImage[] thumbnails,
1076:                    EventListener[] listeners, Locale locale,
1077:                    ImageWriteParam writeParam, ImageWriter writer,
1078:                    RenderingHints hints) {
1079:                ParameterBlock args = new ParameterBlock();
1080:
1081:                args.addSource(source);
1082:
1083:                args.add(output);
1084:                args.add(format);
1085:                args.add(useProperties);
1086:                args.add(transcode);
1087:                args.add(verifyOutput);
1088:                args.add(allowPixelReplacement);
1089:                args.add(tileSize);
1090:                args.add(streamMetadata);
1091:                args.add(imageMetadata);
1092:                args.add(thumbnails);
1093:                args.add(listeners);
1094:                args.add(locale);
1095:                args.add(writeParam);
1096:                args.add(writer);
1097:
1098:                return JAI.createRenderable(OPERATION_NAME, args, hints);
1099:            }
1100:
1101:            /**
1102:             * Returns true indicating that the operation should be rendered
1103:             * immediately during a call to <code>JAI.create[]()</code> or
1104:             * <code>JAI.createCollection[NS]()</code>.
1105:             *
1106:             * @see javax.media.jai.OperationDescriptor
1107:             */
1108:            public boolean isImmediate() {
1109:                return true;
1110:            }
1111:
1112:            /**
1113:             * Validates the parameters in the supplied <code>ParameterBlock</code>.
1114:             *
1115:             * <p>In addition to the standard validation performed by the
1116:             * corresponding superclass method, this method verifies the following:
1117:             * <ul>
1118:             * <li>if <i>VerifyOutput</i> is <code>TRUE</code> and <i>Output</i>
1119:             * is a <code>File</code> or <code>String</code>, whether the
1120:             * corresponding physical file is writable, i.e., exists and may
1121:             * be overwritten or does not exist and may be created; and</li>
1122:             * <li>if <i>VerifyOutput</i> is <code>TRUE</code> and <i>Output</i>
1123:             * is a <code>Socket</code>, whether it is bound, connected, open,
1124:             * and the write-half is not shut down; and</li>
1125:             * <li>if in collection mode (<code>modeName</code> equals
1126:             * {@link CollectionRegistryMode#MODE_NAME}), the source is not a
1127:             * {@link CollectionOp}, and the size of the source
1128:             * {@link Collection} is greater than unity, whether the
1129:             * {@link ImageWriter} <i>cannot</i> write sequences.</li>
1130:             * </ul>
1131:             *
1132:             * If the superclass method finds that the arguments are invalid, or if
1133:             * this method determines that any of the foregoing conditions is true,
1134:             * an error message will be appended to <code>msg</code> and
1135:             * <code>false</code> will be returned; otherwise <code>true</code> will
1136:             * be returned.</p>
1137:             *
1138:             * @param modeName The operation mode.
1139:             * @param args The source and parameters of the operation.
1140:             * @param msg A container for any error messages.
1141:             *
1142:             * @return Whether the supplied parameters are valid.
1143:             */
1144:            protected boolean validateParameters(String modeName,
1145:                    ParameterBlock args, StringBuffer msg) {
1146:                if (!super .validateParameters(modeName, args, msg)) {
1147:                    return false;
1148:                }
1149:
1150:                // Get the Output parameter.
1151:                Object output = args.getObjectParameter(0);
1152:
1153:                // Check the output if so requested by "VerifyOutput".
1154:                Boolean verifyOutput = (Boolean) args.getObjectParameter(4);
1155:                if (verifyOutput.booleanValue()) {
1156:                    if (output instanceof  File || output instanceof  String) {
1157:                        // Set file and path variables.
1158:                        File file = null;
1159:                        String path = null;
1160:                        if (output instanceof  File) {
1161:                            file = (File) output;
1162:                            path = file.getPath();
1163:                        } else if (output instanceof  String) {
1164:                            path = (String) output;
1165:                            file = new File(path);
1166:                        }
1167:
1168:                        // Perform non-destructive test that the file
1169:                        // may be created and written.
1170:                        try {
1171:                            if (file.exists()) {
1172:                                if (!file.canWrite()) {
1173:                                    // Cannot write to existing file.
1174:                                    msg
1175:                                            .append(file.getPath()
1176:                                                    + " "
1177:                                                    + I18N
1178:                                                            .getString("ImageWriteDescriptor15"));
1179:                                    return false;
1180:                                }
1181:                            } else {
1182:                                if (!file.createNewFile()) {
1183:                                    // Cannot create file.
1184:                                    msg
1185:                                            .append(file.getPath()
1186:                                                    + " "
1187:                                                    + I18N
1188:                                                            .getString("ImageWriteDescriptor16"));
1189:                                    return false;
1190:                                }
1191:                                file.delete();
1192:                            }
1193:                        } catch (IOException ioe) {
1194:                            // I/O exception during createNewFile().
1195:                            msg.append(file.getPath() + " "
1196:                                    + I18N.getString("ImageWriteDescriptor17")
1197:                                    + " " + ioe.getMessage());
1198:                            return false;
1199:                        } catch (SecurityException se) {
1200:                            // Security exception during exists(), canWrite(),
1201:                            // createNewFile(), or delete().
1202:                            msg.append(file.getPath() + " "
1203:                                    + I18N.getString("ImageWriteDescriptor18")
1204:                                    + " " + se.getMessage());
1205:                            return false;
1206:                        }
1207:                    } else if (output instanceof  Socket) {
1208:                        Socket socket = (Socket) output;
1209:
1210:                        if (socket.isOutputShutdown()) {
1211:                            msg.append("\"" + socket + "\": "
1212:                                    + I18N.getString("ImageWriteDescriptor19"));
1213:                            return false;
1214:                        } else if (socket.isClosed()) {
1215:                            msg.append("\"" + socket + "\": "
1216:                                    + I18N.getString("ImageWriteDescriptor20"));
1217:                            return false;
1218:                        } else if (!socket.isBound()) {
1219:                            msg.append("\"" + socket + "\": "
1220:                                    + I18N.getString("ImageWriteDescriptor21"));
1221:                            return false;
1222:                        } else if (!socket.isConnected()) {
1223:                            msg.append("\"" + socket + "\": "
1224:                                    + I18N.getString("ImageWriteDescriptor22"));
1225:                            return false;
1226:                        }
1227:                    }
1228:                }
1229:
1230:                // Get the Format parameter.
1231:                String format = (String) args.getObjectParameter(1);
1232:
1233:                // Get the ImageWriter parameter.
1234:                ImageWriter writer = (ImageWriter) args.getObjectParameter(13);
1235:
1236:                if (format == null) {
1237:                    // Attempt to get the format from the ImageWriter provider.
1238:                    if (writer != null) {
1239:
1240:                        // Get the SPI.
1241:                        ImageWriterSpi spi = writer.getOriginatingProvider();
1242:
1243:                        // Set from the SPI.
1244:                        if (spi != null) {
1245:                            format = spi.getFormatNames()[0];
1246:                        }
1247:                    }
1248:
1249:                    // Attempt to deduce the format from the file suffix.
1250:                    if (format == null
1251:                            && (output instanceof  File || output instanceof  String)) {
1252:
1253:                        // Set the file name string.
1254:                        String name = output instanceof  File ? ((File) output)
1255:                                .getName() : (String) output;
1256:
1257:                        // Extract the suffix.
1258:                        String suffix = name
1259:                                .substring(name.lastIndexOf(".") + 1);
1260:
1261:                        // Get the writers of that suffix.
1262:                        Iterator writers = ImageIO
1263:                                .getImageWritersBySuffix(suffix);
1264:
1265:                        if (writers != null) {
1266:                            // Get the first writer.
1267:                            writer = (ImageWriter) writers.next();
1268:
1269:                            if (writer != null) {
1270:                                // Get the SPI.
1271:                                ImageWriterSpi spi = writer
1272:                                        .getOriginatingProvider();
1273:
1274:                                // Set from the SPI.
1275:                                if (spi != null) {
1276:                                    format = spi.getFormatNames()[0];
1277:                                }
1278:                            }
1279:                        }
1280:                    }
1281:
1282:                    // Default to the most versatile core Java Image I/O writer.
1283:                    if (format == null) {
1284:                        format = "PNG";
1285:                    }
1286:
1287:                    // Replace the format setting.
1288:                    if (format != null) {
1289:                        args.set(format, 1);
1290:                    }
1291:                }
1292:
1293:                // Check the tile size parameter if present.
1294:                Dimension tileSize = (Dimension) args.getObjectParameter(6);
1295:                if (tileSize != null
1296:                        && (tileSize.width <= 0 || tileSize.height <= 0)) {
1297:                    msg.append(I18N.getString("ImageWriteDescriptor23"));
1298:                    return false;
1299:                }
1300:
1301:                // For collection mode, verify that the source collection contains
1302:                // at least one RenderedImage and that the writer can handle sequences
1303:                // if there is more than one RenderedImage in the source collection.
1304:                if (modeName.equalsIgnoreCase(CollectionRegistryMode.MODE_NAME)) {
1305:                    // Get the source collection.
1306:                    Collection source = (Collection) args.getSource(0);
1307:
1308:                    // If the source collection is a CollectionOp do not perform this
1309:                    // check as invoking source.size() will render the node.
1310:                    if (!(source instanceof  CollectionOp)) {
1311:
1312:                        // Determine the number of RenderedImages in the Collection.
1313:                        int numRenderedImages = 0;
1314:                        Iterator iter = source.iterator();
1315:                        while (iter.hasNext()) {
1316:                            if (iter.next() instanceof  RenderedImage) {
1317:                                numRenderedImages++;
1318:                            }
1319:                        }
1320:
1321:                        if (numRenderedImages == 0) {
1322:                            msg
1323:                                    .append(I18N
1324:                                            .getString("ImageWriteDescriptor24"));
1325:                            return false;
1326:                        } else if (numRenderedImages > 1) {
1327:                            // Get the writer parameter.
1328:                            writer = (ImageWriter) args.getObjectParameter(13);
1329:
1330:                            // If the parameter writer is null, get one based on the
1331:                            // format.
1332:                            if (writer == null && format != null) {
1333:                                // Get the writers of that format.
1334:                                Iterator writers = ImageIO
1335:                                        .getImageWritersByFormatName(format);
1336:
1337:                                if (writers != null) {
1338:                                    // Get the first writer.
1339:                                    writer = (ImageWriter) writers.next();
1340:                                }
1341:                            }
1342:
1343:                            if (writer != null) {
1344:                                // Check that the writer can write sequences.
1345:                                if (!writer.canWriteSequence()) {
1346:                                    msg
1347:                                            .append(I18N
1348:                                                    .getString("ImageWriteDescriptor25"));
1349:                                    return false;
1350:                                }
1351:                            }
1352:                        }
1353:                    }
1354:                }
1355:
1356:                return true;
1357:            }
1358:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.