xref: /AOO41X/main/filter/source/graphicfilter/itiff/ccidecom.cxx (revision 9e0fc027f109ec4ffcb6033aeec742a099701108)
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