0001: /*
0002: * $RCSfile: ImageReadDescriptor.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.2 $
0042: * $Date: 2005/12/01 00:40:32 $
0043: * $State: Exp $
0044: */
0045: package com.sun.media.jai.operator;
0046:
0047: import java.awt.RenderingHints;
0048: import java.awt.image.RenderedImage;
0049: import java.awt.image.renderable.ContextualRenderedImageFactory;
0050: import java.awt.image.renderable.ParameterBlock;
0051: import java.awt.image.renderable.RenderableImage;
0052: import java.io.File;
0053: import java.io.InputStream;
0054: import java.net.Socket;
0055: import java.util.Collection;
0056: import java.util.EventListener;
0057: import java.util.Locale;
0058: import javax.imageio.ImageReadParam;
0059: import javax.imageio.ImageReader;
0060: import javax.imageio.stream.ImageInputStream;
0061: import javax.media.jai.JAI;
0062: import javax.media.jai.OperationDescriptorImpl;
0063: import javax.media.jai.OperationRegistry;
0064: import javax.media.jai.PropertyGenerator;
0065: import javax.media.jai.RenderedOp;
0066: import javax.media.jai.RenderableOp;
0067: import javax.media.jai.registry.CollectionRegistryMode;
0068: import javax.media.jai.registry.RenderableRegistryMode;
0069: import javax.media.jai.registry.RenderedRegistryMode;
0070: import com.sun.media.jai.util.PropertyGeneratorImpl;
0071:
0072: /**
0073: * An <code>OperationDescriptor</code> describing the "ImageRead" operation.
0074: *
0075: * <p>The "ImageRead" operation uses the
0076: * <a href="http://java.sun.com/j2se/1.4/docs/guide/imageio/index.html">Java
0077: * Image I/O Framework</a> to read images from an input source. Which formats
0078: * may be read depends on which {@link javax.imageio.ImageReader} plug-ins are
0079: * registered with the Image I/O Framework when the operation is invoked.</p>
0080: *
0081: * <p>The input source will usually be an
0082: * {@link javax.imageio.stream.ImageInputStream}, but may be a
0083: * {@link java.io.File}, {@link java.io.RandomAccessFile},
0084: * {@link java.io.InputStream}, {@link java.net.URL},
0085: * {@link java.net.Socket}, {@link java.nio.channels.ReadableByteChannel},
0086: * file path represented as a <code>String</code> or some other type
0087: * compatible with a reader plug-in. The
0088: * {@link javax.imageio.ImageIO} class should be used to specify the location
0089: * and enable the use of cache files via its <code>setCacheDirectory()</code>
0090: * and <code>setUseCache()</code> methods, respectively. Note that this cache
0091: * pertains to image stream caching and is unrelated to the JAI
0092: * <code>TileCache</code>.</p>
0093: *
0094: * <p>The "ImageRead" operation supports <a href="#RenderedMode">rendered</a>,
0095: * <a href="#RenderableMode">renderable</a>, and
0096: * <a href="#CollectionMode">collection</a> modes and requires no source image.
0097: * A {@link java.awt.RenderingHints} object may be supplied when the operation
0098: * is created. In addition to the {@link java.awt.RenderingHints.Key} hints
0099: * recognized by the eventual <code>OpImage</code> constructor, an
0100: * <a href="#ImageLayout"><code>ImageLayout</code> hint</a> may also be
0101: * supplied. The settings of this <code>ImageLayout</code> override any other
0102: * possible derivation of its components. In particular, it is possible that
0103: * the generated image(s) have a different tile layout than that present in
0104: * the image read from the input source.</p>
0105: *
0106: * <p>Image properties are used to make available metadata and other
0107: * information. Property provision is mode-specific.</p>
0108: *
0109: * <p><table border=1>
0110: * <caption><b>Resource List</b></caption>
0111: * <tr><th>Name</th> <th>Value</th></tr>
0112: * <tr><td>GlobalName</td> <td>ImageRead</td></tr>
0113: * <tr><td>LocalName</td> <td>ImageRead</td></tr>
0114: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
0115: * <tr><td>Description</td> <td>Reads an image using the Java Image I/O Framework.</td></tr>
0116: * <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/ImageReadDescriptor.html</td></tr>
0117: * <tr><td>Version</td> <td>1.0</td></tr>
0118: * <tr><td>arg0Desc</td> <td>The input source.</td></tr>
0119: * <tr><td>arg1Desc</td> <td>The index or indices of the image(s) to read.</td></tr>
0120: * <tr><td>arg2Desc</td> <td>Whether metadata should be read if available.</td></tr>
0121: * <tr><td>arg3Desc</td> <td>Whether thumbnails should be read if available.</td></tr>
0122: * <tr><td>arg4Desc</td> <td>Whether to verify the validity of the input source.</td></tr>
0123: * <tr><td>arg5Desc</td> <td>EventListeners to be registered with the ImageReader.</td></tr>
0124: * <tr><td>arg6Desc</td> <td>The Locale for the ImageReader to use.</td></tr>
0125: * <tr><td>arg7Desc</td> <td>Java Image I/O read parameter instance.</td></tr>
0126: * <tr><td>arg8Desc</td> <td>Java Image I/O reader instance.</td></tr>
0127: * </table></p>
0128: *
0129: * <h2><a name="RenderedMode"</a>Rendered Mode</h2>
0130: *
0131: * In rendered mode the "ImageRead" operation creates a
0132: * {@link java.awt.image.RenderedImage} from the specified input source.
0133: *
0134: * <h3><a name="RenderedModeParameters"</a>Rendered Mode Parameters</h3>
0135: *
0136: * The parameter list of the "ImageRead" operation in rendered mode is
0137: * as in the following table.
0138: *
0139: * <p><table border=1>
0140: * <caption><b>Rendered Mode Parameter List</b></caption>
0141: * <tr><th>Name</th> <th>Class Type</th>
0142: * <th>Default Value</th></tr>
0143: * <tr><td><a href="#ParamInput">
0144: * Input</a></td> <td>java.lang.Object.class</td>
0145: * <td>NO_PARAMETER_DEFAULT</td>
0146: * <tr><td><a href="#ParamImageChoice">
0147: * ImageChoice</a></td> <td>java.lang.Integer</td>
0148: * <td>0</td>
0149: * <tr><td><a href="#ParamReadMetadata">
0150: * ReadMetadata</a></td> <td>java.lang.Boolean</td>
0151: * <td>TRUE</td>
0152: * <tr><td><a href="#ParamReadThumbnails">
0153: * ReadThumbnails</a></td> <td>java.lang.Boolean</td>
0154: * <td>TRUE</td>
0155: * <tr><td><a href="#ParamVerifyInput">
0156: * VerifyInput</a></td> <td>java.lang.Boolean</td>
0157: * <td>TRUE</td>
0158: * <tr><td><a href="#ParamListeners">
0159: * Listeners</a></td> <td>java.util.EventListener[]</td>
0160: * <td>null</td>
0161: * <tr><td><a href="#ParamLocale">
0162: * Locale</a></td> <td>java.util.Locale</td>
0163: * <td>null</td>
0164: * <tr><td><a href="#ParamReadParam">
0165: * ReadParam</a></td> <td>javax.imageio.ImageReadParam</td>
0166: * <td>null</td>
0167: * <tr><td><a href="#ParamReader">
0168: * Reader</a></td> <td>javax.imageio.ImageReader</td>
0169: * <td>null</td>
0170: * </table></p>
0171: *
0172: * <p>The rendered mode parameters are handled as follows:
0173: *
0174: * <ul>
0175: * <p><li><a name="ParamInput"</a>
0176: * If Input is a String it is assumed to represent a file path. When
0177: * the node is rendered, if Input is not already an ImageInputStream, then
0178: * ImageIO.createImageInputStream() will be used to attempt to derive an
0179: * ImageInputStream. If such an ImageInputStream is available, it will be
0180: * set as the input of the ImageReader; otherwise the original value of
0181: * Input will be used. Before attempting to apply createImageInputStream(),
0182: * if Input is a String it will be converted to a RandomAccessFile, or if it
0183: * is a Socket or a URL to an InputStream. If the conversion of the Input
0184: * String to RandomAccessFile fails, it will be converted to an
0185: * InputStream by accessing it as a resource bundled in a JAR file.</li></p>
0186: *
0187: * <p><li><a name="ParamImageChoice"</a>
0188: * If ImageChoice is negative an exception will be thrown when the
0189: * operation is created.</li></p>
0190: *
0191: * <p><li><a name="ParamReadMetadata"</a>
0192: * Image properties associated with metadata will be set if and only if
0193: * ReadMetadata is TRUE and the respective metadata are defined. This
0194: * parameter overrides the setting of the ignoreMetadata field of the
0195: * Reader parameter if the latter is also supplied. Metadata property
0196: * values will not be set until requested, i.e., their computation is
0197: * deferred.</li></p>
0198: *
0199: * <p><li><a name="ParamReadThumbnails"</a>
0200: * The image property associated with thumbnails will be set if and only if
0201: * ReadThumbnails is TRUE and thumbnails are defined for the image at the
0202: * specified index. Thumbnail property values are not set until requested,
0203: * i.e., their computation is deferred.</li></p>
0204: *
0205: * <p><li><a name="ParamVerifyInput"</a>
0206: * If VerifyInput is TRUE and Input is either a File or a String which
0207: * specifies a file path, then canRead() will be invoked on Input or a
0208: * derived File object as appropriate. If canRead() returns 'false' an
0209: * exception will be thrown. Note that the canRead() method can not be
0210: * invoked in the case of the Input being a String specifying a file path
0211: * which can be accessed only as an InputStream resource from a JAR file.
0212: * This option is useful to suppress verifying
0213: * the existence of a file on the local file system when this operation is
0214: * created as the local portion of a remote operation which will be
0215: * rendered on a remote peer. This verification will occur when the
0216: * operation is created. </li></p>
0217: *
0218: * <p><li>If VerifyInput is TRUE and Input is a Socket, then an exception will
0219: * be thrown if the socket is not bound, not connected, is closed, or its
0220: * read-half is shut down. This verification will occur when the
0221: * operation is created.</li></p>
0222: *
0223: * <p><li><a name="ParamListeners"</a>
0224: * Listeners will be used to set any progress, update, or warning listeners
0225: * of the ImageReader. Each element in the java.util.EventListener array will
0226: * be added for all types of listener it implements. For example if a listener
0227: * object implements all of the javax.imageio.event.IIORead*Listeners
0228: * interfaces then it will be added as a listener of each of the three types.
0229: * Any elements in the array which do not implement any of the
0230: * IIORead*Listeners will be ignored.</li></p>
0231: *
0232: * <p><li><a name="ParamLocale"</a>
0233: * Locale will be used to set the Locale of the ImageReader. This parameter
0234: * overrides the equivalent setting of the Reader parameter if the latter is
0235: * also supplied.</li></p>
0236: *
0237: * <p><li><a name="ParamReadParam"</a>
0238: * If ReadParam is null, an ImageReadParam will be derived internally using
0239: * ImageReader.getDefaultReadParam(). Supplying an ImageReadParam can be
0240: * useful for special operations such as setting the bands to read via
0241: * setSourceBands() or the subsampling factors via
0242: * setSourceSubsampling(). If the ImageReadParam parameter is not an instance
0243: * of a cloneable subclass of javax.imageio.ImageReadParam, then it would be
0244: * best to avoid using the setDestinationType(), setDestinationOffset(), and
0245: * setSourceRegion() methods on the supplied object as these methods will be
0246: * invoked internally by the reader.</li></p>
0247: *
0248: * <p><li><a name="ParamReader"</a>
0249: * If Reader is null, an attempt will be made to derive an ImageReader
0250: * using ImageIO.getImageReaders().</li></p>
0251: * </ul></p>
0252: *
0253: * <h4><a name="SyncPolicy"</a>Parameters and Synchronization Policy</h4>
0254: *
0255: * Note that any supplied ImageReadParam parameter may be modified within this
0256: * operator. Also, any of the various reading methods of the ImageReader may be
0257: * invoked at an arbitrary subsequent time to populate the image data. Correct
0258: * handling of these parameters at the application level is left to the user.
0259: * Specifically no guarantee as to the correct behavior of this operation is
0260: * made in the cases wherein a user passes in an ImageReadParam or ImageReader
0261: * parameter and modifies its state while this operation is still using these
0262: * objects. This applies especially in the case of multi-threaded applications.
0263: * In such instances it is recommended that the user either not pass in either
0264: * of these parameters or simply use the Java Image I/O API directly rather
0265: * than the JAI operation. (Threads managed internally by JAI, e.g., in the
0266: * TileScheduler, interact with the image object created by this operation only
0267: * via synchronized methods thereby preventing potential race conditions.)
0268: * These caveats also apply to the use of ImageReaders and ImageReadParams
0269: * obtained from image properties.
0270: *
0271: * <p>The foregoing policy regarding modification of any supplied ImageReadParam
0272: * or ImageReader is necessary as neither of these classes is cloneable. Given
0273: * that as a starting point there are in effect three possibilities: (A) do not
0274: * accept them as parameters, (B) accept them via alternate parameters which do
0275: * not pose these problems (for example an ImageReaderSpi and a long list of
0276: * settings represented by the ImageReadParam), or (C) accept them explicitly.
0277: * Option C has been deemed preferable despite the potential race condition
0278: * issues.</p>
0279: *
0280: * <p>In the Sun Microsystems implementation of this operation these potential
0281: * conflicts have been mitigated to a certain extent:
0282: *
0283: * <ul>
0284: * <p><li>If the param is cloneable then it is cloned and the clone used internally.
0285: * Otherwise if the param is an instance of ImageReadParam itself rather than
0286: * of a subclass thereof, i.e., getClass().getName() invoked on the param
0287: * returns "javax.imageio.ImageReadParam", then a new ImageReadParam is
0288: * constructed and the settings of the original param copied to it. If the
0289: * param is not cloneable and is an instance of a proper subclass of
0290: * ImageWriteParam then it is used directly.</li></p>
0291: *
0292: * <p><li>The only ImageReader methods invoked after OpImage construction are
0293: * read(int,ImageReadParam), getNumThumbnails(int), readThumbnail(int,int),
0294: * isIgnoringMetadata(), getStreamMetadata(), and getImageMetadata(int).
0295: * These methods are invoked within getProperty() and with the exception
0296: * of isIgnoringMetadata() are synchronized on the ImageReader.</li></p>
0297: * </ul>
0298: * </p>
0299: *
0300: * <h3><a name="ImageLayout"</a>ImageLayout Hint Handling</h3>
0301: *
0302: * If an ImageLayout hint is provided via the operation's RenderingHints, its
0303: * values will be used. In particular a SampleModel or ColorModel supplied via
0304: * an ImageLayout hint will override any values set via the ImageTypeSpecifier
0305: * of the ImageReadParam parameter if the latter is non-null. This signifies
0306: * that the ImageTypeSpecifier of the OpImage rendering associated with the
0307: * operation node will be forced to match that of the layout even if this type
0308: * is different from or incompatible with the image types available from the
0309: * ImageReader. Note that in such an eventuality an extra amount of memory
0310: * equal to one image tile might be needed for copying purposes. This copying
0311: * is handled by the JAI operation itself.
0312: *
0313: * <p>Any fields of the supplied ImageLayout which are not set will be set to
0314: * default values as follows. The ImageLayout will be cloned before it is
0315: * modified.</p>
0316: *
0317: * <h4>ImageLayout Defaults</h4>
0318: *
0319: * <p><ul>
0320: * <p><li>Image Bounds {minX, minY, width, height}
0321: *
0322: * <p>Each value defaults to the corresponding value of the destination
0323: * which would be derived on the basis of the source image dimensions
0324: * and the settings of the ImageReadParam, i.e., source region,
0325: * subsampling offsets and factors, and destination offset.</p>
0326: *
0327: * <p>It should be noted that unlike in the Java Image I/O API itself,
0328: * negative coordinates are permitted and the image origin is not
0329: * required to be at (0,0) as for BufferedImages. Therefore it is
0330: * possible that a given image be loaded using the same ImageReadParam
0331: * by an ImageReader and by the "ImageRead" operation with different
0332: * results. Possible differences would be that the portion of the
0333: * image with negative coordinates is not clipped as it would be with
0334: * direct Image I/O access, and no empty extent between (0,0) and the
0335: * start of the data will be present.</p>
0336: *
0337: * <p>For example, if the ImageReadParam had sourceRegion [0,0,w,h],
0338: * destinationOffset [-w/2,-h/2], and no subsampling, then the Java
0339: * Image I/O API would compute the effective source and destination
0340: * regions to be [w/2,h/2,w/2,h/2] and [0,0,w/2,h/2], respectively.
0341: * The JAI ImageRead operation would compute the effective source and
0342: * destination regions to be [0,0,w,h] and [-w/2,-h/2,w,h], respectively.
0343: * The Image I/O result would therefore be equal to the bottom right
0344: * quadrant of the JAI result.</p></li></p>
0345: *
0346: * <p><li>Tile Grid {tileGridXOffset, tileGridYOffset, tileWidth, tileHeight}
0347: *
0348: * <pre>
0349: * tileGridXOffset = ImageReader.getTileGridXOffset(imageIndex);
0350: * tileGridYOffset = ImageReader.getTileGridYOffset(imageIndex);
0351: * tileWidth = ImageReader.getTileWidth(imageIndex);
0352: * tileHeight = ImageReader.getTileHeight(imageIndex);
0353: * </pre></li></p>
0354: *
0355: * <p><li>ColorModel
0356: *
0357: * <pre>
0358: * ImageReader.getRawImageType(imageIndex).getColorModel();
0359: * </pre></li></p>
0360: *
0361: * <p><li>SampleModel
0362: *
0363: * <pre>
0364: * ImageReader.getRawImageType(imageIndex).getSampleModel().createCompatibleSampleModel(tileWidth, tileHeight);
0365: * </pre></li></p>
0366: * </ul></p>
0367: *
0368: * <h3><a name="RenderedModeProperties"</a>Image Properties in Rendered Mode</h3>
0369: *
0370: * Image properties are used to provide metadata, thumbnails, and reader-related
0371: * information. The following properties may be obtained from the RenderedOp
0372: * created for the "ImageRead" operation in rendered mode:
0373: *
0374: * <p><table border=1>
0375: * <caption><b>Rendered Mode Image Properties</b></caption>
0376: * <tr>
0377: * <th>Property Name</th>
0378: * <th>Type</th>
0379: * <th>Comment</th>
0380: * </tr>
0381: * <tr>
0382: * <td>JAI.ImageReadParam</td>
0383: * <td>ImageReadParam</td>
0384: * <td>Set to ImageReadParam actually used which may differ from the one passed in.</td>
0385: * </tr>
0386: * <tr>
0387: * <td>JAI.ImageReader</td>
0388: * <td>ImageReader</td>
0389: * <td>Set to ImageReader actually used.</td>
0390: * </tr>
0391: * <tr>
0392: * <td>JAI.ImageMetadata</td>
0393: * <td>IIOMetadata</td>
0394: * <td>Set if and only if ReadMetadata parameter is TRUE and image metadata are available.</td>
0395: * </tr>
0396: * <tr>
0397: * <td>JAI.StreamMetadata</td>
0398: * <td>IIOMetadata</td>
0399: * <td>Set if and only if ReadMetadata parameter is TRUE and stream metadata are available.</td>
0400: * </tr>
0401: * <tr>
0402: * <td>JAI.Thumbnails</td>
0403: * <td>BufferedImage[]</td>
0404: * <td>Set if and only if ReadThumbnails parameter is TRUE and thumbnails are available.</td>
0405: * </tr>
0406: * </table></p>
0407: *
0408: * <p>If a given property is not set, this implies of course that the names of
0409: * absent properties will not appear in the array returned by getPropertyNames()
0410: * and getProperty() invoked to obtain absent properties will return
0411: * java.awt.Image.UndefinedProperty as usual.</p>
0412: *
0413: * <p>The ImageReader and ImageReadParam may be used for subsequent invocations
0414: * of the operation (for example to obtain different images in a multi-page file)
0415: * or for informational purposes. Care should be taken in using these property
0416: * values with respect to the synchronization issues previously discussed.</p>
0417: *
0418: * <p>In all cases image metadata properties will be set when the node is rendered,
0419: * i.e., metadata reading is not subject to the same deferred execution as is
0420: * image data reading. The thumbnail property value will not be set however until
0421: * its value is actually requested.</p>
0422: *
0423: * <h2><a name="RenderableMode"</a>Renderable Mode</h2>
0424: *
0425: * In renderable mode the "ImageRead" operation creates a
0426: * {@link java.awt.image.renderable.RenderableImage} from the specified
0427: * input source.
0428: *
0429: * <p>It should be noted that although they are discussed in the context of
0430: * rendered mode, the <a href="#SyncPolicy">parameter synchronization
0431: * policy</a> and <a href="#ImageLayout">ImageLayout handling methodology</a>
0432: * apply to renderable mode as well.</p>
0433: *
0434: * <h3><a name="RenderableModeParameters"</a>Renderable Mode Parameters</h3>
0435: *
0436: * The parameter list of the "ImageRead" operation in renderable mode is
0437: * identical to the <a href="#RenderedModeParameters">rendered mode parameter
0438: * list</a> mode except as indicated in the following table.
0439: *
0440: * <p><table border=1>
0441: * <caption><b>Renderable Mode Parameter Differences</b></caption>
0442: * <tr><th>Name</th> <th>Class Type</th>
0443: * <th>Default Value</th></tr>
0444: * <tr><td>ImageChoice</td> <td>int[]</td>
0445: * <td>int[] {0,...,NumImages-1}</td>
0446: * </table></p>
0447: *
0448: * <p>In the Sun Microsystems renderable mode implementation of the "ImageRead"
0449: * operation, when createRendering() is invoked on the RenderableImage created
0450: * by the operation, a MultiResolutionRenderableImage is constructed from a
0451: * Vector of RenderedImages consisting of the images at the specified indices.
0452: * These images will be sorted into order of decreasing resolution (as
0453: * determined by the product of width and height for each image) and inserted
0454: * in this order in the Vector of images used to construct the
0455: * MultiResolutionRenderableImage. Metadata will be set on the component
0456: * RenderedImages as usual for rendered mode. Finally the
0457: * createRendering() invocation will be forwarded to the underlying
0458: * MultiResolutionRenderableImage and the resulting RenderedImage returned.</p>
0459: *
0460: * <p>Note that using this approach the entire MultiResolutionRenderableImage
0461: * must be regenerated for each invocation of createRendering(). If multiple
0462: * renderings are to be created from the RenderableImage without changing
0463: * the operation parameters, then a more efficient approach would be to use the
0464: * "JAI.RenderableInput" property to be described.</p>
0465: *
0466: * <h3>Image Properties in Renderable Mode</h3>
0467: *
0468: * The following property will be set on the RenderableOp created for the
0469: * "ImageRead" operation in renderable mode:
0470: *
0471: * <p><table border=1>
0472: * <caption><b>Renderable Mode Image Properties</b></caption>
0473: * <tr>
0474: * <th>Property Name</th>
0475: * <th>Type</th>
0476: * <th>Comment</th>
0477: * </tr>
0478: * <tr>
0479: * <td>JAI.RenderableInput</td>
0480: * <td>RenderableImage</td>
0481: * <td>A RenderableImage derived from the input source according to the supplied set of parameters.</td>
0482: * </tr>
0483: * </table></p>
0484: *
0485: * <p>The RenderableImage which is the value of the foregoing property may have
0486: * set on it any of the properties previously described for rendered mode
0487: * contingent on parameter settings and data availability. The image metadata
0488: * and thumbnail properties would be copied from the highest resolution image
0489: * among those specified by the ImageChoice parameter.</p>
0490: *
0491: * <p>If multiple renderings are to be created from the RenderableImage
0492: * without changing the operation parameters, then an efficient alternative
0493: * approach to multiple invocations of createRendering() on the RenderableImage
0494: * is to obtain the RenderableImage value of the "JAI.RenderableInput" property
0495: * and invoke createRendering() on this value.</p>
0496: *
0497: * <h2><a name="CollectionMode"</a>Collection Mode</h2>
0498: *
0499: * In collection mode the "ImageRead" operation creates a
0500: * <code>Collection</code> of <code>RenderedImage</code>s from the specified
0501: * input source. This could be used for example to load an animated GIF
0502: * image or a multi-page TIFF image.
0503: *
0504: * <p>It should be noted that although they are discussed in the context of
0505: * rendered mode, the <a href="#SyncPolicy">parameter synchronization
0506: * policy</a> and <a href="#ImageLayout">ImageLayout handling methodology</a>
0507: * apply to collection mode as well.</p>
0508: *
0509: * <h3>Collection Mode Parameters</h3>
0510: *
0511: * The parameter list of the "ImageRead" operation in collection mode is
0512: * identical to the <a href="#RenderableModeParameters">renderable mode
0513: * parameter list</a>. In this case
0514: * the RenderedImages loaded for the specified indices will be used to create
0515: * a Collection of RenderedImages. The images will be loaded in the order of
0516: * the indices in the supplied array and appended to a List. The rendering of
0517: * the operation will be a CollectionImage the 'imageCollection' instance
0518: * variable of which will be set to this List.
0519: *
0520: * <h3>Image Properties in Collection Mode</h3>
0521: *
0522: * Contingent on parameter settings and the presence of the appropriate
0523: * metadata, the rendered Collection may have the "JAI.StreamMetadata",
0524: * "JAI.ImageReadParam", and "JAI.ImageReader" properties set. Each
0525: * RenderedImage in the Collection may contain the
0526: * <a href="#RenderedModeProperties">rendered mode properties</a> contingent
0527: * on parameter settings and data availability.
0528: *
0529: * @see javax.media.jai.OperationDescriptor
0530: * @see javax.imageio.ImageReader
0531: * @see javax.imageio.ImageReadParam
0532: * @see javax.imageio.metadata.IIOMetadata
0533: * @see javax.imageio.stream.ImageInputStream
0534: */
0535: public class ImageReadDescriptor extends OperationDescriptorImpl {
0536:
0537: // Property name constants have package access for image factory use.
0538:
0539: /** ImageReadParam property name "JAI.ImageReadParam". */
0540: public static final String PROPERTY_NAME_IMAGE_READ_PARAM = "JAI.ImageReadParam";
0541:
0542: /** ImageReader property name "JAI.ImageReader". */
0543: public static final String PROPERTY_NAME_IMAGE_READER = "JAI.ImageReader";
0544:
0545: /** Image metadata property name "JAI.ImageMetadata". */
0546: public static final String PROPERTY_NAME_METADATA_IMAGE = "JAI.ImageMetadata";
0547:
0548: /** Stream metadata property name "JAI.StreamMetadata". */
0549: public static final String PROPERTY_NAME_METADATA_STREAM = "JAI.StreamMetadata";
0550:
0551: /** Thumbnail property name "JAI.Thumbnails". */
0552: public static final String PROPERTY_NAME_THUMBNAILS = "JAI.Thumbnails";
0553:
0554: /**
0555: * Renderable input property name "JAI.RenderableInput".
0556: */
0557: public static final String PROPERTY_NAME_RENDERABLE_INPUT = "JAI.RenderableInput";
0558:
0559: /**
0560: * Test method.
0561: *
0562: * @param args {inputFile[, mode]}
0563: * @throws Throwable any error.
0564: */
0565: /* XXX
0566: public static void main(String[] args) {
0567: String fileName = args[0];
0568: String modeName = args.length > 1 ?
0569: args[1] : RenderedRegistryMode.MODE_NAME;
0570:
0571: ParameterBlock pb =
0572: (new ParameterBlock()).add(new java.io.File(fileName));
0573:
0574: java.awt.image.RenderedImage[] images = null;
0575: if(modeName.equalsIgnoreCase(RenderedRegistryMode.MODE_NAME)) {
0576: images = new java.awt.image.RenderedImage[1];
0577: images[0] = JAI.create("ImageRead", pb, null);
0578: PrintProps.print((javax.media.jai.PropertySource)images[0]);
0579: } else if(modeName.equalsIgnoreCase(RenderableRegistryMode.MODE_NAME)) {
0580: //pb.add(new int[] {0});
0581: java.awt.image.renderable.RenderableImage ri =
0582: JAI.createRenderable("ImageRead", pb, null);
0583: PrintProps.print((javax.media.jai.PropertySource)ri);
0584: images = new java.awt.image.RenderedImage[1];
0585: //java.awt.image.renderable.RenderContext rc =
0586: // new java.awt.image.renderable.RenderContext(
0587: // new java.awt.geom.AffineTransform(42, 0, 0, 42, 0, 0));
0588: //images[0] = ri.createRendering(rc);
0589: images[0] = ri.createDefaultRendering();
0590: PrintProps.print((javax.media.jai.PropertySource)images[0]);
0591: } else if(modeName.equalsIgnoreCase(CollectionRegistryMode.MODE_NAME)) {
0592: //pb.add(new int[] {0});
0593: java.util.Collection imageCollection =
0594: JAI.createCollection("ImageRead", pb, null);
0595: PrintProps.print((javax.media.jai.PropertySource)imageCollection);
0596: images = new java.awt.image.RenderedImage[imageCollection.size()];
0597: imageCollection.toArray(images);
0598: } else {
0599: throw new UnsupportedOperationException(modeName+" mode not supported");
0600: }
0601:
0602: final java.awt.Frame frame = new java.awt.Frame();
0603: frame.addWindowListener(new java.awt.event.WindowAdapter() {
0604: public void windowClosing(java.awt.event.WindowEvent e) {
0605: frame.setEnabled(false);
0606: frame.dispose();
0607: }
0608: });
0609:
0610: int gridSide = (int)(Math.sqrt(images.length) + 0.5);
0611: frame.setLayout(new java.awt.GridLayout(gridSide, gridSide));
0612: java.awt.Dimension screenSize =
0613: java.awt.Toolkit.getDefaultToolkit().getScreenSize();
0614: int width =
0615: Math.min(screenSize.width/gridSide, images[0].getWidth());
0616: int height =
0617: Math.min(screenSize.height/gridSide, images[0].getHeight());
0618: for(int i = 0; i < images.length; i++) {
0619: javax.media.jai.widget.ScrollingImagePanel panel =
0620: new javax.media.jai.widget.ScrollingImagePanel(images[i],
0621: width, //image.getWidth(),
0622: height);//image.getHeight());
0623: frame.add(panel);
0624: }
0625: frame.pack();
0626: frame.show();
0627: }
0628: */
0629:
0630: /**
0631: * The name of the operation.
0632: */
0633: private static final String OPERATION_NAME = "ImageRead";
0634:
0635: /**
0636: * The resource strings that provide the general documentation and
0637: * specify the parameter list for the "ImageRead" operation.
0638: */
0639: private static final String[][] resources = {
0640: { "GlobalName", OPERATION_NAME },
0641: { "LocalName", OPERATION_NAME },
0642: { "Vendor", "com.sun.media.jai" },
0643: { "Description", I18N.getString("ImageReadDescriptor0") },
0644: {
0645: "DocURL",
0646: "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ImageReadDescriptor.html" },
0647: { "Version", I18N.getString("DescriptorVersion") },
0648: { "arg0Desc", I18N.getString("ImageReadDescriptor1") },
0649: { "arg1Desc", I18N.getString("ImageReadDescriptor2") },
0650: { "arg2Desc", I18N.getString("ImageReadDescriptor3") },
0651: { "arg3Desc", I18N.getString("ImageReadDescriptor4") },
0652: { "arg4Desc", I18N.getString("ImageReadDescriptor5") },
0653: { "arg5Desc", I18N.getString("ImageReadDescriptor6") },
0654: { "arg6Desc", I18N.getString("ImageReadDescriptor7") },
0655: { "arg7Desc", I18N.getString("ImageReadDescriptor8") },
0656: { "arg8Desc", I18N.getString("ImageReadDescriptor9") } };
0657:
0658: /** The parameter names for the "ImageRead" operation. */
0659: private static final String[] paramNames = { "Input",
0660: "ImageChoice", "ReadMetadata", "ReadThumbnails",
0661: "VerifyInput", "Listeners", "Locale", "ReadParam", "Reader" };
0662:
0663: /** The parameter class types for rendered mode of "ImageRead". */
0664: private static final Class[] renderedParamClasses = {
0665: java.lang.Object.class, // Input
0666: java.lang.Integer.class, // ImageChoice
0667: java.lang.Boolean.class, // ReadMetadata
0668: java.lang.Boolean.class, // ReadThumbnails
0669: java.lang.Boolean.class, // VerifyInput
0670: java.util.EventListener[].class, // Listeners
0671: java.util.Locale.class, // Locale
0672: javax.imageio.ImageReadParam.class, // ReadParam
0673: javax.imageio.ImageReader.class // Reader
0674: };
0675:
0676: /** The parameter default values for rendered mode of "ImageRead". */
0677: private static final Object[] renderedParamDefaults = {
0678: NO_PARAMETER_DEFAULT, // Input
0679: new Integer(0), // ImageChoice
0680: Boolean.TRUE, // ReadMetadata
0681: Boolean.TRUE, // ReadThumbnails
0682: Boolean.TRUE, // VerifyInput
0683: null, // Listeners
0684: null, // Locale
0685: null, // ReadParam
0686: null // Reader
0687: };
0688:
0689: /** The parameter class types for renderable mode of "ImageRead". */
0690: private static final Class[] renderableParamClasses = {
0691: java.lang.Object.class, // Input
0692: int[].class, // ImageChoice
0693: java.lang.Boolean.class, // ReadMetadata
0694: java.lang.Boolean.class, // ReadThumbnails
0695: java.lang.Boolean.class, // VerifyInput
0696: java.util.EventListener[].class, // Listeners
0697: java.util.Locale.class, // Locale
0698: javax.imageio.ImageReadParam.class, // ReadParam
0699: javax.imageio.ImageReader.class // Reader
0700: };
0701:
0702: /** The parameter default values for renderable mode of "ImageRead". */
0703: private static final Object[] renderableParamDefaults = {
0704: NO_PARAMETER_DEFAULT, // Input
0705: null, // ImageChoice
0706: Boolean.TRUE, // ReadMetadata
0707: Boolean.TRUE, // ReadThumbnails
0708: Boolean.TRUE, // VerifyInput
0709: null, // Listeners
0710: null, // Locale
0711: null, // ReadParam
0712: null // Reader
0713: };
0714:
0715: /** The parameter class types for collection mode of "ImageRead". */
0716: private static final Class[] collectionParamClasses = renderableParamClasses;
0717:
0718: /** The parameter default values for collection mode of "ImageRead". */
0719: private static final Object[] collectionParamDefaults = renderableParamDefaults;
0720:
0721: /** Constructor. */
0722: public ImageReadDescriptor() {
0723: super (
0724: resources,
0725: new String[] { RenderedRegistryMode.MODE_NAME,
0726: RenderableRegistryMode.MODE_NAME,
0727: CollectionRegistryMode.MODE_NAME },
0728: null, // sourceNames
0729: new Class[][] { null, null, null }, // sourceClasses
0730: paramNames,
0731: new Class[][] { renderedParamClasses,
0732: renderableParamClasses, collectionParamClasses },
0733: new Object[][] { renderedParamDefaults,
0734: renderableParamDefaults,
0735: collectionParamDefaults }, new Object[][] {
0736: null, null, null }); // validParamValues
0737: }
0738:
0739: /**
0740: * Type-safe convenience method for creating a {@link RenderedOp}
0741: * representing the "ImageRead" operation in rendered mode. The
0742: * method packs the parameters into a new <code>ParameterBlock</code>
0743: * and invokes {@link JAI#create(String,ParameterBlock,RenderingHints)}.
0744: *
0745: * @param input The input source.
0746: * @param imageChoice The index of the image to read.
0747: * @param readMetadata Whether metadata should be read if available.
0748: * @param readThumbnails Whether thumbnails should be read if available.
0749: * @param verifyInput Whether to verify the validity of the input source.
0750: * @param listeners EventListeners to be registered with the ImageReader.
0751: * @param locale The Locale for the ImageReader to use.
0752: * @param readParam Java Image I/O read parameter instance.
0753: * @param reader Java Image I/O reader instance.
0754: * @param hints Hints possibly including an <code>ImageLayout</code>.
0755: * @return an image derived from the input source.
0756: */
0757: public static RenderedOp create(ImageInputStream input,
0758: Integer imageChoice, Boolean readMetadata,
0759: Boolean readThumbnails, Boolean verifyInput,
0760: EventListener[] listeners, Locale locale,
0761: ImageReadParam readParam, ImageReader reader,
0762: RenderingHints hints) {
0763:
0764: ParameterBlock args = new ParameterBlock();
0765:
0766: args.add(input);
0767: args.add(imageChoice);
0768: args.add(readMetadata);
0769: args.add(readThumbnails);
0770: args.add(verifyInput);
0771: args.add(listeners);
0772: args.add(locale);
0773: args.add(readParam);
0774: args.add(reader);
0775:
0776: return JAI.create(OPERATION_NAME, args, hints);
0777: }
0778:
0779: /**
0780: * Type-safe convenience method for creating a {@link Collection}
0781: * representing the "ImageRead" operation in collection mode. The
0782: * method packs the parameters into a new <code>ParameterBlock</code>
0783: * and invokes
0784: * {@link JAI#createCollection(String,ParameterBlock, RenderingHints)}.
0785: *
0786: * @param input The input source.
0787: * @param imageChoice The indices of the images to read.
0788: * @param readMetadata Whether metadata should be read if available.
0789: * @param readThumbnails Whether thumbnails should be read if available.
0790: * @param verifyInput Whether to verify the validity of the input source.
0791: * @param listeners EventListeners to be registered with the ImageReader.
0792: * @param locale The Locale for the ImageReader to use.
0793: * @param readParam Java Image I/O read parameter instance.
0794: * @param reader Java Image I/O reader instance.
0795: * @param hints Hints possibly including an <code>ImageLayout</code>.
0796: * @return a collection of images derived from the input source.
0797: */
0798: public static Collection createCollection(ImageInputStream input,
0799: int[] imageChoice, Boolean readMetadata,
0800: Boolean readThumbnails, Boolean verifyInput,
0801: EventListener[] listeners, Locale locale,
0802: ImageReadParam readParam, ImageReader reader,
0803: RenderingHints hints) {
0804:
0805: ParameterBlock args = new ParameterBlock();
0806:
0807: args.add(input);
0808: args.add(imageChoice);
0809: args.add(readMetadata);
0810: args.add(readThumbnails);
0811: args.add(verifyInput);
0812: args.add(listeners);
0813: args.add(locale);
0814: args.add(readParam);
0815: args.add(reader);
0816:
0817: return JAI.createCollection(OPERATION_NAME, args, hints);
0818: }
0819:
0820: /**
0821: * Type-safe convenience method for creating a {@link RenderableOp}
0822: * representing the "ImageRead" operation in renderable mode. The
0823: * method packs the parameters into a new <code>ParameterBlock</code>
0824: * and invokes
0825: * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
0826: *
0827: * @param input The input source.
0828: * @param imageChoice The indices of the images to read.
0829: * @param readMetadata Whether metadata should be read if available.
0830: * @param readThumbnails Whether thumbnails should be read if available.
0831: * @param verifyInput Whether to verify the validity of the input source.
0832: * @param listeners EventListeners to be registered with the ImageReader.
0833: * @param locale The Locale for the ImageReader to use.
0834: * @param readParam Java Image I/O read parameter instance.
0835: * @param reader Java Image I/O reader instance.
0836: * @param hints Hints possibly including an <code>ImageLayout</code>.
0837: * @return an image capable of rendering an image from those in the
0838: * input source.
0839: */
0840: public static RenderableOp createRenderable(ImageInputStream input,
0841: int[] imageChoice, Boolean readMetadata,
0842: Boolean readThumbnails, Boolean verifyInput,
0843: EventListener[] listeners, Locale locale,
0844: ImageReadParam readParam, ImageReader reader,
0845: RenderingHints hints) {
0846:
0847: ParameterBlock args = new ParameterBlock();
0848:
0849: args.add(input);
0850: args.add(imageChoice);
0851: args.add(readMetadata);
0852: args.add(readThumbnails);
0853: args.add(verifyInput);
0854: args.add(listeners);
0855: args.add(locale);
0856: args.add(readParam);
0857: args.add(reader);
0858:
0859: return JAI.createRenderable(OPERATION_NAME, args, hints);
0860: }
0861:
0862: /**
0863: * Returns the array of {@link PropertyGenerator}s for the specified
0864: * mode of this operation.
0865: *
0866: * <p>For renderable mode returns an array containing a single
0867: * <code>PropertyGenerator</code> which defines a
0868: * {@link RenderableImage}-valued property named "JAI.RenderableInput".
0869: * For all other modes <code>null</code> is returned.</p>
0870: *
0871: * @param modeName The name of the mode.
0872: * @return An array containing a single <code>PropertyGenerator</code>
0873: * if <code>modeName</code> is "renderable" (case-insensitive) or
0874: * <code>null</code> otherwise.
0875: */
0876: public PropertyGenerator[] getPropertyGenerators(String modeName) {
0877: return modeName
0878: .equalsIgnoreCase(RenderableRegistryMode.MODE_NAME) ? new PropertyGenerator[] { new ImageReadPropertyGenerator() }
0879: : null;
0880: }
0881:
0882: /**
0883: * Validates the parameters in the supplied <code>ParameterBlock</code>.
0884: *
0885: * <p>In addition to the standard validation performed by the
0886: * corresponding superclass method, this method verifies the following:
0887: * <ul>
0888: * <li>whether <i>ImageChoice</i> is negative (rendered mode)
0889: * or contains any negative indices (other modes); and</li>
0890: * <li>if <i>VerifyInput</i> is <code>TRUE</code> and <i>Input</i>
0891: * is a <code>File</code> or <code>String</code>, whether the
0892: * corresponding physical file exists and is readable; and</li>
0893: * <li>if <i>VerifyInput</i> is <code>TRUE</code> and <i>Input</i>
0894: * is a <code>String</code>, converting which to a
0895: * corresponding physical file failed, whether it can be converted
0896: * to an InputStream accessed as a resource from a JAR file; and</li>
0897: * <li>if <i>VerifyInput</i> is <code>TRUE</code> and <i>Input</i>
0898: * is a <code>Socket</code>, whether it is bound, connected, open,
0899: * and the read-half is not shut down.</li>
0900: * </ul>
0901: *
0902: * If the superclass method finds that the arguments are invalid, or if
0903: * this method determines that any of the foregoing conditions is true,
0904: * an error message will be appended to <code>msg</code> and
0905: * <code>false</code> will be returned; otherwise <code>true</code> will
0906: * be returned.</p>
0907: *
0908: * <p>The file existence and readability verification may be suppressed
0909: * by setting the <i>VerifyInput</i> parameter to <code>FALSE</code>.
0910: * This might be desirable for example if the operation is being
0911: * created for remote rendering and <i>Input</i> is a file which is at
0912: * a location visible on the remote peer but not on the host on which
0913: * the operation is created.</p>
0914: *
0915: * @param modeName The operation mode.
0916: * @param args The source and parameters of the operation.
0917: * @param msg A container for any error messages.
0918: *
0919: * @return Whether the supplied parameters are valid.
0920: */
0921: protected boolean validateParameters(String modeName,
0922: ParameterBlock args, StringBuffer msg) {
0923: if (!super .validateParameters(modeName, args, msg)) {
0924: return false;
0925: }
0926:
0927: // Check "ImageChoice" for negative value(s).
0928: if (modeName.equalsIgnoreCase(RenderedRegistryMode.MODE_NAME)) {
0929: if (args.getIntParameter(1) < 0) {
0930: msg.append(I18N.getString("ImageReadDescriptor10"));
0931: return false;
0932: }
0933: } else { // Non-rendered modes.
0934: int[] imageIndices = (int[]) args.getObjectParameter(1);
0935: if (imageIndices != null) {
0936: for (int i = 0; i < imageIndices.length; i++) {
0937: if (imageIndices[i] < 0) {
0938: msg.append(I18N
0939: .getString("ImageReadDescriptor10"));
0940: return false;
0941: }
0942: }
0943: }
0944: }
0945:
0946: // Check the input if so requested by "VerifyInput".
0947: Boolean verifyInput = (Boolean) args.getObjectParameter(4);
0948: if (verifyInput.booleanValue()) {
0949: // Get the Input parameter.
0950: Object input = args.getObjectParameter(0);
0951:
0952: if (input instanceof File || input instanceof String) {
0953: // Set file and path variables.
0954: File file = null;
0955: String path = null;
0956: if (input instanceof File) {
0957: file = (File) input;
0958: path = file.getPath();
0959: } else if (input instanceof String) {
0960: path = (String) input;
0961: file = new File(path);
0962: }
0963:
0964: // If input is a verify that it exists and is readable.
0965: if (file != null) {
0966: if (!file.exists()) {
0967: // Check if the file is accessible as an InputStream
0968: // resource. This would be the case if the application
0969: // and the image file are packaged in a JAR file
0970: InputStream is = getClass().getClassLoader()
0971: .getResourceAsStream((String) input);
0972: if (is == null) {
0973: msg
0974: .append("\""
0975: + path
0976: + "\": "
0977: + I18N
0978: .getString("ImageReadDescriptor11"));
0979: return false;
0980: }
0981: } else if (!file.canRead()) {
0982: msg
0983: .append("\""
0984: + path
0985: + "\": "
0986: + I18N
0987: .getString("ImageReadDescriptor12"));
0988: return false;
0989: }
0990: }
0991: } else if (input instanceof Socket) {
0992: Socket socket = (Socket) input;
0993:
0994: if (socket.isInputShutdown()) {
0995: msg.append("\"" + socket + "\": "
0996: + I18N.getString("ImageReadDescriptor13"));
0997: return false;
0998: } else if (socket.isClosed()) {
0999: msg.append("\"" + socket + "\": "
1000: + I18N.getString("ImageReadDescriptor14"));
1001: return false;
1002: } else if (!socket.isBound()) {
1003: msg.append("\"" + socket + "\": "
1004: + I18N.getString("ImageReadDescriptor15"));
1005: return false;
1006: } else if (!socket.isConnected()) {
1007: msg.append("\"" + socket + "\": "
1008: + I18N.getString("ImageReadDescriptor16"));
1009: return false;
1010: }
1011: }
1012: }
1013:
1014: return true;
1015: }
1016: }
1017:
1018: // XXX Does this need to return ImageReader and ReadParam props also?
1019: // XXX This same property needs to be set also on each rendering so that
1020: // copying does not occur and require more computation.
1021: final class ImageReadPropertyGenerator extends PropertyGeneratorImpl {
1022:
1023: /** Constructor. */
1024: ImageReadPropertyGenerator() {
1025: super (
1026: new String[] { ImageReadDescriptor.PROPERTY_NAME_RENDERABLE_INPUT },
1027: new Class[] { RenderableImage.class },
1028: new Class[] { RenderableOp.class });
1029: }
1030:
1031: /**
1032: * Returns the specified property in the renderable layer.
1033: *
1034: * @param name Property name.
1035: * @param opNode Operation node.
1036: */
1037: public Object getProperty(String name, Object opNode) {
1038: // Check arguments.
1039: validate(name, opNode);
1040:
1041: // Default to undefined value.
1042: Object value = java.awt.Image.UndefinedProperty;
1043:
1044: if (opNode instanceof RenderableOp
1045: && name
1046: .equalsIgnoreCase(ImageReadDescriptor.PROPERTY_NAME_RENDERABLE_INPUT)) {
1047:
1048: // Save the node reference and get the hints.
1049: RenderableOp node = (RenderableOp) opNode;
1050: RenderingHints hints = node.getRenderingHints();
1051:
1052: // Get the CRIF for "ImageRead".
1053: OperationRegistry registry = null;
1054: ContextualRenderedImageFactory crif = null;
1055:
1056: // Try to get the CRIF from a registry specified in the hints.
1057: if (hints != null
1058: && hints.containsKey(JAI.KEY_OPERATION_REGISTRY)) {
1059: registry = (OperationRegistry) hints
1060: .get(JAI.KEY_OPERATION_REGISTRY);
1061: crif = (ContextualRenderedImageFactory) registry
1062: .getFactory(RenderableRegistryMode.MODE_NAME,
1063: "ImageRead");
1064: }
1065:
1066: // If no registry in the hints or that registry does not contain
1067: // a CRIF for "ImageRead", try to get it from the default registry.
1068: if (crif == null) {
1069: registry = JAI.getDefaultInstance()
1070: .getOperationRegistry();
1071: crif = (ContextualRenderedImageFactory) registry
1072: .getFactory(RenderableRegistryMode.MODE_NAME,
1073: "ImageRead");
1074: }
1075:
1076: // Create the RenderableImage and set the property value to it.
1077: if (crif != null
1078: && crif instanceof com.sun.media.jai.imageioimpl.ImageReadCRIF) {
1079: value = ((com.sun.media.jai.imageioimpl.ImageReadCRIF) crif)
1080: .createRenderable(node.getParameterBlock(),
1081: hints);
1082: }
1083: }
1084:
1085: return value;
1086: }
1087: }
|