001: /*******************************************************************************
002: * Copyright (c) 2000, 2003 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.internal.image;
011:
012: import org.eclipse.swt.*;
013:
014: /*
015: * Decoder for
016: * - CCITT Group 3 1-Dimensional Modified Huffman run length encoding
017: * (TIFF compression type 2)
018: * - CCITT T.4 bi-level encoding 1D
019: * (TIFF compression type 3 option 1D)
020: */
021: final class TIFFModifiedHuffmanCodec {
022: static final short[][][] BLACK_CODE = {
023: /* 2 bits */
024: { { 2, 3 }, { 3, 2 } },
025: /* 3 bits */
026: { { 2, 1 }, { 3, 4 } },
027: /* 4 bits */
028: { { 2, 6 }, { 3, 5 } },
029: /* 5 bits */
030: { { 3, 7 } },
031: /* 6 bits */
032: { { 4, 9 }, { 5, 8 } },
033: /* 7 bits */
034: { { 4, 10 }, { 5, 11 }, { 7, 12 } },
035: /* 8 bits */
036: { { 4, 13 }, { 7, 14 } },
037: /* 9 bits */
038: { { 24, 15 } },
039: /* 10 bits */
040: { { 8, 18 }, { 15, 64 }, { 23, 16 }, { 24, 17 }, { 55, 0 } },
041: /* 11 bits */
042: {/* EOL */{ 0, -1 }, { 8, 1792 }, { 23, 24 }, { 24, 25 },
043: { 40, 23 }, { 55, 22 }, { 103, 19 }, { 104, 20 },
044: { 108, 21 }, { 12, 1856 }, { 13, 1920 } },
045: /* 12 bits */
046: { { 18, 1984 }, { 19, 2048 }, { 20, 2112 }, { 21, 2176 },
047: { 22, 2240 }, { 23, 2304 }, { 28, 2368 },
048: { 29, 2432 }, { 30, 2496 }, { 31, 2560 },
049: { 36, 52 }, { 39, 55 }, { 40, 56 }, { 43, 59 },
050: { 44, 60 }, { 51, 320 }, { 52, 384 }, { 53, 448 },
051: { 55, 53 }, { 56, 54 }, { 82, 50 }, { 83, 51 },
052: { 84, 44 }, { 85, 45 }, { 86, 46 }, { 87, 47 },
053: { 88, 57 }, { 89, 58 }, { 90, 61 }, { 91, 256 },
054: { 100, 48 }, { 101, 49 }, { 102, 62 }, { 103, 63 },
055: { 104, 30 }, { 105, 31 }, { 106, 32 }, { 107, 33 },
056: { 108, 40 }, { 109, 41 }, { 200, 128 },
057: { 201, 192 }, { 202, 26 }, { 203, 27 },
058: { 204, 28 }, { 205, 29 }, { 210, 34 }, { 211, 35 },
059: { 212, 36 }, { 213, 37 }, { 214, 38 }, { 215, 39 },
060: { 218, 42 }, { 219, 43 } },
061: /* 13 bits */
062: { { 74, 640 }, { 75, 704 }, { 76, 768 }, { 77, 832 },
063: { 82, 1280 }, { 83, 1344 }, { 84, 1408 },
064: { 85, 1472 }, { 90, 1536 }, { 91, 1600 },
065: { 100, 1664 }, { 101, 1728 }, { 108, 512 },
066: { 109, 576 }, { 114, 896 }, { 115, 960 },
067: { 116, 1024 }, { 117, 1088 }, { 118, 1152 },
068: { 119, 1216 } } };
069:
070: static final short[][][] WHITE_CODE = {
071: /* 4 bits */
072: { { 7, 2 }, { 8, 3 }, { 11, 4 }, { 12, 5 }, { 14, 6 },
073: { 15, 7 } },
074: /* 5 bits */
075: { { 7, 10 }, { 8, 11 }, { 18, 128 }, { 19, 8 }, { 20, 9 },
076: { 27, 64 } },
077: /* 6 bits */
078: { { 3, 13 }, { 7, 1 }, { 8, 12 }, { 23, 192 },
079: { 24, 1664 }, { 42, 16 }, { 43, 17 }, { 52, 14 },
080: { 53, 15 } },
081: /* 7 bits */
082: { { 3, 22 }, { 4, 23 }, { 8, 20 }, { 12, 19 }, { 19, 26 },
083: { 23, 21 }, { 24, 28 }, { 36, 27 }, { 39, 18 },
084: { 40, 24 }, { 43, 25 }, { 55, 256 } },
085: /* 8 bits */
086: { { 2, 29 }, { 3, 30 }, { 4, 45 }, { 5, 46 }, { 10, 47 },
087: { 11, 48 }, { 18, 33 }, { 19, 34 }, { 20, 35 },
088: { 21, 36 }, { 22, 37 }, { 23, 38 }, { 26, 31 },
089: { 27, 32 }, { 36, 53 }, { 37, 54 }, { 40, 39 },
090: { 41, 40 }, { 42, 41 }, { 43, 42 }, { 44, 43 },
091: { 45, 44 }, { 50, 61 }, { 51, 62 }, { 52, 63 },
092: { 53, 0 }, { 54, 320 }, { 55, 384 }, { 74, 59 },
093: { 75, 60 }, { 82, 49 }, { 83, 50 }, { 84, 51 },
094: { 85, 52 }, { 88, 55 }, { 89, 56 }, { 90, 57 },
095: { 91, 58 }, { 100, 448 }, { 101, 512 },
096: { 103, 640 }, { 104, 576 } },
097: /* 9 bits */
098: { { 152, 1472 }, { 153, 1536 }, { 154, 1600 },
099: { 155, 1728 }, { 204, 704 }, { 205, 768 },
100: { 210, 832 }, { 211, 896 }, { 212, 960 },
101: { 213, 1024 }, { 214, 1088 }, { 215, 1152 },
102: { 216, 1216 }, { 217, 1280 }, { 218, 1344 },
103: { 219, 1408 } },
104: /* 10 bits */
105: {},
106: /* 11 bits */
107: { { 8, 1792 }, { 12, 1856 }, { 13, 1920 } },
108: /* 12 bits */
109: {/* EOL */{ 1, -1 }, { 18, 1984 }, { 19, 2048 },
110: { 20, 2112 }, { 21, 2176 }, { 22, 2240 },
111: { 23, 2304 }, { 28, 2368 }, { 29, 2432 },
112: { 30, 2496 }, { 31, 2560 } } };
113:
114: static final int BLACK_MIN_BITS = 2;
115: static final int WHITE_MIN_BITS = 4;
116:
117: boolean isWhite;
118: int whiteValue = 0;
119: int blackValue = 1;
120: byte[] src;
121: byte[] dest;
122: int byteOffsetSrc = 0;
123: int bitOffsetSrc = 0;
124: int byteOffsetDest = 0;
125: int bitOffsetDest = 0;
126: int code = 0;
127: int nbrBits = 0;
128: /* nbr of bytes per row */
129: int rowSize;
130:
131: public int decode(byte[] src, byte[] dest, int offsetDest,
132: int rowSize, int nRows) {
133: this .src = src;
134: this .dest = dest;
135: this .rowSize = rowSize;
136: byteOffsetSrc = 0;
137: bitOffsetSrc = 0;
138: byteOffsetDest = offsetDest;
139: bitOffsetDest = 0;
140: int cnt = 0;
141: while (cnt < nRows && decodeRow()) {
142: cnt++;
143: /* byte aligned */
144: if (bitOffsetDest > 0) {
145: byteOffsetDest++;
146: bitOffsetDest = 0;
147: }
148: }
149: return byteOffsetDest - offsetDest;
150: }
151:
152: boolean decodeRow() {
153: isWhite = true;
154: int n = 0;
155: while (n < rowSize) {
156: int runLength = decodeRunLength();
157: if (runLength < 0)
158: return false;
159: n += runLength;
160: setNextBits(isWhite ? whiteValue : blackValue, runLength);
161: isWhite = !isWhite;
162: }
163: return true;
164: }
165:
166: int decodeRunLength() {
167: int runLength = 0;
168: int partialRun = 0;
169: short[][][] huffmanCode = isWhite ? WHITE_CODE : BLACK_CODE;
170: while (true) {
171: boolean found = false;
172: nbrBits = isWhite ? WHITE_MIN_BITS : BLACK_MIN_BITS;
173: code = getNextBits(nbrBits);
174: for (int i = 0; i < huffmanCode.length; i++) {
175: for (int j = 0; j < huffmanCode[i].length; j++) {
176: if (huffmanCode[i][j][0] == code) {
177: found = true;
178: partialRun = huffmanCode[i][j][1];
179: if (partialRun == -1) {
180: /* Stop when reaching final EOL on last byte */
181: if (byteOffsetSrc == src.length - 1)
182: return -1;
183: /* Group 3 starts each row with an EOL - ignore it */
184: } else {
185: runLength += partialRun;
186: if (partialRun < 64)
187: return runLength;
188: }
189: break;
190: }
191: }
192: if (found)
193: break;
194: code = code << 1 | getNextBit();
195: }
196: if (!found)
197: SWT.error(SWT.ERROR_INVALID_IMAGE);
198: }
199: }
200:
201: int getNextBit() {
202: int value = (src[byteOffsetSrc] >>> (7 - bitOffsetSrc)) & 0x1;
203: bitOffsetSrc++;
204: if (bitOffsetSrc > 7) {
205: byteOffsetSrc++;
206: bitOffsetSrc = 0;
207: }
208: return value;
209: }
210:
211: int getNextBits(int cnt) {
212: int value = 0;
213: for (int i = 0; i < cnt; i++) {
214: value = value << 1 | getNextBit();
215: }
216: return value;
217: }
218:
219: void setNextBits(int value, int cnt) {
220: int n = cnt;
221: while (bitOffsetDest > 0 && bitOffsetDest <= 7 && n > 0) {
222: dest[byteOffsetDest] = value == 1 ? (byte) (dest[byteOffsetDest] | (1 << (7 - bitOffsetDest)))
223: : (byte) (dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest)));
224: n--;
225: bitOffsetDest++;
226: }
227: if (bitOffsetDest == 8) {
228: byteOffsetDest++;
229: bitOffsetDest = 0;
230: }
231: while (n >= 8) {
232: dest[byteOffsetDest++] = (byte) (value == 1 ? 0xFF : 0);
233: n -= 8;
234: }
235: while (n > 0) {
236: dest[byteOffsetDest] = value == 1 ? (byte) (dest[byteOffsetDest] | (1 << (7 - bitOffsetDest)))
237: : (byte) (dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest)));
238: n--;
239: bitOffsetDest++;
240: }
241: }
242:
243: }
|