Update ooo320-m1
[ooovba.git] / goodies / source / filter.vcl / itiff / ccidecom.cxx
blobb49837e8e9d12105dd1c9d7e9c0e4e74e52297a3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ccidecom.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
34 #include "ccidecom.hxx"
36 //=============================== Huffman-Tabellen ========================
38 //---------------------------- White-Run ------------------------------
40 #define CCIWhiteTableSize 105
42 const CCIHuffmanTableEntry CCIWhiteTable[CCIWhiteTableSize]={
43 { 0, 0x0035, 8 },
44 { 1, 0x0007, 6 },
45 { 2, 0x0007, 4 },
46 { 3, 0x0008, 4 },
47 { 4, 0x000b, 4 },
48 { 5, 0x000c, 4 },
49 { 6, 0x000e, 4 },
50 { 7, 0x000f, 4 },
51 { 8, 0x0013, 5 },
52 { 9, 0x0014, 5 },
53 { 10, 0x0007, 5 },
54 { 11, 0x0008, 5 },
55 { 12, 0x0008, 6 },
56 { 13, 0x0003, 6 },
57 { 14, 0x0034, 6 },
58 { 15, 0x0035, 6 },
59 { 16, 0x002a, 6 },
60 { 17, 0x002b, 6 },
61 { 18, 0x0027, 7 },
62 { 19, 0x000c, 7 },
63 { 20, 0x0008, 7 },
64 { 21, 0x0017, 7 },
65 { 22, 0x0003, 7 },
66 { 23, 0x0004, 7 },
67 { 24, 0x0028, 7 },
68 { 25, 0x002b, 7 },
69 { 26, 0x0013, 7 },
70 { 27, 0x0024, 7 },
71 { 28, 0x0018, 7 },
72 { 29, 0x0002, 8 },
73 { 30, 0x0003, 8 },
74 { 31, 0x001a, 8 },
75 { 32, 0x001b, 8 },
76 { 33, 0x0012, 8 },
77 { 34, 0x0013, 8 },
78 { 35, 0x0014, 8 },
79 { 36, 0x0015, 8 },
80 { 37, 0x0016, 8 },
81 { 38, 0x0017, 8 },
82 { 39, 0x0028, 8 },
83 { 40, 0x0029, 8 },
84 { 41, 0x002a, 8 },
85 { 42, 0x002b, 8 },
86 { 43, 0x002c, 8 },
87 { 44, 0x002d, 8 },
88 { 45, 0x0004, 8 },
89 { 46, 0x0005, 8 },
90 { 47, 0x000a, 8 },
91 { 48, 0x000b, 8 },
92 { 49, 0x0052, 8 },
93 { 50, 0x0053, 8 },
94 { 51, 0x0054, 8 },
95 { 52, 0x0055, 8 },
96 { 53, 0x0024, 8 },
97 { 54, 0x0025, 8 },
98 { 55, 0x0058, 8 },
99 { 56, 0x0059, 8 },
100 { 57, 0x005a, 8 },
101 { 58, 0x005b, 8 },
102 { 59, 0x004a, 8 },
103 { 60, 0x004b, 8 },
104 { 61, 0x0032, 8 },
105 { 62, 0x0033, 8 },
106 { 63, 0x0034, 8 },
107 { 64, 0x001b, 5 },
108 { 128, 0x0012, 5 },
109 { 192, 0x0017, 6 },
110 { 256, 0x0037, 7 },
111 { 320, 0x0036, 8 },
112 { 384, 0x0037, 8 },
113 { 448, 0x0064, 8 },
114 { 512, 0x0065, 8 },
115 { 576, 0x0068, 8 },
116 { 640, 0x0067, 8 },
117 { 704, 0x00cc, 9 },
118 { 768, 0x00cd, 9 },
119 { 832, 0x00d2, 9 },
120 { 896, 0x00d3, 9 },
121 { 960, 0x00d4, 9 },
122 { 1024, 0x00d5, 9 },
123 { 1088, 0x00d6, 9 },
124 { 1152, 0x00d7, 9 },
125 { 1216, 0x00d8, 9 },
126 { 1280, 0x00d9, 9 },
127 { 1344, 0x00da, 9 },
128 { 1408, 0x00db, 9 },
129 { 1472, 0x0098, 9 },
130 { 1536, 0x0099, 9 },
131 { 1600, 0x009a, 9 },
132 { 1664, 0x0018, 6 },
133 { 1728, 0x009b, 9 },
134 { 1792, 0x0008, 11 },
135 { 1856, 0x000c, 11 },
136 { 1920, 0x000d, 11 },
137 { 1984, 0x0012, 12 },
138 { 2048, 0x0013, 12 },
139 { 2112, 0x0014, 12 },
140 { 2176, 0x0015, 12 },
141 { 2240, 0x0016, 12 },
142 { 2304, 0x0017, 12 },
143 { 2368, 0x001c, 12 },
144 { 2432, 0x001d, 12 },
145 { 2496, 0x001e, 12 },
146 { 2560, 0x001f, 12 },
147 { 9999, 0x0001, 12 } // EOL
150 //---------------------------- Black-Run ------------------------------
152 #define CCIBlackTableSize 105
154 const CCIHuffmanTableEntry CCIBlackTable[CCIBlackTableSize]={
155 { 0, 0x0037, 10 },
156 { 1, 0x0002, 3 },
157 { 2, 0x0003, 2 },
158 { 3, 0x0002, 2 },
159 { 4, 0x0003, 3 },
160 { 5, 0x0003, 4 },
161 { 6, 0x0002, 4 },
162 { 7, 0x0003, 5 },
163 { 8, 0x0005, 6 },
164 { 9, 0x0004, 6 },
165 { 10, 0x0004, 7 },
166 { 11, 0x0005, 7 },
167 { 12, 0x0007, 7 },
168 { 13, 0x0004, 8 },
169 { 14, 0x0007, 8 },
170 { 15, 0x0018, 9 },
171 { 16, 0x0017, 10 },
172 { 17, 0x0018, 10 },
173 { 18, 0x0008, 10 },
174 { 19, 0x0067, 11 },
175 { 20, 0x0068, 11 },
176 { 21, 0x006c, 11 },
177 { 22, 0x0037, 11 },
178 { 23, 0x0028, 11 },
179 { 24, 0x0017, 11 },
180 { 25, 0x0018, 11 },
181 { 26, 0x00ca, 12 },
182 { 27, 0x00cb, 12 },
183 { 28, 0x00cc, 12 },
184 { 29, 0x00cd, 12 },
185 { 30, 0x0068, 12 },
186 { 31, 0x0069, 12 },
187 { 32, 0x006a, 12 },
188 { 33, 0x006b, 12 },
189 { 34, 0x00d2, 12 },
190 { 35, 0x00d3, 12 },
191 { 36, 0x00d4, 12 },
192 { 37, 0x00d5, 12 },
193 { 38, 0x00d6, 12 },
194 { 39, 0x00d7, 12 },
195 { 40, 0x006c, 12 },
196 { 41, 0x006d, 12 },
197 { 42, 0x00da, 12 },
198 { 43, 0x00db, 12 },
199 { 44, 0x0054, 12 },
200 { 45, 0x0055, 12 },
201 { 46, 0x0056, 12 },
202 { 47, 0x0057, 12 },
203 { 48, 0x0064, 12 },
204 { 49, 0x0065, 12 },
205 { 50, 0x0052, 12 },
206 { 51, 0x0053, 12 },
207 { 52, 0x0024, 12 },
208 { 53, 0x0037, 12 },
209 { 54, 0x0038, 12 },
210 { 55, 0x0027, 12 },
211 { 56, 0x0028, 12 },
212 { 57, 0x0058, 12 },
213 { 58, 0x0059, 12 },
214 { 59, 0x002b, 12 },
215 { 60, 0x002c, 12 },
216 { 61, 0x005a, 12 },
217 { 62, 0x0066, 12 },
218 { 63, 0x0067, 12 },
219 { 64, 0x000f, 10 },
220 { 128, 0x00c8, 12 },
221 { 192, 0x00c9, 12 },
222 { 256, 0x005b, 12 },
223 { 320, 0x0033, 12 },
224 { 384, 0x0034, 12 },
225 { 448, 0x0035, 12 },
226 { 512, 0x006c, 13 },
227 { 576, 0x006d, 13 },
228 { 640, 0x004a, 13 },
229 { 704, 0x004b, 13 },
230 { 768, 0x004c, 13 },
231 { 832, 0x004d, 13 },
232 { 896, 0x0072, 13 },
233 { 960, 0x0073, 13 },
234 { 1024, 0x0074, 13 },
235 { 1088, 0x0075, 13 },
236 { 1152, 0x0076, 13 },
237 { 1216, 0x0077, 13 },
238 { 1280, 0x0052, 13 },
239 { 1344, 0x0053, 13 },
240 { 1408, 0x0054, 13 },
241 { 1472, 0x0055, 13 },
242 { 1536, 0x005a, 13 },
243 { 1600, 0x005b, 13 },
244 { 1664, 0x0064, 13 },
245 { 1728, 0x0065, 13 },
246 { 1792, 0x0008, 11 },
247 { 1856, 0x000c, 11 },
248 { 1920, 0x000d, 11 },
249 { 1984, 0x0012, 12 },
250 { 2048, 0x0013, 12 },
251 { 2112, 0x0014, 12 },
252 { 2176, 0x0015, 12 },
253 { 2240, 0x0016, 12 },
254 { 2304, 0x0017, 12 },
255 { 2368, 0x001c, 12 },
256 { 2432, 0x001d, 12 },
257 { 2496, 0x001e, 12 },
258 { 2560, 0x001f, 12 },
259 { 9999, 0x0001, 12 } // EOL
263 //---------------------------- 2D-Mode --------------------------------
265 #define CCI2DMODE_UNCOMP 0
266 #define CCI2DMODE_PASS 1
267 #define CCI2DMODE_HORZ 2
268 #define CCI2DMODE_VERT_L3 3
269 #define CCI2DMODE_VERT_L2 4
270 #define CCI2DMODE_VERT_L1 5
271 #define CCI2DMODE_VERT_0 6
272 #define CCI2DMODE_VERT_R1 7
273 #define CCI2DMODE_VERT_R2 8
274 #define CCI2DMODE_VERT_R3 9
276 #define CCI2DModeTableSize 10
278 const CCIHuffmanTableEntry CCI2DModeTable[CCI2DModeTableSize]={
279 { CCI2DMODE_UNCOMP , 0x000f, 10 },
280 { CCI2DMODE_PASS , 0x0001, 4 },
281 { CCI2DMODE_HORZ , 0x0001, 3 },
282 { CCI2DMODE_VERT_L3, 0x0002, 7 },
283 { CCI2DMODE_VERT_L2, 0x0002, 6 },
284 { CCI2DMODE_VERT_L1, 0x0002, 3 },
285 { CCI2DMODE_VERT_0 , 0x0001, 1 },
286 { CCI2DMODE_VERT_R1, 0x0003, 3 },
287 { CCI2DMODE_VERT_R2, 0x0003, 6 },
288 { CCI2DMODE_VERT_R3, 0x0003, 7 }
292 //-------------------------- 2D-Uncompressed-Mode ----------------------
294 #define CCIUNCOMP_0White_1Black 0
295 #define CCIUNCOMP_1White_1Black 1
296 #define CCIUNCOMP_2White_1Black 2
297 #define CCIUNCOMP_3White_1Black 3
298 #define CCIUNCOMP_4White_1Black 4
299 #define CCIUNCOMP_5White 5
300 #define CCIUNCOMP_0White_End 6
301 #define CCIUNCOMP_1White_End 7
302 #define CCIUNCOMP_2White_End 8
303 #define CCIUNCOMP_3White_End 9
304 #define CCIUNCOMP_4White_End 10
306 #define CCIUncompTableSize 11
308 const CCIHuffmanTableEntry CCIUncompTable[CCIUncompTableSize]={
309 { CCIUNCOMP_0White_1Black, 0x0001, 1 },
310 { CCIUNCOMP_1White_1Black, 0x0001, 2 },
311 { CCIUNCOMP_2White_1Black, 0x0001, 3 },
312 { CCIUNCOMP_3White_1Black, 0x0001, 4 },
313 { CCIUNCOMP_4White_1Black, 0x0001, 5 },
314 { CCIUNCOMP_5White , 0x0001, 6 },
315 { CCIUNCOMP_0White_End , 0x0001, 7 },
316 { CCIUNCOMP_1White_End , 0x0001, 8 },
317 { CCIUNCOMP_2White_End , 0x0001, 9 },
318 { CCIUNCOMP_3White_End , 0x0001, 10 },
319 { CCIUNCOMP_4White_End , 0x0001, 11 }
323 //================== Sicherheitskopie der Huffman-Tabellen ================
324 // Um sicher zugehen, dass die Huffman-Tabellen keine Fehler enthalten,
325 // wurden sie zweimal von unterschiedlichen Quellen eingegeben (Uff) und
326 // verglichen.
327 // Da sich aber im Laufe der Pflege des Source-Codes mal ein Fehler
328 // einschleichen koennte (z.B. versehentlicher druck einer Taste im Editor)
329 // werden die Tablellen hier weiterhin zweimal aufgefuehrt und zur Laufzeit
330 // verglichen. (Wenn der Vergleich fehlschlaegt, liefert CCIDecompressor
331 // immer einen Fehler). Das Ganze mag etwas wahnsinnig erscheinen, aber ein Fehler
332 // in den Tabellen waere sonst sehr sehr schwer zu erkennen, zumal es
333 // unwahrscheinlich ist, dass eine oder mehere Beispieldateien alle Codes
334 // durchlaufen.
336 const CCIHuffmanTableEntry CCIWhiteTableSave[CCIWhiteTableSize]={
337 { 0, 0x0035, 8 },
338 { 1, 0x0007, 6 },
339 { 2, 0x0007, 4 },
340 { 3, 0x0008, 4 },
341 { 4, 0x000b, 4 },
342 { 5, 0x000c, 4 },
343 { 6, 0x000e, 4 },
344 { 7, 0x000f, 4 },
345 { 8, 0x0013, 5 },
346 { 9, 0x0014, 5 },
347 { 10, 0x0007, 5 },
348 { 11, 0x0008, 5 },
349 { 12, 0x0008, 6 },
350 { 13, 0x0003, 6 },
351 { 14, 0x0034, 6 },
352 { 15, 0x0035, 6 },
353 { 16, 0x002a, 6 },
354 { 17, 0x002b, 6 },
355 { 18, 0x0027, 7 },
356 { 19, 0x000c, 7 },
357 { 20, 0x0008, 7 },
358 { 21, 0x0017, 7 },
359 { 22, 0x0003, 7 },
360 { 23, 0x0004, 7 },
361 { 24, 0x0028, 7 },
362 { 25, 0x002b, 7 },
363 { 26, 0x0013, 7 },
364 { 27, 0x0024, 7 },
365 { 28, 0x0018, 7 },
366 { 29, 0x0002, 8 },
367 { 30, 0x0003, 8 },
368 { 31, 0x001a, 8 },
369 { 32, 0x001b, 8 },
370 { 33, 0x0012, 8 },
371 { 34, 0x0013, 8 },
372 { 35, 0x0014, 8 },
373 { 36, 0x0015, 8 },
374 { 37, 0x0016, 8 },
375 { 38, 0x0017, 8 },
376 { 39, 0x0028, 8 },
377 { 40, 0x0029, 8 },
378 { 41, 0x002a, 8 },
379 { 42, 0x002b, 8 },
380 { 43, 0x002c, 8 },
381 { 44, 0x002d, 8 },
382 { 45, 0x0004, 8 },
383 { 46, 0x0005, 8 },
384 { 47, 0x000a, 8 },
385 { 48, 0x000b, 8 },
386 { 49, 0x0052, 8 },
387 { 50, 0x0053, 8 },
388 { 51, 0x0054, 8 },
389 { 52, 0x0055, 8 },
390 { 53, 0x0024, 8 },
391 { 54, 0x0025, 8 },
392 { 55, 0x0058, 8 },
393 { 56, 0x0059, 8 },
394 { 57, 0x005a, 8 },
395 { 58, 0x005b, 8 },
396 { 59, 0x004a, 8 },
397 { 60, 0x004b, 8 },
398 { 61, 0x0032, 8 },
399 { 62, 0x0033, 8 },
400 { 63, 0x0034, 8 },
401 { 64, 0x001b, 5 },
402 { 128, 0x0012, 5 },
403 { 192, 0x0017, 6 },
404 { 256, 0x0037, 7 },
405 { 320, 0x0036, 8 },
406 { 384, 0x0037, 8 },
407 { 448, 0x0064, 8 },
408 { 512, 0x0065, 8 },
409 { 576, 0x0068, 8 },
410 { 640, 0x0067, 8 },
411 { 704, 0x00cc, 9 },
412 { 768, 0x00cd, 9 },
413 { 832, 0x00d2, 9 },
414 { 896, 0x00d3, 9 },
415 { 960, 0x00d4, 9 },
416 { 1024, 0x00d5, 9 },
417 { 1088, 0x00d6, 9 },
418 { 1152, 0x00d7, 9 },
419 { 1216, 0x00d8, 9 },
420 { 1280, 0x00d9, 9 },
421 { 1344, 0x00da, 9 },
422 { 1408, 0x00db, 9 },
423 { 1472, 0x0098, 9 },
424 { 1536, 0x0099, 9 },
425 { 1600, 0x009a, 9 },
426 { 1664, 0x0018, 6 },
427 { 1728, 0x009b, 9 },
428 { 1792, 0x0008, 11 },
429 { 1856, 0x000c, 11 },
430 { 1920, 0x000d, 11 },
431 { 1984, 0x0012, 12 },
432 { 2048, 0x0013, 12 },
433 { 2112, 0x0014, 12 },
434 { 2176, 0x0015, 12 },
435 { 2240, 0x0016, 12 },
436 { 2304, 0x0017, 12 },
437 { 2368, 0x001c, 12 },
438 { 2432, 0x001d, 12 },
439 { 2496, 0x001e, 12 },
440 { 2560, 0x001f, 12 },
441 { 9999, 0x0001, 12 } // EOL
444 const CCIHuffmanTableEntry CCIBlackTableSave[CCIBlackTableSize]={
445 { 0, 0x0037, 10 },
446 { 1, 0x0002, 3 },
447 { 2, 0x0003, 2 },
448 { 3, 0x0002, 2 },
449 { 4, 0x0003, 3 },
450 { 5, 0x0003, 4 },
451 { 6, 0x0002, 4 },
452 { 7, 0x0003, 5 },
453 { 8, 0x0005, 6 },
454 { 9, 0x0004, 6 },
455 { 10, 0x0004, 7 },
456 { 11, 0x0005, 7 },
457 { 12, 0x0007, 7 },
458 { 13, 0x0004, 8 },
459 { 14, 0x0007, 8 },
460 { 15, 0x0018, 9 },
461 { 16, 0x0017, 10 },
462 { 17, 0x0018, 10 },
463 { 18, 0x0008, 10 },
464 { 19, 0x0067, 11 },
465 { 20, 0x0068, 11 },
466 { 21, 0x006c, 11 },
467 { 22, 0x0037, 11 },
468 { 23, 0x0028, 11 },
469 { 24, 0x0017, 11 },
470 { 25, 0x0018, 11 },
471 { 26, 0x00ca, 12 },
472 { 27, 0x00cb, 12 },
473 { 28, 0x00cc, 12 },
474 { 29, 0x00cd, 12 },
475 { 30, 0x0068, 12 },
476 { 31, 0x0069, 12 },
477 { 32, 0x006a, 12 },
478 { 33, 0x006b, 12 },
479 { 34, 0x00d2, 12 },
480 { 35, 0x00d3, 12 },
481 { 36, 0x00d4, 12 },
482 { 37, 0x00d5, 12 },
483 { 38, 0x00d6, 12 },
484 { 39, 0x00d7, 12 },
485 { 40, 0x006c, 12 },
486 { 41, 0x006d, 12 },
487 { 42, 0x00da, 12 },
488 { 43, 0x00db, 12 },
489 { 44, 0x0054, 12 },
490 { 45, 0x0055, 12 },
491 { 46, 0x0056, 12 },
492 { 47, 0x0057, 12 },
493 { 48, 0x0064, 12 },
494 { 49, 0x0065, 12 },
495 { 50, 0x0052, 12 },
496 { 51, 0x0053, 12 },
497 { 52, 0x0024, 12 },
498 { 53, 0x0037, 12 },
499 { 54, 0x0038, 12 },
500 { 55, 0x0027, 12 },
501 { 56, 0x0028, 12 },
502 { 57, 0x0058, 12 },
503 { 58, 0x0059, 12 },
504 { 59, 0x002b, 12 },
505 { 60, 0x002c, 12 },
506 { 61, 0x005a, 12 },
507 { 62, 0x0066, 12 },
508 { 63, 0x0067, 12 },
509 { 64, 0x000f, 10 },
510 { 128, 0x00c8, 12 },
511 { 192, 0x00c9, 12 },
512 { 256, 0x005b, 12 },
513 { 320, 0x0033, 12 },
514 { 384, 0x0034, 12 },
515 { 448, 0x0035, 12 },
516 { 512, 0x006c, 13 },
517 { 576, 0x006d, 13 },
518 { 640, 0x004a, 13 },
519 { 704, 0x004b, 13 },
520 { 768, 0x004c, 13 },
521 { 832, 0x004d, 13 },
522 { 896, 0x0072, 13 },
523 { 960, 0x0073, 13 },
524 { 1024, 0x0074, 13 },
525 { 1088, 0x0075, 13 },
526 { 1152, 0x0076, 13 },
527 { 1216, 0x0077, 13 },
528 { 1280, 0x0052, 13 },
529 { 1344, 0x0053, 13 },
530 { 1408, 0x0054, 13 },
531 { 1472, 0x0055, 13 },
532 { 1536, 0x005a, 13 },
533 { 1600, 0x005b, 13 },
534 { 1664, 0x0064, 13 },
535 { 1728, 0x0065, 13 },
536 { 1792, 0x0008, 11 },
537 { 1856, 0x000c, 11 },
538 { 1920, 0x000d, 11 },
539 { 1984, 0x0012, 12 },
540 { 2048, 0x0013, 12 },
541 { 2112, 0x0014, 12 },
542 { 2176, 0x0015, 12 },
543 { 2240, 0x0016, 12 },
544 { 2304, 0x0017, 12 },
545 { 2368, 0x001c, 12 },
546 { 2432, 0x001d, 12 },
547 { 2496, 0x001e, 12 },
548 { 2560, 0x001f, 12 },
549 { 9999, 0x0001, 12 } // EOL
553 const CCIHuffmanTableEntry CCI2DModeTableSave[CCI2DModeTableSize]={
554 { CCI2DMODE_UNCOMP , 0x000f, 10 },
555 { CCI2DMODE_PASS , 0x0001, 4 },
556 { CCI2DMODE_HORZ , 0x0001, 3 },
557 { CCI2DMODE_VERT_L3, 0x0002, 7 },
558 { CCI2DMODE_VERT_L2, 0x0002, 6 },
559 { CCI2DMODE_VERT_L1, 0x0002, 3 },
560 { CCI2DMODE_VERT_0 , 0x0001, 1 },
561 { CCI2DMODE_VERT_R1, 0x0003, 3 },
562 { CCI2DMODE_VERT_R2, 0x0003, 6 },
563 { CCI2DMODE_VERT_R3, 0x0003, 7 }
567 const CCIHuffmanTableEntry CCIUncompTableSave[CCIUncompTableSize]={
568 { CCIUNCOMP_0White_1Black, 0x0001, 1 },
569 { CCIUNCOMP_1White_1Black, 0x0001, 2 },
570 { CCIUNCOMP_2White_1Black, 0x0001, 3 },
571 { CCIUNCOMP_3White_1Black, 0x0001, 4 },
572 { CCIUNCOMP_4White_1Black, 0x0001, 5 },
573 { CCIUNCOMP_5White , 0x0001, 6 },
574 { CCIUNCOMP_0White_End , 0x0001, 7 },
575 { CCIUNCOMP_1White_End , 0x0001, 8 },
576 { CCIUNCOMP_2White_End , 0x0001, 9 },
577 { CCIUNCOMP_3White_End , 0x0001, 10 },
578 { CCIUNCOMP_4White_End , 0x0001, 11 }
581 //=========================================================================
584 CCIDecompressor::CCIDecompressor( ULONG nOpts, UINT32 nImageWidth ) :
585 bTableBad ( FALSE ),
586 bStatus ( FALSE ),
587 pByteSwap ( NULL ),
588 nWidth ( nImageWidth ),
589 nOptions ( nOpts ),
590 pLastLine ( NULL )
592 if ( nOpts & CCI_OPTION_INVERSEBITORDER )
594 pByteSwap = new BYTE[ 256 ];
595 for ( int i = 0; i < 256; i++ )
597 pByteSwap[ i ] = sal::static_int_cast< BYTE >(
598 ( i << 7 ) | ( ( i & 2 ) << 5 ) | ( ( i & 4 ) << 3 ) | ( ( i & 8 ) << 1 ) |
599 ( ( i & 16 ) >> 1 ) | ( ( i & 32 ) >> 3 ) | ( ( i & 64 ) >> 5 ) | ( ( i & 128 ) >> 7 ));
603 pWhiteLookUp =new CCILookUpTableEntry[1<<13];
604 pBlackLookUp =new CCILookUpTableEntry[1<<13];
605 p2DModeLookUp=new CCILookUpTableEntry[1<<10];
606 pUncompLookUp=new CCILookUpTableEntry[1<<11];
608 MakeLookUp(CCIWhiteTable,CCIWhiteTableSave,pWhiteLookUp,CCIWhiteTableSize,13);
609 MakeLookUp(CCIBlackTable,CCIBlackTableSave,pBlackLookUp,CCIBlackTableSize,13);
610 MakeLookUp(CCI2DModeTable,CCI2DModeTableSave,p2DModeLookUp,CCI2DModeTableSize,10);
611 MakeLookUp(CCIUncompTable,CCIUncompTableSave,pUncompLookUp,CCIUncompTableSize,11);
615 CCIDecompressor::~CCIDecompressor()
617 delete[] pByteSwap;
618 delete[] pLastLine;
619 delete[] pWhiteLookUp;
620 delete[] pBlackLookUp;
621 delete[] p2DModeLookUp;
622 delete[] pUncompLookUp;
626 void CCIDecompressor::StartDecompression( SvStream & rIStream )
628 pIStream = &rIStream;
629 nInputBitsBufSize = 0;
630 bFirstEOL = TRUE;
631 bStatus = TRUE;
632 nEOLCount = 0;
634 if ( bTableBad == TRUE )
635 return;
639 BOOL CCIDecompressor::DecompressScanline( BYTE * pTarget, ULONG nTargetBits )
641 USHORT i;
642 BYTE * pSrc,* pDst;
643 BOOL b2D;
645 if ( nEOLCount >= 5 ) // RTC( Return To Controller )
646 return TRUE;
648 if ( bStatus == FALSE )
649 return FALSE;
651 // Wenn EOL-Codes vorhanden sind, steht der EOL-Code auch vor der ersten Zeile.
652 // (und ich dachte EOL heisst 'End Of Line'...)
653 // Daher lesen wir den EOL-Code immer vor jeder Zeile als erstes ein:
654 if ( nOptions & CCI_OPTION_EOL )
656 if ( bFirstEOL )
658 UINT32 nCurPos = pIStream->Tell();
659 UINT16 nOldInputBitsBufSize = nInputBitsBufSize;
660 UINT32 nOldInputBitsBuf = nInputBitsBuf;
661 if ( ReadEOL( 32 ) == FALSE )
663 nInputBitsBufSize = nOldInputBitsBufSize;
664 nInputBitsBuf = nOldInputBitsBuf;
665 pIStream->Seek( nCurPos );
666 nOptions &=~ CCI_OPTION_EOL; // CCITT Group 3 - Compression Type 2
668 bFirstEOL = FALSE;
670 else
672 if ( ReadEOL( nTargetBits ) == FALSE )
674 return bStatus;
679 if ( nEOLCount >= 5 ) // RTC( Return To Controller )
680 return TRUE;
682 // ggf. eine weisse vorherige Zeile herstellen fuer 2D:
683 if ( nOptions & CCI_OPTION_2D )
685 if ( pLastLine == NULL || nLastLineSize != ( ( nTargetBits + 7 ) >> 3 ) )
687 if ( pLastLine == NULL )
688 delete[] pLastLine;
689 nLastLineSize = ( nTargetBits + 7 ) >> 3;
690 pLastLine = new BYTE[ nLastLineSize ];
691 pDst = pLastLine;
692 for ( i = 0; i < nLastLineSize; i++ ) *( pDst++ ) = 0x00;
695 // ggf. Zeilen-Anfang auf naechste Byte-Grenze runden:
696 if ( nOptions & CCI_OPTION_BYTEALIGNROW )
697 nInputBitsBufSize &= 0xfff8;
699 // Ist es eine 2D-Zeile ?:
700 if ( nOptions & CCI_OPTION_2D )
702 if ( nOptions & CCI_OPTION_EOL )
703 b2D = Read2DTag();
704 else
705 b2D = TRUE;
707 else
708 b2D = FALSE;
710 // Zeile einlesen:
711 if ( b2D )
712 Read2DScanlineData( pTarget, (USHORT)nTargetBits );
713 else
714 Read1DScanlineData( pTarget, (USHORT)nTargetBits );
716 // Wenn wir im 2D-Modus sind, muessen wir uns die Zeile merken:
717 if ( nOptions & CCI_OPTION_2D && bStatus == TRUE )
719 pSrc = pTarget;
720 pDst = pLastLine;
721 for ( i = 0; i < nLastLineSize; i++ ) *(pDst++)=*(pSrc++);
724 if ( pIStream->GetError() )
725 bStatus = FALSE;
727 return bStatus;
731 void CCIDecompressor::MakeLookUp(const CCIHuffmanTableEntry * pHufTab,
732 const CCIHuffmanTableEntry * pHufTabSave,
733 CCILookUpTableEntry * pLookUp,
734 USHORT nHuffmanTableSize,
735 USHORT nMaxCodeBits)
737 USHORT i,j,nMinCode,nMaxCode,nLookUpSize,nMask;
739 if (bTableBad==TRUE) return;
741 nLookUpSize=1<<nMaxCodeBits;
743 nMask=0xffff>>(16-nMaxCodeBits);
745 for (i=0; i<nLookUpSize; i++) pLookUp[i].nCodeBits=0;
746 for (i=0; i<nHuffmanTableSize; i++) {
747 if ( pHufTab[i].nValue!=pHufTabSave[i].nValue ||
748 pHufTab[i].nCode!=pHufTabSave[i].nCode ||
749 pHufTab[i].nCodeBits!=pHufTabSave[i].nCodeBits ||
750 pHufTab[i].nCodeBits==0 ||
751 pHufTab[i].nCodeBits>nMaxCodeBits )
753 bTableBad=TRUE;
754 return;
756 nMinCode = nMask & (pHufTab[i].nCode << (nMaxCodeBits-pHufTab[i].nCodeBits));
757 nMaxCode = nMinCode | (nMask >> pHufTab[i].nCodeBits);
758 for (j=nMinCode; j<=nMaxCode; j++) {
759 if (pLookUp[j].nCodeBits!=0) {
760 bTableBad=TRUE;
761 return;
763 pLookUp[j].nValue=pHufTab[i].nValue;
764 pLookUp[j].nCodeBits=pHufTab[i].nCodeBits;
770 BOOL CCIDecompressor::ReadEOL( UINT32 /*nMaxFillBits*/ )
772 USHORT nCode;
773 BYTE nByte;
775 // if (nOptions&CCI_OPTION_BYTEALIGNEOL) nMaxFillBits=7; else nMaxFillBits=0;
776 // Buuuh: Entweder wird die Option in itiff.cxx nicht richtig gesetzt (-> Fehler in Doku)
777 // oder es gibt tatsaechlich gemeine Export-Filter, die immer ein Align machen.
778 // Ausserdem wurden Dateien gefunden, in denen mehr als die maximal 7 noetigen
779 // Fuellbits vor dem EOL-Code stehen. Daher akzeptieren wir nun grundsaetzlich
780 // bis zu 32-Bloedsinn-Bits vor dem EOL-Code:
781 // und ich habe eine Datei gefunden in der bis zu ??? Bloedsinn Bits stehen, zudem ist dort die Bit Reihenfolge verdreht (SJ);
783 UINT32 nMaxPos = pIStream->Tell();
784 nMaxPos += nWidth >> 3;
786 for ( ;; )
788 while ( nInputBitsBufSize < 12 )
790 *pIStream >> nByte;
791 if ( pIStream->IsEof() )
792 return FALSE;
793 if ( pIStream->Tell() > nMaxPos )
794 return FALSE;
796 if ( nOptions & CCI_OPTION_INVERSEBITORDER )
797 nByte = pByteSwap[ nByte ];
798 nInputBitsBuf=(nInputBitsBuf<<8) | (ULONG)nByte;
799 nInputBitsBufSize += 8;
801 nCode = (USHORT)( ( nInputBitsBuf >> ( nInputBitsBufSize - 12 ) ) & 0x0fff );
802 if ( nCode == 0x0001 )
804 nEOLCount++;
805 nInputBitsBufSize -= 12;
806 break;
808 else
809 nInputBitsBufSize--;
811 return TRUE;
815 BOOL CCIDecompressor::Read2DTag()
817 BYTE nByte;
819 // Ein Bit einlesen und TRUE liefern, wenn es 0 ist, sonst FALSE
820 if (nInputBitsBufSize==0) {
821 *pIStream >> nByte;
822 if ( nOptions & CCI_OPTION_INVERSEBITORDER )
823 nByte = pByteSwap[ nByte ];
824 nInputBitsBuf=(ULONG)nByte;
825 nInputBitsBufSize=8;
827 nInputBitsBufSize--;
828 if ( ((nInputBitsBuf>>nInputBitsBufSize)&0x0001) ) return FALSE;
829 else return TRUE;
833 BYTE CCIDecompressor::ReadBlackOrWhite()
835 BYTE nByte;
837 // Ein Bit einlesen und 0x00 liefern, wenn es 0 ist, sonst 0xff
838 if (nInputBitsBufSize==0) {
839 *pIStream >> nByte;
840 if ( nOptions & CCI_OPTION_INVERSEBITORDER )
841 nByte = pByteSwap[ nByte ];
842 nInputBitsBuf=(ULONG)nByte;
843 nInputBitsBufSize=8;
845 nInputBitsBufSize--;
846 if ( ((nInputBitsBuf>>nInputBitsBufSize)&0x0001) ) return 0xff;
847 else return 0x00;
851 USHORT CCIDecompressor::ReadCodeAndDecode(const CCILookUpTableEntry * pLookUp,
852 USHORT nMaxCodeBits)
854 USHORT nCode,nCodeBits;
855 BYTE nByte;
857 // Einen Huffman-Code einlesen und dekodieren:
858 while (nInputBitsBufSize<nMaxCodeBits) {
859 *pIStream >> nByte;
860 if ( nOptions & CCI_OPTION_INVERSEBITORDER )
861 nByte = pByteSwap[ nByte ];
862 nInputBitsBuf=(nInputBitsBuf<<8) | (ULONG)nByte;
863 nInputBitsBufSize+=8;
865 nCode=(USHORT)((nInputBitsBuf>>(nInputBitsBufSize-nMaxCodeBits))
866 &(0xffff>>(16-nMaxCodeBits)));
867 nCodeBits=pLookUp[nCode].nCodeBits;
868 if (nCodeBits==0) bStatus=FALSE;
869 nInputBitsBufSize = nInputBitsBufSize - nCodeBits;
870 return pLookUp[nCode].nValue;
874 void CCIDecompressor::FillBits(BYTE * pTarget, USHORT nTargetBits,
875 USHORT nBitPos, USHORT nNumBits,
876 BYTE nBlackOrWhite)
878 if ( nBitPos >= nTargetBits )
879 return;
880 if ( nBitPos + nNumBits > nTargetBits )
881 nNumBits = nTargetBits - nBitPos;
883 pTarget+=nBitPos>>3;
884 nBitPos&=7;
886 if (nBlackOrWhite==0x00) *pTarget &= 0xff << (8-nBitPos);
887 else *pTarget |= 0xff >> nBitPos;
888 if (nNumBits>8-nBitPos) {
889 nNumBits-=8-nBitPos;
890 while (nNumBits>=8) {
891 *(++pTarget)=nBlackOrWhite;
892 nNumBits-=8;
894 if (nNumBits>0) *(++pTarget)=nBlackOrWhite;
899 USHORT CCIDecompressor::CountBits(const BYTE * pData, USHORT nDataSizeBits,
900 USHORT nBitPos, BYTE nBlackOrWhite)
902 USHORT nPos,nLo;
903 BYTE nData;
905 // Hier wird die Anzahl der zusammenhaengenden Bits gezaehlt, die
906 // ab Position nBitPos in pTarget alle die Farbe nBlackOrWhite
907 // (0xff oder 0x00) haben.
909 nPos=nBitPos;
910 for (;;) {
911 if (nPos>=nDataSizeBits) {
912 nPos=nDataSizeBits;
913 break;
915 nData=pData[nPos>>3];
916 nLo=nPos & 7;
917 if ( nLo==0 && nData==nBlackOrWhite) nPos+=8;
918 else {
919 if ( ((nData^nBlackOrWhite) & (0x80 >> nLo))!=0) break;
920 nPos++;
923 if (nPos<=nBitPos) return 0;
924 else return nPos-nBitPos;
928 void CCIDecompressor::Read1DScanlineData(BYTE * pTarget, USHORT nTargetBits)
930 USHORT nCode,nCodeBits,nDataBits,nTgtFreeByteBits;
931 BYTE nByte;
932 BYTE nBlackOrWhite; // ist 0xff fuer Black oder 0x00 fuer White
933 BOOL bTerminatingCode;
935 // Der erste Code ist immer eine "White-Code":
936 nBlackOrWhite=0x00;
938 // Anzahl der Bits, die im Byte *pTarget noch nicht geschrieben sind:
939 nTgtFreeByteBits=8;
941 // Schleife ueber Codes aus dem Eingabe-Stream:
942 do {
944 // die naechsten 13 Bits nach nCode holen, aber noch nicht
945 // aus dem Eingabe-Buffer loeschen:
946 while (nInputBitsBufSize<13) {
947 *pIStream >> nByte;
948 if ( nOptions & CCI_OPTION_INVERSEBITORDER )
949 nByte = pByteSwap[ nByte ];
950 nInputBitsBuf=(nInputBitsBuf<<8) | (ULONG)nByte;
951 nInputBitsBufSize+=8;
953 nCode=(USHORT)((nInputBitsBuf>>(nInputBitsBufSize-13))&0x1fff);
955 // Anzahl der DatenBits und Anzahl der CodeBits ermitteln:
956 if (nBlackOrWhite) {
957 nCodeBits=pBlackLookUp[nCode].nCodeBits;
958 nDataBits=pBlackLookUp[nCode].nValue;
960 else {
961 nCodeBits=pWhiteLookUp[nCode].nCodeBits;
962 nDataBits=pWhiteLookUp[nCode].nValue;
964 // Ist es ein Ungueltiger Code ?
965 if ( nDataBits == 9999 )
967 return;
969 if ( nCodeBits == 0 )
971 return; // das koennen sich jetzt um FuellBits handeln
973 nEOLCount = 0;
974 // Zuviele Daten ?
975 if (nDataBits>nTargetBits) {
976 // Ja, koennte ein Folge-Fehler durch ungueltigen Code sein,
977 // daher irdenwie weitermachen:
978 nDataBits=nTargetBits;
981 // Ist es ein 'Terminating-Code' ?
982 if (nDataBits<64) bTerminatingCode=TRUE; else bTerminatingCode=FALSE;
984 // Die gelesenen Bits aus dem Eingabe-Buffer entfernen:
985 nInputBitsBufSize = nInputBitsBufSize - nCodeBits;
987 // Die Anzahl Daten-Bits in die Scanline schreiben:
988 if (nDataBits>0) {
989 nTargetBits = nTargetBits - nDataBits;
990 if (nBlackOrWhite==0x00) *pTarget &= 0xff << nTgtFreeByteBits;
991 else *pTarget |= 0xff >> (8-nTgtFreeByteBits);
992 if (nDataBits<=nTgtFreeByteBits) {
993 if (nDataBits==nTgtFreeByteBits) {
994 pTarget++;
995 nTgtFreeByteBits=8;
997 else nTgtFreeByteBits = nTgtFreeByteBits - nDataBits;
999 else {
1000 nDataBits = nDataBits - nTgtFreeByteBits;
1001 pTarget++;
1002 nTgtFreeByteBits=8;
1003 while (nDataBits>=8) {
1004 *(pTarget++)=nBlackOrWhite;
1005 nDataBits-=8;
1007 if (nDataBits>0) {
1008 *pTarget=nBlackOrWhite;
1009 nTgtFreeByteBits = nTgtFreeByteBits - nDataBits;
1014 // ggf. Umschaltung Black <-> White:
1015 if (bTerminatingCode==TRUE) nBlackOrWhite=~nBlackOrWhite;
1017 } while (nTargetBits>0 || bTerminatingCode==FALSE);
1022 void CCIDecompressor::Read2DScanlineData(BYTE * pTarget, USHORT nTargetBits)
1024 USHORT n2DMode,nBitPos,nUncomp,nRun,nRun2,nt;
1025 BYTE nBlackOrWhite;
1027 nBlackOrWhite=0x00;
1028 nBitPos=0;
1030 while (nBitPos<nTargetBits && bStatus==TRUE) {
1032 n2DMode=ReadCodeAndDecode(p2DModeLookUp,10);
1033 if (bStatus==FALSE) return;
1035 if (n2DMode==CCI2DMODE_UNCOMP) {
1036 for (;;) {
1037 nUncomp=ReadCodeAndDecode(pUncompLookUp,11);
1038 if ( nUncomp <= CCIUNCOMP_4White_1Black ) {
1039 nRun=nUncomp-CCIUNCOMP_0White_1Black;
1040 FillBits(pTarget,nTargetBits,nBitPos,nRun,0x00);
1041 nBitPos = nBitPos + nRun;
1042 FillBits(pTarget,nTargetBits,nBitPos,1,0xff);
1043 nBitPos++;
1045 else if ( nUncomp == CCIUNCOMP_5White ) {
1046 FillBits(pTarget,nTargetBits,nBitPos,5,0x00);
1047 nBitPos = nBitPos + 5;
1049 else {
1050 nRun=nUncomp-CCIUNCOMP_0White_End;
1051 FillBits(pTarget,nTargetBits,nBitPos,nRun,0x00);
1052 nBitPos = nBitPos + nRun;
1053 nBlackOrWhite=ReadBlackOrWhite();
1054 break;
1059 else if (n2DMode==CCI2DMODE_PASS) {
1060 if (nBitPos==0 && nBlackOrWhite==0x00 && CountBits(pLastLine,nTargetBits,0,0xff)!=0) nRun=0;
1061 else {
1062 nRun=CountBits(pLastLine,nTargetBits,nBitPos,~nBlackOrWhite);
1063 nRun = nRun + CountBits(pLastLine,nTargetBits,nBitPos+nRun,nBlackOrWhite);
1065 nRun = nRun + CountBits(pLastLine,nTargetBits,nBitPos+nRun,~nBlackOrWhite);
1066 FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite);
1067 nBitPos = nBitPos + nRun;
1070 else if (n2DMode==CCI2DMODE_HORZ) {
1071 if (nBlackOrWhite==0x00) {
1072 nRun=0;
1073 do {
1074 nt=ReadCodeAndDecode(pWhiteLookUp,13);
1075 nRun = nRun + nt;
1076 } while (nt>=64);
1077 nRun2=0;
1078 do {
1079 nt=ReadCodeAndDecode(pBlackLookUp,13);
1080 nRun2 = nRun2 + nt;
1081 } while (nt>=64);
1083 else {
1084 nRun=0;
1085 do {
1086 nt=ReadCodeAndDecode(pBlackLookUp,13);
1087 nRun = nRun + nt;
1088 } while (nt>=64);
1089 nRun2=0;
1090 do {
1091 nt=ReadCodeAndDecode(pWhiteLookUp,13);
1092 nRun2 = nRun2 + nt;
1093 } while (nt>=64);
1095 FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite);
1096 nBitPos = nBitPos + nRun;
1097 FillBits(pTarget,nTargetBits,nBitPos,nRun2,~nBlackOrWhite);
1098 nBitPos = nBitPos + nRun2;
1101 else { // Es ist einer der Modi CCI2DMODE_VERT_...
1102 if (nBitPos==0 && nBlackOrWhite==0x00 && CountBits(pLastLine,nTargetBits,0,0xff)!=0) nRun=0;
1103 else {
1104 nRun=CountBits(pLastLine,nTargetBits,nBitPos,~nBlackOrWhite);
1105 nRun = nRun + CountBits(pLastLine,nTargetBits,nBitPos+nRun,nBlackOrWhite);
1107 nRun+=n2DMode-CCI2DMODE_VERT_0;
1108 FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite);
1109 nBitPos = nBitPos + nRun;
1110 nBlackOrWhite=~nBlackOrWhite;