Mercurial > projects > dwt-mac
comparison dwt/internal/image/TIFFModifiedHuffmanCodec.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | e831403a80a9 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:380af2bdd8e5 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2003 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 *******************************************************************************/ | |
11 module dwt.internal.image; | |
12 | |
13 import dwt.DWT; | |
14 | |
15 /* | |
16 * Decoder for | |
17 * - CCITT Group 3 1-Dimensional Modified Huffman run length encoding | |
18 * (TIFF compression type 2) | |
19 * - CCITT T.4 bi-level encoding 1D | |
20 * (TIFF compression type 3 option 1D) | |
21 */ | |
22 final class TIFFModifiedHuffmanCodec { | |
23 static final short[][][] BLACK_CODE = { | |
24 /* 2 bits */ | |
25 {{2, 3}, {3, 2}}, | |
26 /* 3 bits */ | |
27 {{2, 1}, {3, 4}}, | |
28 /* 4 bits */ | |
29 {{2, 6}, {3, 5}}, | |
30 /* 5 bits */ | |
31 {{3, 7}}, | |
32 /* 6 bits */ | |
33 {{4, 9}, {5, 8}}, | |
34 /* 7 bits */ | |
35 {{4, 10}, {5, 11}, {7, 12}}, | |
36 /* 8 bits */ | |
37 {{4, 13}, {7, 14}}, | |
38 /* 9 bits */ | |
39 {{24, 15}}, | |
40 /* 10 bits */ | |
41 {{8, 18}, {15, 64}, {23, 16}, {24, 17}, {55, 0}}, | |
42 /* 11 bits */ | |
43 {/* EOL */{0, -1}, {8, 1792}, {23, 24}, {24, 25}, {40, 23}, {55, 22}, {103, 19}, | |
44 {104, 20}, {108, 21}, {12, 1856}, {13, 1920}}, | |
45 /* 12 bits */ | |
46 {{18, 1984}, {19, 2048}, {20, 2112}, {21, 2176}, {22, 2240}, {23, 2304}, | |
47 {28, 2368}, {29, 2432}, {30, 2496}, {31, 2560}, {36, 52}, {39, 55}, {40, 56}, | |
48 {43, 59}, {44, 60}, {51, 320}, {52, 384}, {53, 448}, {55, 53}, {56, 54}, {82, 50}, | |
49 {83, 51}, {84, 44}, {85, 45}, {86, 46}, {87, 47}, {88, 57}, {89, 58}, {90, 61}, | |
50 {91, 256}, {100, 48}, {101, 49}, {102, 62}, {103, 63}, {104, 30}, {105, 31}, | |
51 {106, 32}, {107, 33}, {108, 40}, {109, 41}, {200, 128}, {201, 192}, {202, 26}, | |
52 {203, 27}, {204, 28}, {205, 29}, {210, 34}, {211, 35}, {212, 36}, {213, 37}, | |
53 {214, 38}, {215, 39}, {218, 42}, {219, 43}}, | |
54 /* 13 bits */ | |
55 {{74, 640}, {75, 704}, {76, 768}, {77, 832}, {82, 1280}, {83, 1344}, {84, 1408}, | |
56 {85, 1472}, {90, 1536}, {91, 1600}, {100, 1664}, {101, 1728}, {108, 512}, | |
57 {109, 576}, {114, 896}, {115, 960}, {116, 1024}, {117, 1088}, {118, 1152}, | |
58 {119, 1216}} | |
59 }; | |
60 | |
61 static final short[][][] WHITE_CODE = { | |
62 /* 4 bits */ | |
63 {{7, 2}, {8, 3}, {11, 4}, {12, 5}, {14, 6}, {15, 7}}, | |
64 /* 5 bits */ | |
65 {{7, 10}, {8, 11}, {18, 128}, {19, 8}, {20, 9}, {27, 64}}, | |
66 /* 6 bits */ | |
67 {{3, 13}, {7, 1}, {8, 12}, {23, 192}, {24, 1664}, {42, 16}, {43, 17}, {52, 14}, | |
68 {53, 15}}, | |
69 /* 7 bits */ | |
70 {{3, 22}, {4, 23}, {8, 20}, {12, 19}, {19, 26}, {23, 21}, {24, 28}, {36, 27}, | |
71 {39, 18}, {40, 24}, {43, 25}, {55, 256}}, | |
72 /* 8 bits */ | |
73 {{2, 29}, {3, 30}, {4, 45}, {5, 46}, {10, 47}, {11, 48}, {18, 33}, {19, 34}, | |
74 {20, 35}, {21, 36}, {22, 37}, {23, 38}, {26, 31}, {27, 32}, {36, 53}, {37, 54}, | |
75 {40, 39}, {41, 40}, {42, 41}, {43, 42}, {44, 43}, {45, 44}, {50, 61}, {51, 62}, | |
76 {52, 63}, {53, 0}, {54, 320}, {55, 384}, {74, 59}, {75, 60}, {82, 49}, {83, 50}, | |
77 {84, 51}, {85, 52}, {88, 55}, {89, 56}, {90, 57}, {91, 58}, {100, 448}, | |
78 {101, 512}, {103, 640}, {104, 576}}, | |
79 /* 9 bits */ | |
80 {{152, 1472}, {153, 1536}, {154, 1600}, {155, 1728}, {204, 704}, {205, 768}, | |
81 {210, 832}, {211, 896}, {212, 960}, {213, 1024}, {214, 1088}, {215, 1152}, | |
82 {216, 1216}, {217, 1280}, {218, 1344}, {219, 1408}}, | |
83 /* 10 bits */ | |
84 {}, | |
85 /* 11 bits */ | |
86 {{8, 1792}, {12, 1856}, {13, 1920}}, | |
87 /* 12 bits */ | |
88 {/* EOL */{1, -1}, {18, 1984}, {19, 2048}, {20, 2112}, {21, 2176}, {22, 2240}, {23, 2304}, | |
89 {28, 2368}, {29, 2432}, {30, 2496}, {31, 2560}} | |
90 }; | |
91 | |
92 static final int BLACK_MIN_BITS = 2; | |
93 static final int WHITE_MIN_BITS = 4; | |
94 | |
95 bool isWhite; | |
96 int whiteValue = 0; | |
97 int blackValue = 1; | |
98 byte[] src; | |
99 byte[] dest; | |
100 int byteOffsetSrc = 0; | |
101 int bitOffsetSrc = 0; | |
102 int byteOffsetDest = 0; | |
103 int bitOffsetDest = 0; | |
104 int code = 0; | |
105 int nbrBits = 0; | |
106 /* nbr of bytes per row */ | |
107 int rowSize; | |
108 | |
109 public int decode(byte[] src, byte[] dest, int offsetDest, int rowSize, int nRows) { | |
110 this.src = src; | |
111 this.dest = dest; | |
112 this.rowSize = rowSize; | |
113 byteOffsetSrc = 0; | |
114 bitOffsetSrc = 0; | |
115 byteOffsetDest = offsetDest; | |
116 bitOffsetDest = 0; | |
117 int cnt = 0; | |
118 while (cnt < nRows && decodeRow()) { | |
119 cnt++; | |
120 /* byte aligned */ | |
121 if (bitOffsetDest > 0) { | |
122 byteOffsetDest++; | |
123 bitOffsetDest = 0; | |
124 } | |
125 } | |
126 return byteOffsetDest - offsetDest; | |
127 } | |
128 | |
129 bool decodeRow() { | |
130 isWhite = true; | |
131 int n = 0; | |
132 while (n < rowSize) { | |
133 int runLength = decodeRunLength(); | |
134 if (runLength < 0) return false; | |
135 n += runLength; | |
136 setNextBits(isWhite ? whiteValue : blackValue, runLength); | |
137 isWhite = !isWhite; | |
138 } | |
139 return true; | |
140 } | |
141 | |
142 int decodeRunLength() { | |
143 int runLength = 0; | |
144 int partialRun = 0; | |
145 short[][][] huffmanCode = isWhite ? WHITE_CODE : BLACK_CODE; | |
146 while (true) { | |
147 bool found = false; | |
148 nbrBits = isWhite ? WHITE_MIN_BITS : BLACK_MIN_BITS; | |
149 code = getNextBits(nbrBits); | |
150 for (int i = 0; i < huffmanCode.length; i++) { | |
151 for (int j = 0; j < huffmanCode[i].length; j++) { | |
152 if (huffmanCode[i][j][0] is code) { | |
153 found = true; | |
154 partialRun = huffmanCode[i][j][1]; | |
155 if (partialRun is -1) { | |
156 /* Stop when reaching final EOL on last byte */ | |
157 if (byteOffsetSrc is src.length - 1) return -1; | |
158 /* Group 3 starts each row with an EOL - ignore it */ | |
159 } else { | |
160 runLength += partialRun; | |
161 if (partialRun < 64) return runLength; | |
162 } | |
163 break; | |
164 } | |
165 } | |
166 if (found) break; | |
167 code = code << 1 | getNextBit(); | |
168 } | |
169 if (!found) DWT.error(DWT.ERROR_INVALID_IMAGE); | |
170 } | |
171 } | |
172 | |
173 int getNextBit() { | |
174 int value = (src[byteOffsetSrc] >>> (7 - bitOffsetSrc)) & 0x1; | |
175 bitOffsetSrc++; | |
176 if (bitOffsetSrc > 7) { | |
177 byteOffsetSrc++; | |
178 bitOffsetSrc = 0; | |
179 } | |
180 return value; | |
181 } | |
182 | |
183 int getNextBits(int cnt) { | |
184 int value = 0; | |
185 for (int i = 0; i < cnt; i++) { | |
186 value = value << 1 | getNextBit(); | |
187 } | |
188 return value; | |
189 } | |
190 | |
191 void setNextBits(int value, int cnt) { | |
192 int n = cnt; | |
193 while (bitOffsetDest > 0 && bitOffsetDest <= 7 && n > 0) { | |
194 dest[byteOffsetDest] = value is 1 ? | |
195 (byte)(dest[byteOffsetDest] | (1 << (7 - bitOffsetDest))) : | |
196 (byte)(dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest))); | |
197 n--; | |
198 bitOffsetDest++; | |
199 } | |
200 if (bitOffsetDest is 8) { | |
201 byteOffsetDest++; | |
202 bitOffsetDest = 0; | |
203 } | |
204 while (n >= 8) { | |
205 dest[byteOffsetDest++] = (byte) (value is 1 ? 0xFF : 0); | |
206 n -= 8; | |
207 } | |
208 while (n > 0) { | |
209 dest[byteOffsetDest] = value is 1 ? | |
210 (byte)(dest[byteOffsetDest] | (1 << (7 - bitOffsetDest))) : | |
211 (byte)(dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest))); | |
212 n--; | |
213 bitOffsetDest++; | |
214 } | |
215 } | |
216 | |
217 } |