001: /*
002: * $RCSfile: TIFFT6Compressor.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.3 $
042: * $Date: 2006/04/11 22:10:37 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageioimpl.plugins.tiff;
046:
047: import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
048: import com.sun.media.imageio.plugins.tiff.TIFFCompressor;
049: import com.sun.media.imageio.plugins.tiff.TIFFField;
050: import com.sun.media.imageio.plugins.tiff.TIFFTag;
051: import java.io.IOException;
052: import javax.imageio.IIOException;
053:
054: /**
055: *
056: */
057: public class TIFFT6Compressor extends TIFFFaxCompressor {
058:
059: public TIFFT6Compressor() {
060: super ("CCITT T.6", BaselineTIFFTagSet.COMPRESSION_CCITT_T_6,
061: true);
062: }
063:
064: /**
065: * Encode a buffer of data using CCITT T.6 Compression also known as
066: * Group 4 facsimile compression.
067: *
068: * @param data The row of data to compress.
069: * @param lineStride Byte step between the same sample in different rows.
070: * @param colOffset Bit offset within first <code>data[rowOffset]</code>.
071: * @param width Number of bits in the row.
072: * @param height Number of rows in the buffer.
073: * @param compData The compressed data.
074: *
075: * @return The number of bytes saved in the compressed data array.
076: */
077: public synchronized int encodeT6(byte[] data, int lineStride,
078: int colOffset, int width, int height, byte[] compData) {
079: //
080: // ao, a1, a2 are bit indices in the current line
081: // b1 and b2 are bit indices in the reference line (line above)
082: // color is the current color (WHITE or BLACK)
083: //
084: byte[] refData = null;
085: int refAddr = 0;
086: int lineAddr = 0;
087: int outIndex = 0;
088:
089: initBitBuf();
090:
091: //
092: // Iterate over all lines
093: //
094: while (height-- != 0) {
095: int a0 = colOffset;
096: int last = a0 + width;
097:
098: int testbit = ((data[lineAddr + (a0 >>> 3)] & 0xff) >>> (7 - (a0 & 0x7))) & 0x1;
099: int a1 = testbit != 0 ? a0 : nextState(data, lineAddr, a0,
100: last);
101:
102: testbit = refData == null ? 0 : ((refData[refAddr
103: + (a0 >>> 3)] & 0xff) >>> (7 - (a0 & 0x7))) & 0x1;
104: int b1 = testbit != 0 ? a0 : nextState(refData, refAddr,
105: a0, last);
106:
107: //
108: // The current color is set to WHITE at line start
109: //
110: int color = WHITE;
111:
112: while (true) {
113: int b2 = nextState(refData, refAddr, b1, last);
114: if (b2 < a1) { // pass mode
115: outIndex += add2DBits(compData, outIndex, pass, 0);
116: a0 = b2;
117: } else {
118: int tmp = b1 - a1 + 3;
119: if ((tmp <= 6) && (tmp >= 0)) { // vertical mode
120: outIndex += add2DBits(compData, outIndex, vert,
121: tmp);
122: a0 = a1;
123: } else { // horizontal mode
124: int a2 = nextState(data, lineAddr, a1, last);
125: outIndex += add2DBits(compData, outIndex, horz,
126: 0);
127: outIndex += add1DBits(compData, outIndex, a1
128: - a0, color);
129: outIndex += add1DBits(compData, outIndex, a2
130: - a1, color ^ 1);
131: a0 = a2;
132: }
133: }
134: if (a0 >= last) {
135: break;
136: }
137: color = ((data[lineAddr + (a0 >>> 3)] & 0xff) >>> (7 - (a0 & 0x7))) & 0x1;
138: a1 = nextState(data, lineAddr, a0, last);
139: b1 = nextState(refData, refAddr, a0, last);
140: testbit = refData == null ? 0
141: : ((refData[refAddr + (b1 >>> 3)] & 0xff) >>> (7 - (b1 & 0x7))) & 0x1;
142: if (testbit == color) {
143: b1 = nextState(refData, refAddr, b1, last);
144: }
145: }
146:
147: refData = data;
148: refAddr = lineAddr;
149: lineAddr += lineStride;
150:
151: } // End while(height--)
152:
153: //
154: // append eofb
155: //
156: outIndex += addEOFB(compData, outIndex);
157:
158: // Flip the bytes if inverse fill was requested.
159: if (inverseFill) {
160: for (int i = 0; i < outIndex; i++) {
161: compData[i] = TIFFFaxDecompressor.flipTable[compData[i] & 0xff];
162: }
163: }
164:
165: return outIndex;
166: }
167:
168: public int encode(byte[] b, int off, int width, int height,
169: int[] bitsPerSample, int scanlineStride) throws IOException {
170: if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) {
171: throw new IIOException(
172: "Bits per sample must be 1 for T6 compression!");
173: }
174:
175: if (metadata instanceof TIFFImageMetadata) {
176: TIFFImageMetadata tim = (TIFFImageMetadata) metadata;
177:
178: long[] options = new long[1];
179: options[0] = 0;
180:
181: BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
182: TIFFField T6Options = new TIFFField(base
183: .getTag(BaselineTIFFTagSet.TAG_T6_OPTIONS),
184: TIFFTag.TIFF_LONG, 1, options);
185: tim.rootIFD.addTIFFField(T6Options);
186: }
187:
188: // See comment in TIFFT4Compressor
189: int maxBits = 9 * ((width + 1) / 2) + 2;
190: int bufSize = (maxBits + 7) / 8;
191: bufSize = height * (bufSize + 2) + 12;
192:
193: byte[] compData = new byte[bufSize];
194: int bytes = encodeT6(b, scanlineStride, 8 * off, width, height,
195: compData);
196: stream.write(compData, 0, bytes);
197: return bytes;
198: }
199: }
|