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