001: package org.libtiff.jai.codec;
002:
003: /*
004: * XTIFF: eXtensible TIFF libraries for JAI.
005: *
006: * The contents of this file are subject to the JAVA ADVANCED IMAGING
007: * SAMPLE INPUT-OUTPUT CODECS AND WIDGET HANDLING SOURCE CODE License
008: * Version 1.0 (the "License"); You may not use this file except in
009: * compliance with the License. You may obtain a copy of the License at
010: * http://www.sun.com/software/imaging/JAI/index.html
011: *
012: * Software distributed under the License is distributed on an "AS IS"
013: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
014: * the License for the specific language governing rights and limitations
015: * under the License.
016: *
017: * The Original Code is JAVA ADVANCED IMAGING SAMPLE INPUT-OUTPUT CODECS
018: * AND WIDGET HANDLING SOURCE CODE.
019: * The Initial Developer of the Original Code is: Sun Microsystems, Inc..
020: * Portions created by: Niles Ritter
021: * are Copyright (C): Niles Ritter, GeoTIFF.org, 1999,2000.
022: * All Rights Reserved.
023: * Contributor(s): Niles Ritter
024: */
025:
026: import java.io.IOException;
027: import java.util.Enumeration;
028: import java.util.Hashtable;
029: import java.util.Vector;
030: import java.util.TreeMap;
031: import java.util.Iterator;
032: import org.libtiff.jai.util.JaiI18N;
033:
034: // Warning: media libraries subject to change
035: import com.sun.media.jai.codec.SeekableStream;
036:
037: /**
038: * XTIFFDirectory is an extensible TIFF directory object. This
039: * class may be extended without changing the XTIFF codec by
040: * overriding the XTIFFFactory instance registered in this
041: * class. In addition, this class is the repository of all
042: * XTIFFTileCodec's which may be augmented with new codecs,
043: * again without overriding the ImageCodec. If the jai "tiff"
044: * codec has been overridden through the
045: * <code>XTIFFDescriptor.register()</code> method, each XTIFF image will
046: * possess a property called "tiff.directory" which will be
047: * an object of the type created by the factory. The class is
048: * declared as serializable to permit its transmission to remote
049: * images as a set of parameters to the codec, and to be able
050: * to survive as an instantiated property of the RenderedImage.
051: *
052: *
053: * @serializable
054: * @author Niles Ritter
055: * @see XTIFFDescriptor
056: * @see XTIFFField
057: * @see XTIFFTileCodec
058: * @see XTIFFFactory
059: */
060: public class XTIFFDirectory extends Object implements
061: java.io.Serializable {
062: private int imageType;
063:
064: /** default directory factory */
065: protected static XTIFFFactory factory = new XTIFFFactory();
066:
067: protected static Hashtable tileCodecs = new Hashtable();
068:
069: /** The stream being read. Not persisted */
070: transient protected SeekableStream stream;
071:
072: /** A boolean storing the endianness of the stream. */
073: boolean isBigEndian;
074:
075: /** A boolean indicating tiled tagset */
076: boolean _isTiled = false;
077:
078: /** for dynamically adding fields in sorted order*/
079: TreeMap fieldIndex = new TreeMap();
080:
081: /** The default constructor. Publicized for Serializability */
082: public XTIFFDirectory() {
083: }
084:
085: private static boolean isValidEndianTag(int endian) {
086: return ((endian == 0x4949) || (endian == 0x4d4d));
087: }
088:
089: /**
090: * If true this image uses TIFF 6.0 tiling
091: */
092: public boolean isTiled() {
093: return _isTiled;
094: }
095:
096: /**
097: * reads the TIFF header. Not likely to be overridden.
098: */
099: protected void readHeader() throws IOException {
100:
101: // Read the TIFF header
102: stream.seek(0L);
103: int endian = stream.readUnsignedShort();
104: if (!isValidEndianTag(endian)) {
105: throw new IllegalArgumentException(JaiI18N
106: .getString("XTIFFDirectory1"));
107: }
108: isBigEndian = (endian == 0x4d4d);
109:
110: // Verify that Douglas Addams still has influence in software:
111: int magic = readUnsignedShort(stream);
112: if (magic != 42) {
113: throw new IllegalArgumentException(JaiI18N
114: .getString("XTIFFDirectory2"));
115: }
116:
117: }
118:
119: /**
120: * Constructs a XTIFFDirectory from a SeekableStream.
121: * The directory parameter specifies which directory to read from
122: * the linked list present in the stream; directory 0 is normally
123: * read but it is possible to store multiple images in a single
124: * TIFF file by maintaing multiple directories.
125: *
126: * @param stream a SeekableStream to read from.
127: * @param directory the index of the directory to read.
128: */
129: protected XTIFFDirectory(SeekableStream stream, int directory)
130: throws IOException {
131:
132: this .stream = stream;
133: long global_save_offset = stream.getFilePointer();
134: long ifd_offset;
135:
136: readHeader();
137:
138: // Get the initial ifd offset as an unsigned int (using a long)
139: ifd_offset = readUnsignedInt(stream);
140:
141: for (int i = 0; i < directory; i++) {
142: if (ifd_offset == 0L) {
143: throw new IllegalArgumentException(JaiI18N
144: .getString("XTIFFDirectory3"));
145: }
146:
147: stream.seek(ifd_offset);
148: int entries = readUnsignedShort(stream);
149: stream.skip(12 * entries);
150:
151: ifd_offset = readUnsignedInt(stream);
152: }
153:
154: stream.seek(ifd_offset);
155: initialize();
156: stream.seek(global_save_offset);
157: }
158:
159: /**
160: * Constructs a XTIFFDirectory by reading a SeekableStream.
161: * The ifd_offset parameter specifies the stream offset from which
162: * to begin reading; this mechanism is sometimes used to store
163: * private IFDs within a TIFF file that are not part of the normal
164: * sequence of IFDs.
165: *
166: * @param stream a SeekableStream to read from.
167: * @param ifd_offset the long byte offset of the directory.
168: */
169: protected XTIFFDirectory(SeekableStream stream, long ifd_offset)
170: throws IOException {
171: this .stream = stream;
172: long global_save_offset = stream.getFilePointer();
173:
174: readHeader();
175:
176: stream.seek(ifd_offset);
177: initialize();
178: stream.seek(global_save_offset);
179: }
180:
181: private static final int[] _sizeOfType = { 0, // 0 = n/a
182: 1, // 1 = byte
183: 1, // 2 = ascii
184: 2, // 3 = short
185: 4, // 4 = long
186: 8, // 5 = rational
187: 1, // 6 = sbyte
188: 1, // 7 = undefined
189: 2, // 8 = sshort
190: 4, // 9 = slong
191: 8, // 10 = srational
192: 4, // 11 = float
193: 8 // 12 = double
194: };
195:
196: /**
197: * Return the size of a data type. Extend if you
198: * need to define new TIFF field types. Also override
199: * the createField() method of the XTIFFFactory, the
200: * XTIFFField class, and the readFieldValue() method here.
201: * @param type the XTIFFField type code
202: * @see XTIFFField
203: * @see XTIFFFactory
204: */
205: public int sizeOfType(int type)
206: throws ArrayIndexOutOfBoundsException {
207: return _sizeOfType[type];
208: }
209:
210: /**
211: * Create and add a TIFF field to this directory.
212: * @param tag the TIFF tag listed in XTIFF
213: * @param type the TIFF field type listed in XTIFFField
214: * @param count the number of values in array obj
215: * @param obj the array of values
216: * @see XTIFFField
217: * @see XTIFF
218: */
219: public void addField(int tag, int type, int count, Object obj) {
220: addField(factory.createField(tag, type, count, obj));
221: }
222:
223: /**
224: * Create a TIFF field
225: * @param tag the TIFF tag listed in XTIFF
226: * @param type the TIFF field type listed in XTIFFField
227: * @param count the number of values in array obj
228: * @param obj the array of values
229: * @see XTIFFField
230: * @see XTIFF
231: */
232: public static XTIFFField createField(int tag, int type, int count,
233: Object obj) {
234: return factory.createField(tag, type, count, obj);
235: }
236:
237: /**
238: * Add an existing TIFF field to this directory.
239: * @param type the XTIFFField type code
240: * @see XTIFFField
241: */
242: public void addField(XTIFFField field) {
243: fieldIndex.put(new Integer(field.tag), field);
244: }
245:
246: /**
247: * Initialize the directory from a stream
248: */
249: protected void initialize() throws IOException {
250: XTIFFField field;
251: long nextTagOffset;
252:
253: int numEntries = readUnsignedShort(stream);
254:
255: for (int i = 0; i < numEntries; i++) {
256:
257: try {
258: field = readField();
259: } catch (ArrayIndexOutOfBoundsException ae) {
260: // if the data type is unknown we should skip this TIFF Field
261: continue;
262: }
263: addField(field);
264: }
265: }
266:
267: /** Returns the number of directory entries. */
268: public int getNumEntries() {
269: return fieldIndex.size();
270: }
271:
272: /**
273: * Returns the value of a given tag as a XTIFFField,
274: * or null if the tag is not present.
275: */
276: public XTIFFField getField(int tag) {
277: return (XTIFFField) fieldIndex.get(new Integer(tag));
278: }
279:
280: /**
281: * Returns true if a tag appears in the directory.
282: */
283: public boolean isTagPresent(int tag) {
284: return fieldIndex.containsKey(new Integer(tag));
285: }
286:
287: /**
288: * Returns an ordered array of ints indicating the tag
289: * values.
290: */
291: public int[] getTags() {
292: int[] tags = new int[fieldIndex.size()];
293: Iterator iter = fieldIndex.keySet().iterator();
294: int i = 0;
295: while (iter.hasNext()) {
296: tags[i++] = ((Integer) iter.next()).intValue();
297: }
298: return tags;
299: }
300:
301: /**
302: * Returns an array of XTIFFFields containing all the fields
303: * in this directory.
304: */
305: public XTIFFField[] getFields() {
306: XTIFFField[] fields = new XTIFFField[fieldIndex.size()];
307: Iterator iter = fieldIndex.values().iterator();
308: int i = 0;
309: while (iter.hasNext()) {
310: fields[i++] = (XTIFFField) iter.next();
311: }
312: return fields;
313: }
314:
315: /**
316: * Returns the value of a particular index of a given tag as a
317: * byte. The caller is responsible for ensuring that the tag is
318: * present and has type XTIFFField.TIFF_SBYTE, TIFF_BYTE, or
319: * TIFF_UNDEFINED.
320: */
321: public byte getFieldAsByte(int tag, int index) {
322: return (getField(tag).getAsBytes())[index];
323: }
324:
325: /**
326: * Returns the value of index 0 of a given tag as a
327: * byte. The caller is responsible for ensuring that the tag is
328: * present and has type XTIFFField.TIFF_SBYTE, TIFF_BYTE, or
329: * TIFF_UNDEFINED.
330: */
331: public byte getFieldAsByte(int tag) {
332: return getFieldAsByte(tag, 0);
333: }
334:
335: /**
336: * Returns the value of a particular index of a given tag as a
337: * long. The caller is responsible for ensuring that the tag is
338: * present and has type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED,
339: * TIFF_SHORT, TIFF_SSHORT, TIFF_SLONG or TIFF_LONG.
340: */
341: public long getFieldAsLong(int tag, int index) {
342: return getField(tag).getAsLong(index);
343: }
344:
345: /**
346: * Returns the value of index 0 of a given tag as a
347: * long. The caller is responsible for ensuring that the tag is
348: * present and has type TIFF_BYTE, TIFF_SBYTE, TIFF_UNDEFINED,
349: * TIFF_SHORT, TIFF_SSHORT, TIFF_SLONG or TIFF_LONG.
350: */
351: public long getFieldAsLong(int tag) {
352: return getFieldAsLong(tag, 0);
353: }
354:
355: /**
356: * Returns the value of a particular index of a given tag as a
357: * float. The caller is responsible for ensuring that the tag is
358: * present and has numeric type (all but TIFF_UNDEFINED and
359: * TIFF_ASCII).
360: */
361: public float getFieldAsFloat(int tag, int index) {
362: return getField(tag).getAsFloat(index);
363: }
364:
365: /**
366: * Returns the value of index 0 of a given tag as a float. The
367: * caller is responsible for ensuring that the tag is present and
368: * has numeric type (all but TIFF_UNDEFINED and TIFF_ASCII).
369: */
370: public float getFieldAsFloat(int tag) {
371: return getFieldAsFloat(tag, 0);
372: }
373:
374: /**
375: * Returns the value of a particular index of a given tag as a
376: * double. The caller is responsible for ensuring that the tag is
377: * present and has numeric type (all but TIFF_UNDEFINED and
378: * TIFF_ASCII).
379: */
380: public double getFieldAsDouble(int tag, int index) {
381: return getField(tag).getAsDouble(index);
382: }
383:
384: /**
385: * Returns the value of index 0 of a given tag as a double. The
386: * caller is responsible for ensuring that the tag is present and
387: * has numeric type (all but TIFF_UNDEFINED and TIFF_ASCII).
388: */
389: public double getFieldAsDouble(int tag) {
390: return getFieldAsDouble(tag, 0);
391: }
392:
393: /**
394: * TIFF field-value reader. Override if there are
395: * new field types. Also override sizeOfType() and,
396: * possibly the createField method of the factory,
397: * if the field needs new accessors.
398: */
399: public Object readFieldValue(int tag, int type, int count)
400: throws IOException, ArrayIndexOutOfBoundsException {
401: int j;
402: Object obj = null;
403:
404: switch (type) {
405: case XTIFFField.TIFF_BYTE:
406: case XTIFFField.TIFF_SBYTE:
407: case XTIFFField.TIFF_UNDEFINED:
408: case XTIFFField.TIFF_ASCII:
409: byte[] bvalues = new byte[count];
410: stream.readFully(bvalues, 0, count);
411:
412: if (type == XTIFFField.TIFF_ASCII) {
413:
414: // Can be multiple strings
415: int index = 0, prevIndex = 0;
416: Vector v = new Vector();
417:
418: while (index < count) {
419:
420: while ((index < count) && (bvalues[index++] != 0))
421: ;
422:
423: // When we encountered zero, means one string has ended
424: v.add(new String(bvalues, prevIndex,
425: (index - prevIndex)));
426: prevIndex = index;
427: }
428:
429: count = v.size();
430: String strings[] = new String[count];
431: for (int c = 0; c < count; c++) {
432: strings[c] = (String) v.elementAt(c);
433: }
434:
435: obj = strings;
436: } else {
437: obj = bvalues;
438: }
439:
440: break;
441:
442: case XTIFFField.TIFF_SHORT:
443: char[] cvalues = new char[count];
444: for (j = 0; j < count; j++) {
445: cvalues[j] = (char) (readUnsignedShort(stream));
446: }
447: obj = cvalues;
448: break;
449:
450: case XTIFFField.TIFF_LONG:
451: long[] lvalues = new long[count];
452: for (j = 0; j < count; j++) {
453: lvalues[j] = readUnsignedInt(stream);
454: }
455: obj = lvalues;
456: break;
457:
458: case XTIFFField.TIFF_RATIONAL:
459: long[][] llvalues = new long[count][2];
460: for (j = 0; j < count; j++) {
461: llvalues[j][0] = readUnsignedInt(stream);
462: llvalues[j][1] = readUnsignedInt(stream);
463: }
464: obj = llvalues;
465: break;
466:
467: case XTIFFField.TIFF_SSHORT:
468: short[] svalues = new short[count];
469: for (j = 0; j < count; j++) {
470: svalues[j] = readShort(stream);
471: }
472: obj = svalues;
473: break;
474:
475: case XTIFFField.TIFF_SLONG:
476: int[] ivalues = new int[count];
477: for (j = 0; j < count; j++) {
478: ivalues[j] = readInt(stream);
479: }
480: obj = ivalues;
481: break;
482:
483: case XTIFFField.TIFF_SRATIONAL:
484: int[][] iivalues = new int[count][2];
485: for (j = 0; j < count; j++) {
486: iivalues[j][0] = readInt(stream);
487: iivalues[j][1] = readInt(stream);
488: }
489: obj = iivalues;
490: break;
491:
492: case XTIFFField.TIFF_FLOAT:
493: float[] fvalues = new float[count];
494: for (j = 0; j < count; j++) {
495: fvalues[j] = readFloat(stream);
496: }
497: obj = fvalues;
498: break;
499:
500: case XTIFFField.TIFF_DOUBLE:
501: double[] dvalues = new double[count];
502: for (j = 0; j < count; j++) {
503: dvalues[j] = readDouble(stream);
504: }
505: obj = dvalues;
506: break;
507:
508: default:
509: System.err.println(JaiI18N.getString("XTIFFDirectory0"));
510: break;
511: }
512: return obj;
513: }
514:
515: /**
516: * Method for reading a field from stream. Positions
517: * stream at the next field location.
518: */
519: private XTIFFField readField() throws IOException,
520: ArrayIndexOutOfBoundsException {
521: int j;
522: int tag = readUnsignedShort(stream);
523: int type = readUnsignedShort(stream);
524: int count = (int) readUnsignedInt(stream);
525: int value = 0;
526:
527: // The place to return to to read the next tag
528: long nextTagOffset = stream.getFilePointer() + 4;
529:
530: try {
531: // If the tag data can't fit in 4 bytes, the next 4 bytes
532: // contain the starting offset of the data
533: if (count * sizeOfType(type) > 4) {
534: value = (int) (readUnsignedInt(stream));
535: stream.seek(value);
536: }
537: } catch (ArrayIndexOutOfBoundsException ae) {
538: System.err.println(tag + " "
539: + JaiI18N.getString("XTIFFDirectory4"));
540: // if the data type is unknown we should skip this TIFF Field
541: stream.seek(nextTagOffset);
542: throw ae;
543: }
544:
545: Object obj = readFieldValue(tag, type, count);
546:
547: // Position stream at next field and return this one
548: stream.seek(nextTagOffset);
549:
550: return createField(tag, type, count, obj);
551: }
552:
553: // Methods to read primitive data types from the stream
554:
555: protected short readShort(SeekableStream stream) throws IOException {
556: if (isBigEndian) {
557: return stream.readShort();
558: } else {
559: return stream.readShortLE();
560: }
561: }
562:
563: protected int readUnsignedShort(SeekableStream stream)
564: throws IOException {
565: if (isBigEndian) {
566: int val = stream.readUnsignedShort();
567: return val;
568: } else {
569: int val = stream.readUnsignedShortLE();
570: return val;
571: }
572: }
573:
574: protected int readInt(SeekableStream stream) throws IOException {
575: if (isBigEndian) {
576: return stream.readInt();
577: } else {
578: return stream.readIntLE();
579: }
580: }
581:
582: protected long readUnsignedInt(SeekableStream stream)
583: throws IOException {
584: if (isBigEndian) {
585: return stream.readUnsignedInt();
586: } else {
587: return stream.readUnsignedIntLE();
588: }
589: }
590:
591: protected long readLong(SeekableStream stream) throws IOException {
592: if (isBigEndian) {
593: return stream.readLong();
594: } else {
595: return stream.readLongLE();
596: }
597: }
598:
599: protected float readFloat(SeekableStream stream) throws IOException {
600: if (isBigEndian) {
601: return stream.readFloat();
602: } else {
603: return stream.readFloatLE();
604: }
605: }
606:
607: protected double readDouble(SeekableStream stream)
608: throws IOException {
609: if (isBigEndian) {
610: return stream.readDouble();
611: } else {
612: return stream.readDoubleLE();
613: }
614: }
615:
616: // Static methods used by the public static method below
617:
618: private static int readUnsignedShort(SeekableStream stream,
619: boolean isBigEndian) throws IOException {
620: if (isBigEndian) {
621: return stream.readUnsignedShort();
622: } else {
623: return stream.readUnsignedShortLE();
624: }
625: }
626:
627: private static long readUnsignedInt(SeekableStream stream,
628: boolean isBigEndian) throws IOException {
629: if (isBigEndian) {
630: return stream.readUnsignedInt();
631: } else {
632: return stream.readUnsignedIntLE();
633: }
634: }
635:
636: // Utilities
637:
638: /**
639: * Returns the number of image directories (subimages) stored in a
640: * given TIFF file, represented by a <code>SeekableStream</code>.
641: */
642: public static int getNumDirectories(SeekableStream stream)
643: throws IOException {
644: long pointer = stream.getFilePointer(); // Save stream pointer
645:
646: stream.seek(0L);
647: int endian = stream.readUnsignedShort();
648: if (!isValidEndianTag(endian)) {
649: throw new IllegalArgumentException(JaiI18N
650: .getString("XTIFFDirectory1"));
651: }
652: boolean isBigEndian = (endian == 0x4d4d);
653: int magic = readUnsignedShort(stream, isBigEndian);
654: if (magic != 42) {
655: throw new IllegalArgumentException(JaiI18N
656: .getString("XTIFFDirectory2"));
657: }
658:
659: stream.seek(4L);
660: long offset = readUnsignedInt(stream, isBigEndian);
661:
662: int numDirectories = 0;
663: while (offset != 0L) {
664: ++numDirectories;
665:
666: stream.seek(offset);
667: int entries = readUnsignedShort(stream, isBigEndian);
668: stream.skip(12 * entries);
669: offset = readUnsignedInt(stream, isBigEndian);
670: }
671:
672: stream.seek(pointer); // Reset stream pointer
673: return numDirectories;
674: }
675:
676: /**
677: * Returns a boolean indicating whether the byte order used in the
678: * the TIFF file is big-endian (i.e. whether the byte order is from
679: * the most significant to the least significant)
680: */
681: public boolean isBigEndian() {
682: return isBigEndian;
683: }
684:
685: /**
686: * Specifies the type of compression to be used. The compression type
687: * specified will be honored only if it is compatible with the image
688: * being written out.
689: *
690: * @param compression The compression type.
691: */
692: public void setCompression(int compression) {
693: //this.compression = compression;
694: // Check to see if compression supported
695: // Add Field
696: addField(XTIFF.TIFFTAG_COMPRESSION, XTIFFField.TIFF_SHORT, 1,
697: new char[] { (char) compression });
698: }
699:
700: /**
701: * Return the type of compression indicated in the
702: * TIFF fields, or XTIFF.COMPRESSION_NON if not
703: * specified.
704: */
705: public int getCompression() {
706: if (getField(XTIFF.TIFFTAG_COMPRESSION) == null)
707: return XTIFF.COMPRESSION_NONE;
708: return (int) getFieldAsLong(XTIFF.TIFFTAG_COMPRESSION);
709: }
710:
711: /**
712: * If set, the data will be written out in tiled format, instead of
713: * in strips.
714: *
715: * @param isTiled Specifies whether the image data should be
716: * wriiten out in tiled format.
717: */
718: public void setIsTiled(boolean isTiled) {
719: this ._isTiled = isTiled;
720: }
721:
722: /**
723: * Constructs a tile codec for decoding data, using the
724: * compression defined in the current directory.
725: * @param param the encoding param
726: * @see XTIFFTileCodec
727: */
728: public XTIFFTileCodec createTileCodec(XTIFFDecodeParam param)
729: throws IOException {
730: int compression = getCompression();
731: XTIFFTileCodec codec = getTileCodec(compression);
732: if (codec == null)
733: throw new IOException("Compression type (" + compression
734: + ") not supported");
735: return codec.create(param);
736: }
737:
738: /**
739: * Constructs a tile codec for encoding data, using the
740: * compression defined in the current directory.
741: * @param param the encoding param
742: * @see XTIFFTileCodec
743: */
744: public XTIFFTileCodec createTileCodec(XTIFFEncodeParam param)
745: throws IOException {
746: int compression = getCompression();
747: XTIFFTileCodec codec = getTileCodec(compression);
748: if (codec == null)
749: throw new IOException("Compression type (" + compression
750: + ") not supported");
751: return codec.create(param);
752: }
753:
754: /**
755: * Set the XTIFFFactory, which is used to
756: * construct the XTIFFDirectory object assigned as a
757: * "tiff.directory" property in the resulting jai image.
758: *
759: * @param fact the factory to register. The factory is
760: * guaranteed to always be non-null; if a null is passed
761: * in then the default XTIFFFactory is used.
762: * a null object is passed in
763: * @see XTIFFFactory
764: */
765: public static void setFactory(XTIFFFactory fact) {
766: if (fact == null)
767: factory = new XTIFFFactory();
768: else
769: factory = fact;
770: }
771:
772: /**
773: * Constructs a XTIFFDirectory from a SeekableStream.
774: * The directory parameter specifies which directory to read from
775: * the linked list present in the stream; directory 0 is normally
776: * read but it is possible to store multiple images in a single
777: * TIFF file by maintaing multiple directories.
778: *
779: * @param stream a SeekableStream to read from.
780: * @param directory the index of the directory to read.
781: * @see XTIFFFactory
782: */
783: public static XTIFFDirectory create(SeekableStream stream,
784: int directory) throws IOException {
785: return factory.createDirectory(stream, directory);
786: }
787:
788: /**
789: * Constructs a TIFFDirectory by reading a SeekableStream.
790: * The ifd_offset parameter specifies the stream offset from which
791: * to begin reading; this mechanism is sometimes used to store
792: * private IFDs within a TIFF file that are not part of the normal
793: * sequence of IFDs. Uses the XTIFFFactory to do this, so
794: * to extend the directory class, the factory method should be
795: * extended and registered instead of this one.
796: *
797: * @param stream a SeekableStream to read from.
798: * @param ifd_offset the long byte offset of the directory.
799: * @see XTIFFFactory
800: */
801: public static XTIFFDirectory create(SeekableStream stream,
802: long ifd_offset) throws IOException {
803: return factory.createDirectory(stream, ifd_offset);
804: }
805:
806: /**
807: * Constructs an XTIFFDirectory from the currently.
808: * registered XTIFFDirectory factory.
809: * @see XTIFFFactory
810: */
811: public static XTIFFDirectory create() {
812: return factory.createDirectory();
813: }
814:
815: /**
816: * Return the currently registered XTIFFTileCodec
817: * for this compression type. Used by the XTIFFImage
818: * to decode the compression data.
819: * @see XTIFFTileCodec
820: */
821: public static XTIFFTileCodec getTileCodec(int comp) {
822: return (XTIFFTileCodec) tileCodecs.get(new Integer(comp));
823: }
824:
825: /**
826: * UnRegister the XTIFFTileCodec corresponding to the
827: * TIFF compression type.
828: * @param comp The TIFF compression code indicated
829: */
830: public static void unRegisterTileCodec(int comp) {
831: XTIFFTileCodec cod = getTileCodec(comp);
832: tileCodecs.remove(cod);
833: }
834:
835: /**
836: * Register a new XTIFFTileCodec for encoding and decoding
837: * compressed TIFF image data. This overrides any existing
838: * codec previously registered.
839: * @param comp The TIFF compression code indicated by the
840: * @param codec The codec to register.
841: * XTIFF.TIFFTAG_COMPRESSION field.
842: * @see XTIFFTileCodec
843: */
844: public static void registerTileCodec(int comp, XTIFFTileCodec codec) {
845: tileCodecs.put(new Integer(comp), codec);
846: }
847:
848: /**
849: * Get the JAI Image decoded type. This method is
850: * called by the XTIFFTileCodeImpl object during the
851: * decode() method to determine what type of colorspace
852: * and sample model to use.
853: */
854: public int getImageType() {
855: return imageType;
856: }
857:
858: /**
859: * Set the JAI Image decoded type. This method is
860: * called by the XTIFFImage constructor to indicate
861: * to the XTIFFTileCodec what type of colorspace and
862: * sample model to use. The types are enumerated in
863: * the XTIFF class.
864: * @see XTIFF
865: * @see XTIFFImage
866: * @see XTIFFTileCodec
867: */
868: public void setImageType(int image_type) {
869: imageType = image_type;
870: }
871: }
|