001: /*
002: * $RCSfile: TIFFEncodeParam.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.2 $
009: * $Date: 2005/11/14 22:44:06 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.codec;
013:
014: import java.awt.image.RenderedImage;
015: import java.util.Collections;
016: import java.util.Iterator;
017: import java.util.zip.Deflater;
018:
019: /**
020: * An instance of <code>ImageEncodeParam</code> for encoding images in
021: * the TIFF format.
022: *
023: * <p> This class allows for the specification of encoding parameters. By
024: * default, the image is encoded without any compression, and is written
025: * out consisting of strips, not tiles. The particular compression scheme
026: * to be used can be specified by using the <code>setCompression()</code>
027: * method. The compression scheme specified will be honored only if it is
028: * compatible with the type of image being written out. For example,
029: * Group3 and Group4 compressions can only be used with Bilevel images.
030: * Writing of tiled TIFF images can be enabled by calling the
031: * <code>setWriteTiled()</code> method.
032: *
033: * <p><b> This class is not a committed part of the JAI API. It may
034: * be removed or changed in future releases of JAI.</b>
035: *
036: */
037: public class TIFFEncodeParam implements ImageEncodeParam {
038:
039: /** No compression. */
040: public static final int COMPRESSION_NONE = 1;
041:
042: /** Byte-oriented run-length encoding "PackBits" compression. */
043: public static final int COMPRESSION_PACKBITS = 32773;
044:
045: /**
046: * Modified Huffman Compression (CCITT Run Length Encoding (RLE)).
047: */
048: public static final int COMPRESSION_GROUP3_1D = 2;
049:
050: /**
051: * CCITT T.4 bilevel compression (Group 3 facsimile compression).
052: */
053: public static final int COMPRESSION_GROUP3_2D = 3;
054:
055: /**
056: * CCITT T.6 bilevel compression (Group 4 facsimile compression).
057: */
058: public static final int COMPRESSION_GROUP4 = 4;
059:
060: /**
061: * LZW compression.
062: * <p><b>Not supported.</b>
063: */
064: public static final int COMPRESSION_LZW = 5;
065:
066: /**
067: * <a href="ftp://ftp.sgi.com/graphics/tiff/TTN2.draft.txt">
068: * JPEG-in-TIFF</a> compression.
069: */
070: public static final int COMPRESSION_JPEG_TTN2 = 7;
071:
072: /**
073: * <a href="http://info.internet.isi.edu:80/in-notes/rfc/files/rfc1951.txt">
074: * DEFLATE</a> lossless compression (also known as "Zip-in-TIFF").
075: */
076: public static final int COMPRESSION_DEFLATE = 32946;
077:
078: private int compression = COMPRESSION_NONE;
079:
080: private boolean reverseFillOrder = false;
081: private boolean T4Encode2D = true;
082: private boolean T4PadEOLs = false;
083:
084: private boolean writeTiled = false;
085: private int tileWidth;
086: private int tileHeight;
087:
088: private Iterator extraImages;
089:
090: private TIFFField[] extraFields;
091:
092: private boolean convertJPEGRGBToYCbCr = true;
093: private JPEGEncodeParam jpegEncodeParam = null;
094:
095: private int deflateLevel = Deflater.DEFAULT_COMPRESSION;
096:
097: private boolean isLittleEndian = false;
098:
099: /**
100: * Constructs a TIFFEncodeParam object with default values for
101: * all parameters.
102: */
103: public TIFFEncodeParam() {
104: }
105:
106: /**
107: * Returns the value of the compression parameter.
108: */
109: public int getCompression() {
110: return compression;
111: }
112:
113: /**
114: * Specifies the type of compression to be used. The compression type
115: * specified will be honored only if it is compatible with the image
116: * being written out. Currently only PackBits, JPEG, and DEFLATE
117: * compression schemes are supported.
118: *
119: * <p> If <code>compression</code> is set to any value but
120: * <code>COMPRESSION_NONE</code> and the <code>OutputStream</code>
121: * supplied to the <code>ImageEncoder</code> is not a
122: * <code>SeekableOutputStream</code>, then the encoder will use either
123: * a temporary file or a memory cache when compressing the data
124: * depending on whether the file system is accessible. Compression
125: * will therefore be more efficient if a <code>SeekableOutputStream</code>
126: * is supplied.
127: *
128: * @param compression The compression type.
129: * @throws IllegalArgumentException if <code>compression</code> is
130: * not one of the defined <code>COMPRESSION_*</code> constants.
131: */
132: public void setCompression(int compression) {
133:
134: switch (compression) {
135: case COMPRESSION_NONE:
136: case COMPRESSION_GROUP3_1D:
137: case COMPRESSION_GROUP3_2D:
138: case COMPRESSION_GROUP4:
139: case COMPRESSION_PACKBITS:
140: case COMPRESSION_JPEG_TTN2:
141: case COMPRESSION_DEFLATE:
142: // Do nothing.
143: break;
144: default:
145: throw new IllegalArgumentException(JaiI18N
146: .getString("TIFFEncodeParam0"));
147: }
148:
149: this .compression = compression;
150: }
151:
152: /**
153: * Returns value of flag indicating whether CCITT-compressed bilevel
154: * data should be filled in reverse order.
155: *
156: * @see #setReverseFillOrder
157: */
158: public boolean getReverseFillOrder() {
159: return reverseFillOrder;
160: }
161:
162: /**
163: * Set value of flag indicating whether CCITT-compressed bilevel
164: * data should be filled in reverse order. If <code>true</code>,
165: * pixels are arranged within a byte such that pixels with lower
166: * column values are stored in the lower order bits of the byte.
167: * Thus <code>true</code> corresponds to TIFF FillOrder value 2
168: * and <code>false</code> to TIFF FillOrder 1. The default
169: * value is <code>false</code>.
170: */
171: public void setReverseFillOrder(boolean reverseFillOrder) {
172: this .reverseFillOrder = reverseFillOrder;
173: }
174:
175: /**
176: * Returns value of flag indicating whether T4-compressed bilevel data
177: * should be two-dimensionally encoded.
178: *
179: * @see #setT4Encode2D
180: */
181: public boolean getT4Encode2D() {
182: return T4Encode2D;
183: }
184:
185: /**
186: * Set value of flag indicating whether T4-compressed bilevel data
187: * should be two-dimensionally encoded. If <code>true</code> the
188: * data are two-dimensionally encoded; if <code>false</code> they
189: * are one-dimensionally encoded. The default value is <code>true</code>.
190: */
191: public void setT4Encode2D(boolean T4Encode2D) {
192: this .T4Encode2D = T4Encode2D;
193: }
194:
195: /**
196: * Returns value of flag indicating whether T4-compressed bilevel data
197: * should have the embedded EOL bit sequences padded to byte alignment.
198: *
199: * @see #setT4PadEOLs
200: */
201: public boolean getT4PadEOLs() {
202: return T4PadEOLs;
203: }
204:
205: /**
206: * Sets value of flag indicating whether T4-compressed bilevel data
207: * should have the embedded EOL bit sequences padded to byte alignment.
208: * If <code>true</code>, zero-valued bits are prepended to each EOL
209: * bit sequence <code>0x001</code> such that the EOL is right-aligned
210: * on a byte boundary:
211: *
212: * <pre>
213: * xxxx-0000 0000-0001
214: * </pre>
215: *
216: * where "x" denotes a value which could be either data or a fill bit
217: * depending on the alignment of the data before the EOL. The default
218: * value is <code>false</code>.
219: */
220: public void setT4PadEOLs(boolean T4PadEOLs) {
221: this .T4PadEOLs = T4PadEOLs;
222: }
223:
224: /**
225: * Returns the value of the writeTiled parameter.
226: */
227: public boolean getWriteTiled() {
228: return writeTiled;
229: }
230:
231: /**
232: * If set, the data will be written out in tiled format, instead of
233: * in strips.
234: *
235: * @param writeTiled Specifies whether the image data should be
236: * wriiten out in tiled format.
237: */
238: public void setWriteTiled(boolean writeTiled) {
239: this .writeTiled = writeTiled;
240: }
241:
242: /**
243: * Sets the dimensions of the tiles to be written. If either
244: * value is non-positive, the encoder will use a default value.
245: *
246: * <p> If the data are being written as tiles, i.e.,
247: * <code>getWriteTiled()</code> returns <code>true</code>, then the
248: * default tile dimensions used by the encoder are those of the tiles
249: * of the image being encoded.
250: *
251: * <p> If the data are being written as strips, i.e.,
252: * <code>getWriteTiled()</code> returns <code>false</code>, the width
253: * of each strip is always the width of the image and the default
254: * number of rows per strip is 8.
255: *
256: * <p> If JPEG compession is being used, the dimensions of the strips or
257: * tiles may be modified to conform to the JPEG-in-TIFF specification.
258: *
259: * @param tileWidth The tile width; ignored if strips are used.
260: * @param tileHeight The tile height or number of rows per strip.
261: */
262: public void setTileSize(int tileWidth, int tileHeight) {
263: this .tileWidth = tileWidth;
264: this .tileHeight = tileHeight;
265: }
266:
267: /**
268: * Retrieves the tile width set via <code>setTileSize()</code>.
269: */
270: public int getTileWidth() {
271: return tileWidth;
272: }
273:
274: /**
275: * Retrieves the tile height set via <code>setTileSize()</code>.
276: */
277: public int getTileHeight() {
278: return tileHeight;
279: }
280:
281: /**
282: * Sets an <code>Iterator</code> of additional images to be written
283: * after the image passed as an argument to the <code>ImageEncoder</code>.
284: * The methods on the supplied <code>Iterator</code> must only be invoked
285: * by the <code>ImageEncoder</code> which will exhaust the available
286: * values unless an error occurs.
287: *
288: * <p> The value returned by an invocation of <code>next()</code> on the
289: * <code>Iterator</code> must return either a <code>RenderedImage</code>
290: * or an <code>Object[]</code> of length 2 wherein the element at index
291: * zero is a <code>RenderedImage</code> amd the other element is a
292: * <code>TIFFEncodeParam</code>. If no <code>TIFFEncodeParam</code> is
293: * supplied in this manner for an additional image, the parameters used
294: * to create the <code>ImageEncoder</code> will be used. The extra
295: * image <code>Iterator</code> set on any <code>TIFFEncodeParam</code>
296: * of an additional image will in all cases be ignored.
297: */
298: public synchronized void setExtraImages(Iterator extraImages) {
299: this .extraImages = extraImages;
300: }
301:
302: /**
303: * Returns the additional image <code>Iterator</code> specified via
304: * <code>setExtraImages()</code> or <code>null</code> if none was
305: * supplied or if a <code>null</code> value was supplied.
306: */
307: public synchronized Iterator getExtraImages() {
308: return extraImages;
309: }
310:
311: /**
312: * Sets the compression level for DEFLATE-compressed data which should
313: * either be <code>java.util.Deflater.DEFAULT_COMPRESSION</code> or a
314: * value in the range [1,9] where larger values indicate more compression.
315: * The default setting is <code>Deflater.DEFAULT_COMPRESSION</code>. This
316: * setting is ignored if the compression type is not DEFLATE.
317: *
318: * @throws IllegalArgumentException if <code>deflateLevel</code> is
319: * not in the range <code>[1, 9]</code> and is not
320: * {@link Deflater#DEFAULT_COMPRESSION}.
321: */
322: public void setDeflateLevel(int deflateLevel) {
323: if (deflateLevel < 1 && deflateLevel > 9
324: && deflateLevel != Deflater.DEFAULT_COMPRESSION) {
325: throw new IllegalArgumentException(JaiI18N
326: .getString("TIFFEncodeParam1"));
327: }
328:
329: this .deflateLevel = deflateLevel;
330: }
331:
332: /**
333: * Gets the compression level for DEFLATE compression.
334: */
335: public int getDeflateLevel() {
336: return deflateLevel;
337: }
338:
339: /**
340: * Sets flag indicating whether to convert RGB data to YCbCr when the
341: * compression type is JPEG. The default value is <code>true</code>.
342: * This flag is ignored if the compression type is not JPEG.
343: */
344: public void setJPEGCompressRGBToYCbCr(boolean convertJPEGRGBToYCbCr) {
345: this .convertJPEGRGBToYCbCr = convertJPEGRGBToYCbCr;
346: }
347:
348: /**
349: * Whether RGB data will be converted to YCbCr when using JPEG compression.
350: */
351: public boolean getJPEGCompressRGBToYCbCr() {
352: return convertJPEGRGBToYCbCr;
353: }
354:
355: /**
356: * Sets the JPEG compression parameters. These parameters are ignored
357: * if the compression type is not JPEG. The argument may be
358: * <code>null</code> to indicate that default compression parameters
359: * are to be used. For maximum conformance with the specification it
360: * is recommended in most cases that only the quality compression
361: * parameter be set.
362: *
363: * <p> The <code>writeTablesOnly</code> and <code>JFIFHeader</code>
364: * flags of the <code>JPEGEncodeParam</code> are ignored. The
365: * <code>writeImageOnly</code> flag is used to determine whether the
366: * JPEGTables field will be written to the TIFF stream: if
367: * <code>writeImageOnly</code> is <code>true</code>, then the JPEGTables
368: * field will be written and will contain a valid JPEG abbreviated
369: * table specification datastream. In this case the data in each data
370: * segment (strip or tile) will contain an abbreviated JPEG image
371: * datastream. If the <code>writeImageOnly</code> flag is
372: * <code>false</code>, then the JPEGTables field will not be written and
373: * each data segment will contain a complete JPEG interchange datastream.
374: */
375: public void setJPEGEncodeParam(JPEGEncodeParam jpegEncodeParam) {
376: if (jpegEncodeParam != null) {
377: jpegEncodeParam = (JPEGEncodeParam) jpegEncodeParam.clone();
378: jpegEncodeParam.setWriteTablesOnly(false);
379: jpegEncodeParam.setWriteJFIFHeader(false);
380: }
381: this .jpegEncodeParam = jpegEncodeParam;
382: }
383:
384: /**
385: * Retrieves the JPEG compression parameters.
386: */
387: public JPEGEncodeParam getJPEGEncodeParam() {
388: if (jpegEncodeParam == null) {
389: jpegEncodeParam = new JPEGEncodeParam();
390: jpegEncodeParam.setWriteTablesOnly(false);
391: jpegEncodeParam.setWriteImageOnly(true);
392: jpegEncodeParam.setWriteJFIFHeader(false);
393: }
394: return jpegEncodeParam;
395: }
396:
397: /**
398: * Sets an array of extra fields to be written to the TIFF Image File
399: * Directory (IFD). Fields with tags equal to the tag of any
400: * automatically generated fields are ignored. No error checking is
401: * performed with respect to the validity of the field contents or
402: * the appropriateness of the field for the image being encoded.
403: *
404: * @param extraFields An array of extra fields; the parameter is
405: * copied by reference.
406: */
407: public void setExtraFields(TIFFField[] extraFields) {
408: this .extraFields = extraFields;
409: }
410:
411: /**
412: * Returns the value set by <code>setExtraFields()</code>.
413: */
414: public TIFFField[] getExtraFields() {
415: return extraFields;
416: }
417:
418: /**
419: * Sets a flag indicating whether the byte order used to write the
420: * output stream is <i>little endian</i>. If <code>true</code>
421: * multi-byte data units such as 16-bit and 32-bit integers and 32-bit
422: * floating point values are written from the least to the most
423: * significant byte; if <code>false</code> the order is from most to
424: * least significant byte. The default value is <code>false</code>.
425: */
426: public void setLittleEndian(boolean isLittleEndian) {
427: this .isLittleEndian = isLittleEndian;
428: }
429:
430: /**
431: * Returns the value of the flag indicating whether the output stream
432: * byte order is little endian.
433: */
434: public boolean getLittleEndian() {
435: return this.isLittleEndian;
436: }
437: }
|