1 /*
2  * $RCSfile: TIFFDescriptor.java,v $
3  *
4  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Use is subject to license terms.
7  *
8  * $Revision: 1.1 $
9  * $Date: 2005/02/11 04:57:45 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.mediax.jai.operator;
13 import com.lightcrafts.media.jai.codec.SeekableStream;
14 import com.lightcrafts.media.jai.codec.TIFFDecodeParam;
15 import java.awt.RenderingHints;
16 import java.awt.image.renderable.ParameterBlock;
17 import com.lightcrafts.mediax.jai.JAI;
18 import com.lightcrafts.mediax.jai.OperationDescriptorImpl;
19 import com.lightcrafts.mediax.jai.ParameterBlockJAI;
20 import com.lightcrafts.mediax.jai.RenderedOp;
21 import com.lightcrafts.mediax.jai.registry.RenderedRegistryMode;
22 
23 /**
24  * An <code>OperationDescriptor</code> describing the "TIFF" operation.
25  *
26  * <p> The "TIFF" operation reads TIFF data from a <code>SeekableStream</code>.
27  *
28  * <p><a href="http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf">
29  * TIFF version 6.0</a> was finalized in June, 1992.  Since that time
30  * there have been two technical notes extending the specification.
31  * There are also a number of
32  * <a href="http://home.earthlink.net/~ritter/tiff/#extensions">
33  * TIFF Extensions</a> including
34  * <a href="http://www.remotesensing.org/geotiff/geotiff.html">
35  * GeoTIFF</a>.
36  *
37  * <p> The TIFF format consists of a short header that points to a
38  * linked list of Image File Directories (IFDs).  An IFD is
39  * essentially a list of fields.  The <code>TIFFDirectory</code> class
40  * encapsulates a set of common operations performed on an IFD; an instance
41  * of the <code>TIFFField</code> class corresponds to a field in an IFD.
42  * Each field has numeric value or <i>tag</i>, a data type, and a byte offset
43  * at which the field's data may be found.  This mechanism allows TIFF
44  * files to contain multiple images, each with its own IFD, and to order
45  * its contents flexibly since (apart from the header) nothing is required to
46  * appear at a fixed offset.
47  *
48  * <p> An image generated by the "TIFF" operation will have a property
49  * named "tiff_directory" the value of which will be a <code>TIFFDirectory</code>
50  * corresponding to the IFD of the image.  JAI's property inheritance mechanism
51  * provides a mechanism by which the field information of the IFD may be
52  * made available to applications in a straightforward way.  This mechanism
53  * may be utilized by setting a <code>PropertyGenerator</code> on this
54  * <code>OperationDescriptor</code> which extracts <code>TIFFField</code>s
55  * from the <code>TIFFDirectory</code>-valued property and returns them either
56  * as <code>TIFFField</code> instances or as some user-defined object
57  * initialized from a <code>TIFFField</code>.  In the latter case application
58  * code would be insulated from the uncommitted <code>TIFFField</code> class.
59  *
60  * <p> The second parameter contains an instance of
61  * <code>TIFFDecodeParam</code> to be used during the decoding.
62  * It may be set to <code>null</code> in order to perform default
63  * decoding, or equivalently may be omitted.
64  *
65  * <p> Some TIFF extensions make use of a mechanism known as "private
66  * IFDs."  A private IFD is one that is not referenced by the standard
67  * linked list of IFDs that starts in the file header.  To a standard
68  * TIFF reader, it appears as an unreferenced area in the file.
69  * However, the byte offset of the private IFD is stored as the value
70  * of a private tag, allowing readers that understand the tag to
71  * locate and interpret the IFD.  The "TIFF" operation may read the data
72  * at an arbitrary IFD by supplying the offset of the IFD via the
73  * <code>setIFDOffset()</code> method of the <code>TIFFDecodeParam</code>
74  * parameter.
75  *
76  * <p> The third parameter specifies which page of the TIFF data to
77  * read.  This permits loading of multi-page TIFF files.  The value
78  * provided is zero-relative and so may be interpreted as the index
79  * of the IFD after the first IFD in the stream with zero of course
80  * indicating the first IFD.  The default value is zero.
81  *
82  * <p> All pages of a multi-page TIFF stream may also be read by doing the
83  * following:
84  * <pre>
85  * SeekableStream s; // initialization omitted
86  * ParameterBlock pb = new ParameterBlock();
87  * pb.add(s);
88  *
89  * TIFFDecodeParam param = new TIFFDecodeParam();
90  * pb.add(param);
91  *
92  * java.util.ArrayList images = new ArrayList();
93  * long nextOffset = 0;
94  * do {
95  *     RenderedOp op = JAI.create("tiff", pb);
96  *     images.add(op);
97  *     TIFFDirectory dir = (TIFFDirectory)op.getProperty("tiff_directory");
98  *     nextOffset = dir.getNextIFDOffset();
99  *     if(nextOffset != 0) {
100  *         param.setIFDOffset(nextOffset);
101  *     }
102  * } while(nextOffset != 0);
103  * </pre>
104  *
105  * <p><b> The classes in the <code>com.lightcrafts.media.jai.codec</code>
106  * package are not a committed part of the JAI API.  Future releases
107  * of JAI will make use of new classes in their place.  This
108  * class will change accordingly.</b>
109  *
110  * <p><table border=1>
111  * <caption>Resource List</caption>
112  * <tr><th>Name</th>        <th>Value</th></tr>
113  * <tr><td>GlobalName</td>  <td>TIFF</td></tr>
114  * <tr><td>LocalName</td>   <td>TIFF</td></tr>
115  * <tr><td>Vendor</td>      <td>com.lightcrafts.media.jai</td></tr>
116  * <tr><td>Description</td> <td>Reads a TIFF 6.0 file.</td></tr>
117  * <tr><td>DocURL</td>      <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/TIFFDescriptor.html</td></tr>
118  * <tr><td>Version</td>     <td>1.0</td></tr>
119  * <tr><td>arg0Desc</td>    <td>The SeekableStream to read from.</td></tr>
120  * <tr><td>arg1Desc</td>    <td>The TIFFDecodeParam to use.</td></tr>
121  * <tr><td>arg2Desc</td>    <td>The page to be decoded.</td></tr>
122  * </table></p>
123  * <p><table border=1>
124  * <caption>Parameter List</caption>
125  * <tr><th>Name</th>  <th>Class Type</th>
126  *                    <th>Default Value</th></tr>
127  * <tr><td>stream</td>  <td>com.lightcrafts.media.jai.codec.SeekableStream</td>
128  *                      <td>NO_PARAMETER_DEFAULT</td>
129  * <tr><td>param</td>   <td>com.lightcrafts.media.jai.codec.TIFFDecodeParam</td>
130  *                      <td>null</td>
131  * <tr><td>page</td>    <td>java.lang.Integer</td>
132  *                      <td>0</td>
133  * </table></p>
134  *
135  * @see com.lightcrafts.media.jai.codec.SeekableStream
136  * @see com.lightcrafts.media.jai.codec.TIFFDecodeParam
137  * @see com.lightcrafts.media.jai.codec.TIFFDirectory
138  * @see com.lightcrafts.media.jai.codec.TIFFEncodeParam
139  * @see com.lightcrafts.media.jai.codec.TIFFField
140  * @see com.lightcrafts.mediax.jai.OperationDescriptor
141  * @see com.lightcrafts.mediax.jai.operator.EncodeDescriptor
142  */
143 public class TIFFDescriptor extends OperationDescriptorImpl {
144 
145     /**
146      * The resource strings that provide the general documentation and
147      * specify the parameter list for the "TIFF" operation.
148      */
149     private static final String[][] resources = {
150         {"GlobalName",  "TIFF"},
151         {"LocalName",   "TIFF"},
152         {"Vendor",      "com.lightcrafts.media.jai"},
153         {"Description", JaiI18N.getString("TIFFDescriptor0")},
154         {"DocURL",      "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/TIFFDescriptor.html"},
155         {"Version",     JaiI18N.getString("DescriptorVersion")},
156         {"arg0Desc",    JaiI18N.getString("TIFFDescriptor1")},
157         {"arg1Desc",    JaiI18N.getString("TIFFDescriptor2")},
158         {"arg2Desc",    JaiI18N.getString("TIFFDescriptor3")}
159     };
160 
161     /** The parameter names for the "TIFF" operation. */
162     private static final String[] paramNames = {
163         "stream", "param", "page"
164     };
165 
166     /** The parameter class types for the "TIFF" operation. */
167     private static final Class[] paramClasses = {
168 	com.lightcrafts.media.jai.codec.SeekableStream.class,
169         com.lightcrafts.media.jai.codec.TIFFDecodeParam.class,
170         java.lang.Integer.class
171     };
172 
173     /** The parameter default values for the "TIFF" operation. */
174     private static final Object[] paramDefaults = {
175         NO_PARAMETER_DEFAULT, null, new Integer(0)
176     };
177 
178     /** Constructor. */
TIFFDescriptor()179     public TIFFDescriptor() {
180         super(resources, 0, paramClasses, paramNames, paramDefaults);
181     }
182 
183 
184     /**
185      * Reads TIFF 6.0 data from an SeekableStream.
186      *
187      * <p>Creates a <code>ParameterBlockJAI</code> from all
188      * supplied arguments except <code>hints</code> and invokes
189      * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
190      *
191      * @see JAI
192      * @see ParameterBlockJAI
193      * @see RenderedOp
194      *
195      * @param stream The SeekableStream to read from.
196      * @param param The TIFFDecodeParam to use.
197      * May be <code>null</code>.
198      * @param page The page to be decoded.
199      * May be <code>null</code>.
200      * @param hints The <code>RenderingHints</code> to use.
201      * May be <code>null</code>.
202      * @return The <code>RenderedOp</code> destination.
203      * @throws IllegalArgumentException if <code>stream</code> is <code>null</code>.
204      */
create(SeekableStream stream, TIFFDecodeParam param, Integer page, RenderingHints hints)205     public static RenderedOp create(SeekableStream stream,
206                                     TIFFDecodeParam param,
207                                     Integer page,
208                                     RenderingHints hints)  {
209         ParameterBlockJAI pb =
210             new ParameterBlockJAI("TIFF",
211                                   RenderedRegistryMode.MODE_NAME);
212 
213         pb.setParameter("stream", stream);
214         pb.setParameter("param", param);
215         pb.setParameter("page", page);
216 
217         return JAI.create("TIFF", pb, hints);
218     }
219 }
220