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