1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ccidecom.cxx,v $
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
]={
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
]={
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
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
336 const CCIHuffmanTableEntry CCIWhiteTableSave
[CCIWhiteTableSize
]={
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
]={
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
) :
588 nWidth ( nImageWidth
),
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()
619 delete[] pWhiteLookUp
;
620 delete[] pBlackLookUp
;
621 delete[] p2DModeLookUp
;
622 delete[] pUncompLookUp
;
626 void CCIDecompressor::StartDecompression( SvStream
& rIStream
)
628 pIStream
= &rIStream
;
629 nInputBitsBufSize
= 0;
634 if ( bTableBad
== TRUE
)
639 BOOL
CCIDecompressor::DecompressScanline( BYTE
* pTarget
, ULONG nTargetBits
)
645 if ( nEOLCount
>= 5 ) // RTC( Return To Controller )
648 if ( bStatus
== 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
)
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
672 if ( ReadEOL( nTargetBits
) == FALSE
)
679 if ( nEOLCount
>= 5 ) // RTC( Return To Controller )
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
)
689 nLastLineSize
= ( nTargetBits
+ 7 ) >> 3;
690 pLastLine
= new BYTE
[ nLastLineSize
];
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
)
712 Read2DScanlineData( pTarget
, (USHORT
)nTargetBits
);
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
)
721 for ( i
= 0; i
< nLastLineSize
; i
++ ) *(pDst
++)=*(pSrc
++);
724 if ( pIStream
->GetError() )
731 void CCIDecompressor::MakeLookUp(const CCIHuffmanTableEntry
* pHufTab
,
732 const CCIHuffmanTableEntry
* pHufTabSave
,
733 CCILookUpTableEntry
* pLookUp
,
734 USHORT nHuffmanTableSize
,
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
)
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) {
763 pLookUp
[j
].nValue
=pHufTab
[i
].nValue
;
764 pLookUp
[j
].nCodeBits
=pHufTab
[i
].nCodeBits
;
770 BOOL
CCIDecompressor::ReadEOL( UINT32
/*nMaxFillBits*/ )
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;
788 while ( nInputBitsBufSize
< 12 )
791 if ( pIStream
->IsEof() )
793 if ( pIStream
->Tell() > nMaxPos
)
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 )
805 nInputBitsBufSize
-= 12;
815 BOOL
CCIDecompressor::Read2DTag()
819 // Ein Bit einlesen und TRUE liefern, wenn es 0 ist, sonst FALSE
820 if (nInputBitsBufSize
==0) {
822 if ( nOptions
& CCI_OPTION_INVERSEBITORDER
)
823 nByte
= pByteSwap
[ nByte
];
824 nInputBitsBuf
=(ULONG
)nByte
;
828 if ( ((nInputBitsBuf
>>nInputBitsBufSize
)&0x0001) ) return FALSE
;
833 BYTE
CCIDecompressor::ReadBlackOrWhite()
837 // Ein Bit einlesen und 0x00 liefern, wenn es 0 ist, sonst 0xff
838 if (nInputBitsBufSize
==0) {
840 if ( nOptions
& CCI_OPTION_INVERSEBITORDER
)
841 nByte
= pByteSwap
[ nByte
];
842 nInputBitsBuf
=(ULONG
)nByte
;
846 if ( ((nInputBitsBuf
>>nInputBitsBufSize
)&0x0001) ) return 0xff;
851 USHORT
CCIDecompressor::ReadCodeAndDecode(const CCILookUpTableEntry
* pLookUp
,
854 USHORT nCode
,nCodeBits
;
857 // Einen Huffman-Code einlesen und dekodieren:
858 while (nInputBitsBufSize
<nMaxCodeBits
) {
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
,
878 if ( nBitPos
>= nTargetBits
)
880 if ( nBitPos
+ nNumBits
> nTargetBits
)
881 nNumBits
= nTargetBits
- nBitPos
;
886 if (nBlackOrWhite
==0x00) *pTarget
&= 0xff << (8-nBitPos
);
887 else *pTarget
|= 0xff >> nBitPos
;
888 if (nNumBits
>8-nBitPos
) {
890 while (nNumBits
>=8) {
891 *(++pTarget
)=nBlackOrWhite
;
894 if (nNumBits
>0) *(++pTarget
)=nBlackOrWhite
;
899 USHORT
CCIDecompressor::CountBits(const BYTE
* pData
, USHORT nDataSizeBits
,
900 USHORT nBitPos
, BYTE nBlackOrWhite
)
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.
911 if (nPos
>=nDataSizeBits
) {
915 nData
=pData
[nPos
>>3];
917 if ( nLo
==0 && nData
==nBlackOrWhite
) nPos
+=8;
919 if ( ((nData
^nBlackOrWhite
) & (0x80 >> nLo
))!=0) break;
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
;
932 BYTE nBlackOrWhite
; // ist 0xff fuer Black oder 0x00 fuer White
933 BOOL bTerminatingCode
;
935 // Der erste Code ist immer eine "White-Code":
938 // Anzahl der Bits, die im Byte *pTarget noch nicht geschrieben sind:
941 // Schleife ueber Codes aus dem Eingabe-Stream:
944 // die naechsten 13 Bits nach nCode holen, aber noch nicht
945 // aus dem Eingabe-Buffer loeschen:
946 while (nInputBitsBufSize
<13) {
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:
957 nCodeBits
=pBlackLookUp
[nCode
].nCodeBits
;
958 nDataBits
=pBlackLookUp
[nCode
].nValue
;
961 nCodeBits
=pWhiteLookUp
[nCode
].nCodeBits
;
962 nDataBits
=pWhiteLookUp
[nCode
].nValue
;
964 // Ist es ein Ungueltiger Code ?
965 if ( nDataBits
== 9999 )
969 if ( nCodeBits
== 0 )
971 return; // das koennen sich jetzt um FuellBits handeln
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:
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
) {
997 else nTgtFreeByteBits
= nTgtFreeByteBits
- nDataBits
;
1000 nDataBits
= nDataBits
- nTgtFreeByteBits
;
1003 while (nDataBits
>=8) {
1004 *(pTarget
++)=nBlackOrWhite
;
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
;
1030 while (nBitPos
<nTargetBits
&& bStatus
==TRUE
) {
1032 n2DMode
=ReadCodeAndDecode(p2DModeLookUp
,10);
1033 if (bStatus
==FALSE
) return;
1035 if (n2DMode
==CCI2DMODE_UNCOMP
) {
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);
1045 else if ( nUncomp
== CCIUNCOMP_5White
) {
1046 FillBits(pTarget
,nTargetBits
,nBitPos
,5,0x00);
1047 nBitPos
= nBitPos
+ 5;
1050 nRun
=nUncomp
-CCIUNCOMP_0White_End
;
1051 FillBits(pTarget
,nTargetBits
,nBitPos
,nRun
,0x00);
1052 nBitPos
= nBitPos
+ nRun
;
1053 nBlackOrWhite
=ReadBlackOrWhite();
1059 else if (n2DMode
==CCI2DMODE_PASS
) {
1060 if (nBitPos
==0 && nBlackOrWhite
==0x00 && CountBits(pLastLine
,nTargetBits
,0,0xff)!=0) nRun
=0;
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) {
1074 nt
=ReadCodeAndDecode(pWhiteLookUp
,13);
1079 nt
=ReadCodeAndDecode(pBlackLookUp
,13);
1086 nt
=ReadCodeAndDecode(pBlackLookUp
,13);
1091 nt
=ReadCodeAndDecode(pWhiteLookUp
,13);
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;
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
;