001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: TIFFField.java 447277 2006-09-18 06:19:34Z jeremias $ */
019:
020: package org.apache.xmlgraphics.image.codec.tiff;
021:
022: import java.io.Serializable;
023:
024: /**
025: * A class representing a field in a TIFF 6.0 Image File Directory.
026: *
027: * <p> The TIFF file format is described in more detail in the
028: * comments for the TIFFDescriptor class.
029: *
030: * <p> A field in a TIFF Image File Directory (IFD). A field is defined
031: * as a sequence of values of identical data type. TIFF 6.0 defines
032: * 12 data types, which are mapped internally onto the Java datatypes
033: * byte, int, long, float, and double.
034: *
035: * <p><b> This class is not a committed part of the JAI API. It may
036: * be removed or changed in future releases of JAI.</b>
037: *
038: * @see TIFFDirectory
039: */
040: public class TIFFField extends Object implements Comparable,
041: Serializable {
042:
043: /** Flag for 8 bit unsigned integers. */
044: public static final int TIFF_BYTE = 1;
045:
046: /** Flag for null-terminated ASCII strings. */
047: public static final int TIFF_ASCII = 2;
048:
049: /** Flag for 16 bit unsigned integers. */
050: public static final int TIFF_SHORT = 3;
051:
052: /** Flag for 32 bit unsigned integers. */
053: public static final int TIFF_LONG = 4;
054:
055: /** Flag for pairs of 32 bit unsigned integers. */
056: public static final int TIFF_RATIONAL = 5;
057:
058: /** Flag for 8 bit signed integers. */
059: public static final int TIFF_SBYTE = 6;
060:
061: /** Flag for 8 bit uninterpreted bytes. */
062: public static final int TIFF_UNDEFINED = 7;
063:
064: /** Flag for 16 bit signed integers. */
065: public static final int TIFF_SSHORT = 8;
066:
067: /** Flag for 32 bit signed integers. */
068: public static final int TIFF_SLONG = 9;
069:
070: /** Flag for pairs of 32 bit signed integers. */
071: public static final int TIFF_SRATIONAL = 10;
072:
073: /** Flag for 32 bit IEEE floats. */
074: public static final int TIFF_FLOAT = 11;
075:
076: /** Flag for 64 bit IEEE doubles. */
077: public static final int TIFF_DOUBLE = 12;
078:
079: /** The tag number. */
080: int tag;
081:
082: /** The tag type. */
083: int type;
084:
085: /** The number of data items present in the field. */
086: int count;
087:
088: /** The field data. */
089: Object data;
090:
091: /** The default constructor. */
092: TIFFField() {
093: }
094:
095: /**
096: * Constructs a TIFFField with arbitrary data. The data
097: * parameter must be an array of a Java type appropriate for the
098: * type of the TIFF field. Since there is no available 32-bit
099: * unsigned datatype, long is used. The mapping between types is
100: * as follows:
101: *
102: * <table border=1>
103: * <tr>
104: * <th> TIFF type </th> <th> Java type </th>
105: * <tr>
106: * <td><tt>TIFF_BYTE</tt></td> <td><tt>byte</tt></td>
107: * <tr>
108: * <td><tt>TIFF_ASCII</tt></td> <td><tt>String</tt></td>
109: * <tr>
110: * <td><tt>TIFF_SHORT</tt></td> <td><tt>char</tt></td>
111: * <tr>
112: * <td><tt>TIFF_LONG</tt></td> <td><tt>long</tt></td>
113: * <tr>
114: * <td><tt>TIFF_RATIONAL</tt></td> <td><tt>long[2]</tt></td>
115: * <tr>
116: * <td><tt>TIFF_SBYTE</tt></td> <td><tt>byte</tt></td>
117: * <tr>
118: * <td><tt>TIFF_UNDEFINED</tt></td> <td><tt>byte</tt></td>
119: * <tr>
120: * <td><tt>TIFF_SSHORT</tt></td> <td><tt>short</tt></td>
121: * <tr>
122: * <td><tt>TIFF_SLONG</tt></td> <td><tt>int</tt></td>
123: * <tr>
124: * <td><tt>TIFF_SRATIONAL</tt></td> <td><tt>int[2]</tt></td>
125: * <tr>
126: * <td><tt>TIFF_FLOAT</tt></td> <td><tt>float</tt></td>
127: * <tr>
128: * <td><tt>TIFF_DOUBLE</tt></td> <td><tt>double</tt></td>
129: * </table>
130: */
131: public TIFFField(int tag, int type, int count, Object data) {
132: this .tag = tag;
133: this .type = type;
134: this .count = count;
135: this .data = data;
136: }
137:
138: /**
139: * Returns the tag number, between 0 and 65535.
140: */
141: public int getTag() {
142: return tag;
143: }
144:
145: /**
146: * Returns the type of the data stored in the IFD.
147: * For a TIFF6.0 file, the value will equal one of the
148: * TIFF_ constants defined in this class. For future
149: * revisions of TIFF, higher values are possible.
150: *
151: */
152: public int getType() {
153: return type;
154: }
155:
156: /**
157: * Returns the number of elements in the IFD.
158: */
159: public int getCount() {
160: return count;
161: }
162:
163: /**
164: * Returns the data as an uninterpreted array of bytes.
165: * The type of the field must be one of TIFF_BYTE, TIFF_SBYTE,
166: * or TIFF_UNDEFINED;
167: *
168: * <p> For data in TIFF_BYTE format, the application must take
169: * care when promoting the data to longer integral types
170: * to avoid sign extension.
171: *
172: * <p> A ClassCastException will be thrown if the field is not
173: * of type TIFF_BYTE, TIFF_SBYTE, or TIFF_UNDEFINED.
174: */
175: public byte[] getAsBytes() {
176: return (byte[]) data;
177: }
178:
179: /**
180: * Returns TIFF_SHORT data as an array of chars (unsigned 16-bit
181: * integers).
182: *
183: * <p> A ClassCastException will be thrown if the field is not
184: * of type TIFF_SHORT.
185: */
186: public char[] getAsChars() {
187: return (char[]) data;
188: }
189:
190: /**
191: * Returns TIFF_SSHORT data as an array of shorts (signed 16-bit
192: * integers).
193: *
194: * <p> A ClassCastException will be thrown if the field is not
195: * of type TIFF_SSHORT.
196: */
197: public short[] getAsShorts() {
198: return (short[]) data;
199: }
200:
201: /**
202: * Returns TIFF_SLONG data as an array of ints (signed 32-bit
203: * integers).
204: *
205: * <p> A ClassCastException will be thrown if the field is not
206: * of type TIFF_SLONG.
207: */
208: public int[] getAsInts() {
209: return (int[]) data;
210: }
211:
212: /**
213: * Returns TIFF_LONG data as an array of longs (signed 64-bit
214: * integers).
215: *
216: * <p> A ClassCastException will be thrown if the field is not
217: * of type TIFF_LONG.
218: */
219: public long[] getAsLongs() {
220: return (long[]) data;
221: }
222:
223: /**
224: * Returns TIFF_FLOAT data as an array of floats.
225: *
226: * <p> A ClassCastException will be thrown if the field is not
227: * of type TIFF_FLOAT.
228: */
229: public float[] getAsFloats() {
230: return (float[]) data;
231: }
232:
233: /**
234: * Returns TIFF_DOUBLE data as an array of doubles.
235: *
236: * <p> A ClassCastException will be thrown if the field is not
237: * of type TIFF_DOUBLE.
238: */
239: public double[] getAsDoubles() {
240: return (double[]) data;
241: }
242:
243: /**
244: * Returns TIFF_SRATIONAL data as an array of 2-element arrays of ints.
245: *
246: * <p> A ClassCastException will be thrown if the field is not
247: * of type TIFF_SRATIONAL.
248: */
249: public int[][] getAsSRationals() {
250: return (int[][]) data;
251: }
252:
253: /**
254: * Returns TIFF_RATIONAL data as an array of 2-element arrays of longs.
255: *
256: * <p> A ClassCastException will be thrown if the field is not
257: * of type TIFF_RATTIONAL.
258: */
259: public long[][] getAsRationals() {
260: return (long[][]) data;
261: }
262:
263: /**
264: * Returns data in TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
265: * TIFF_SSHORT, or TIFF_SLONG format as an int.
266: *
267: * <p> TIFF_BYTE and TIFF_UNDEFINED data are treated as unsigned;
268: * that is, no sign extension will take place and the returned
269: * value will be in the range [0, 255]. TIFF_SBYTE data will
270: * be returned in the range [-128, 127].
271: *
272: * <p> A ClassCastException will be thrown if the field is not of
273: * type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
274: * TIFF_SSHORT, or TIFF_SLONG.
275: */
276: public int getAsInt(int index) {
277: switch (type) {
278: case TIFF_BYTE:
279: case TIFF_UNDEFINED:
280: return ((byte[]) data)[index] & 0xff;
281: case TIFF_SBYTE:
282: return ((byte[]) data)[index];
283: case TIFF_SHORT:
284: return ((char[]) data)[index] & 0xffff;
285: case TIFF_SSHORT:
286: return ((short[]) data)[index];
287: case TIFF_SLONG:
288: return ((int[]) data)[index];
289: default:
290: throw new ClassCastException();
291: }
292: }
293:
294: /**
295: * Returns data in TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
296: * TIFF_SSHORT, TIFF_SLONG, or TIFF_LONG format as a long.
297: *
298: * <p> TIFF_BYTE and TIFF_UNDEFINED data are treated as unsigned;
299: * that is, no sign extension will take place and the returned
300: * value will be in the range [0, 255]. TIFF_SBYTE data will
301: * be returned in the range [-128, 127].
302: *
303: * <p> A ClassCastException will be thrown if the field is not of
304: * type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED, TIFF_SHORT,
305: * TIFF_SSHORT, TIFF_SLONG, or TIFF_LONG.
306: */
307: public long getAsLong(int index) {
308: switch (type) {
309: case TIFF_BYTE:
310: case TIFF_UNDEFINED:
311: return ((byte[]) data)[index] & 0xff;
312: case TIFF_SBYTE:
313: return ((byte[]) data)[index];
314: case TIFF_SHORT:
315: return ((char[]) data)[index] & 0xffff;
316: case TIFF_SSHORT:
317: return ((short[]) data)[index];
318: case TIFF_SLONG:
319: return ((int[]) data)[index];
320: case TIFF_LONG:
321: return ((long[]) data)[index];
322: default:
323: throw new ClassCastException();
324: }
325: }
326:
327: /**
328: * Returns data in any numerical format as a float. Data in
329: * TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated by
330: * dividing the numerator into the denominator using
331: * double-precision arithmetic and then truncating to single
332: * precision. Data in TIFF_SLONG, TIFF_LONG, or TIFF_DOUBLE
333: * format may suffer from truncation.
334: *
335: * <p> A ClassCastException will be thrown if the field is
336: * of type TIFF_UNDEFINED or TIFF_ASCII.
337: */
338: public float getAsFloat(int index) {
339: switch (type) {
340: case TIFF_BYTE:
341: return ((byte[]) data)[index] & 0xff;
342: case TIFF_SBYTE:
343: return ((byte[]) data)[index];
344: case TIFF_SHORT:
345: return ((char[]) data)[index] & 0xffff;
346: case TIFF_SSHORT:
347: return ((short[]) data)[index];
348: case TIFF_SLONG:
349: return ((int[]) data)[index];
350: case TIFF_LONG:
351: return ((long[]) data)[index];
352: case TIFF_FLOAT:
353: return ((float[]) data)[index];
354: case TIFF_DOUBLE:
355: return (float) ((double[]) data)[index];
356: case TIFF_SRATIONAL:
357: int[] ivalue = getAsSRational(index);
358: return (float) ((double) ivalue[0] / ivalue[1]);
359: case TIFF_RATIONAL:
360: long[] lvalue = getAsRational(index);
361: return (float) ((double) lvalue[0] / lvalue[1]);
362: default:
363: throw new ClassCastException();
364: }
365: }
366:
367: /**
368: * Returns data in any numerical format as a float. Data in
369: * TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated by
370: * dividing the numerator into the denominator using
371: * double-precision arithmetic.
372: *
373: * <p> A ClassCastException will be thrown if the field is of
374: * type TIFF_UNDEFINED or TIFF_ASCII.
375: */
376: public double getAsDouble(int index) {
377: switch (type) {
378: case TIFF_BYTE:
379: return ((byte[]) data)[index] & 0xff;
380: case TIFF_SBYTE:
381: return ((byte[]) data)[index];
382: case TIFF_SHORT:
383: return ((char[]) data)[index] & 0xffff;
384: case TIFF_SSHORT:
385: return ((short[]) data)[index];
386: case TIFF_SLONG:
387: return ((int[]) data)[index];
388: case TIFF_LONG:
389: return ((long[]) data)[index];
390: case TIFF_FLOAT:
391: return ((float[]) data)[index];
392: case TIFF_DOUBLE:
393: return ((double[]) data)[index];
394: case TIFF_SRATIONAL:
395: int[] ivalue = getAsSRational(index);
396: return (double) ivalue[0] / ivalue[1];
397: case TIFF_RATIONAL:
398: long[] lvalue = getAsRational(index);
399: return (double) lvalue[0] / lvalue[1];
400: default:
401: throw new ClassCastException();
402: }
403: }
404:
405: /**
406: * Returns a TIFF_ASCII data item as a String.
407: *
408: * <p> A ClassCastException will be thrown if the field is not
409: * of type TIFF_ASCII.
410: */
411: public String getAsString(int index) {
412: return ((String[]) data)[index];
413: }
414:
415: /**
416: * Returns a TIFF_SRATIONAL data item as a two-element array
417: * of ints.
418: *
419: * <p> A ClassCastException will be thrown if the field is not
420: * of type TIFF_SRATIONAL.
421: */
422: public int[] getAsSRational(int index) {
423: return ((int[][]) data)[index];
424: }
425:
426: /**
427: * Returns a TIFF_RATIONAL data item as a two-element array
428: * of ints.
429: *
430: * <p> A ClassCastException will be thrown if the field is not
431: * of type TIFF_RATIONAL.
432: */
433: public long[] getAsRational(int index) {
434: return ((long[][]) data)[index];
435: }
436:
437: /**
438: * Compares this <code>TIFFField</code> with another
439: * <code>TIFFField</code> by comparing the tags.
440: *
441: * <p><b>Note: this class has a natural ordering that is inconsistent
442: * with <code>equals()</code>.</b>
443: *
444: * @throws IllegalArgumentException if the parameter is <code>null</code>.
445: * @throws ClassCastException if the parameter is not a
446: * <code>TIFFField</code>.
447: */
448: public int compareTo(Object o) {
449: if (o == null) {
450: throw new IllegalArgumentException();
451: }
452:
453: int oTag = ((TIFFField) o).getTag();
454:
455: if (tag < oTag) {
456: return -1;
457: } else if (tag > oTag) {
458: return 1;
459: } else {
460: return 0;
461: }
462: }
463: }
|