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_svtools.hxx"
26
27 #include "decode.hxx"
28
29 // ------------------------------------------------------------------------
30
31 struct GIFLZWTableEntry
32 {
33 GIFLZWTableEntry* pPrev;
34 GIFLZWTableEntry* pFirst;
35 sal_uInt8 nData;
36 };
37
38 // ------------------------------------------------------------------------
39
GIFLZWDecompressor(sal_uInt8 cDataSize)40 GIFLZWDecompressor::GIFLZWDecompressor( sal_uInt8 cDataSize ) :
41 nInputBitsBuf ( 0 ),
42 nOutBufDataLen ( 0 ),
43 nInputBitsBufSize ( 0 ),
44 bEOIFound ( sal_False ),
45 nDataSize ( cDataSize )
46 {
47 pOutBuf = new sal_uInt8[ 4096 ];
48
49 nClearCode = 1 << nDataSize;
50 nEOICode = nClearCode + 1;
51 nTableSize = nEOICode + 1;
52 nCodeSize = nDataSize + 1;
53 nOldCode = 0xffff;
54 pOutBufData = pOutBuf + 4096;
55
56 pTable = new GIFLZWTableEntry[ 4098 ];
57
58 for( sal_uInt16 i = 0; i < nTableSize; i++ )
59 {
60 pTable[i].pPrev = NULL;
61 pTable[i].pFirst = pTable + i;
62 pTable[i].nData = (sal_uInt8) i;
63 }
64 }
65
66 // ------------------------------------------------------------------------
67
~GIFLZWDecompressor()68 GIFLZWDecompressor::~GIFLZWDecompressor()
69 {
70 delete[] pOutBuf;
71 delete[] pTable;
72 }
73
74 // ------------------------------------------------------------------------
75
DecompressBlock(HPBYTE pSrc,sal_uInt8 cBufSize,sal_uLong & rCount,sal_Bool & rEOI)76 HPBYTE GIFLZWDecompressor::DecompressBlock( HPBYTE pSrc, sal_uInt8 cBufSize,
77 sal_uLong& rCount, sal_Bool& rEOI )
78 {
79 sal_uLong nTargetSize = 4096;
80 sal_uLong nCount = 0;
81 HPBYTE pTarget = (HPBYTE) rtl_allocateMemory( nTargetSize );
82 HPBYTE pTmpTarget = pTarget;
83
84 nBlockBufSize = cBufSize;
85 nBlockBufPos = 0;
86 pBlockBuf = pSrc;
87
88 while( ProcessOneCode() )
89 {
90 nCount += nOutBufDataLen;
91
92 if( nCount > nTargetSize )
93 {
94 sal_uLong nNewSize = nTargetSize << 1;
95 sal_uLong nOffset = pTmpTarget - pTarget;
96 HPBYTE pTmp = (HPBYTE) rtl_allocateMemory( nNewSize );
97
98 memcpy( pTmp, pTarget, nTargetSize );
99 rtl_freeMemory( pTarget );
100
101 nTargetSize = nNewSize;
102 pTmpTarget = ( pTarget = pTmp ) + nOffset;
103 }
104
105 memcpy( pTmpTarget, pOutBufData, nOutBufDataLen );
106 pTmpTarget += nOutBufDataLen;
107 pOutBufData += nOutBufDataLen;
108 nOutBufDataLen = 0;
109
110 if ( bEOIFound )
111 break;
112 }
113
114 rCount = nCount;
115 rEOI = bEOIFound;
116
117 return pTarget;
118 }
119
120 // ------------------------------------------------------------------------
121
AddToTable(sal_uInt16 nPrevCode,sal_uInt16 nCodeFirstData)122 void GIFLZWDecompressor::AddToTable( sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData )
123 {
124 GIFLZWTableEntry* pE;
125
126 if( nTableSize < 4096 )
127 {
128 pE = pTable + nTableSize;
129 pE->pPrev = pTable + nPrevCode;
130 pE->pFirst = pE->pPrev->pFirst;
131 pE->nData = pTable[ nCodeFirstData ].pFirst->nData;
132 nTableSize++;
133
134 if ( ( nTableSize == (sal_uInt16) (1 << nCodeSize) ) && ( nTableSize < 4096 ) )
135 nCodeSize++;
136 }
137 }
138
139 // ------------------------------------------------------------------------
140
ProcessOneCode()141 sal_Bool GIFLZWDecompressor::ProcessOneCode()
142 {
143 GIFLZWTableEntry* pE;
144 sal_uInt16 nCode;
145 sal_Bool bRet = sal_False;
146 sal_Bool bEndOfBlock = sal_False;
147
148 while( nInputBitsBufSize < nCodeSize )
149 {
150 if( nBlockBufPos >= nBlockBufSize )
151 {
152 bEndOfBlock = sal_True;
153 break;
154 }
155
156 nInputBitsBuf |= ( (sal_uLong) pBlockBuf[ nBlockBufPos++ ] ) << nInputBitsBufSize;
157 nInputBitsBufSize += 8;
158 }
159
160 if ( !bEndOfBlock )
161 {
162 // Einen Code aus dem Eingabe-Buffer holen:
163 nCode = sal::static_int_cast< sal_uInt16 >(
164 ( (sal_uInt16) nInputBitsBuf ) & ( ~( 0xffff << nCodeSize ) ));
165 nInputBitsBuf >>= nCodeSize;
166 nInputBitsBufSize = nInputBitsBufSize - nCodeSize;
167
168 if ( nCode < nClearCode )
169 {
170 if ( nOldCode != 0xffff )
171 AddToTable( nOldCode, nCode );
172 }
173 else if ( ( nCode > nEOICode ) && ( nCode <= nTableSize ) )
174 {
175 if ( nCode == nTableSize )
176 AddToTable( nOldCode, nOldCode );
177 else
178 AddToTable( nOldCode, nCode );
179 }
180 else
181 {
182 if ( nCode == nClearCode )
183 {
184 nTableSize = nEOICode + 1;
185 nCodeSize = nDataSize + 1;
186 nOldCode = 0xffff;
187 nOutBufDataLen = 0;
188 }
189 else
190 bEOIFound = sal_True;
191
192 return sal_True;
193 }
194
195 nOldCode = nCode;
196
197 // Zeichen(/-folge) des Codes nCode in den Ausgabe-Buffer schreiben:
198 pE = pTable + nCode;
199 do
200 {
201 nOutBufDataLen++;
202 *(--pOutBufData) = pE->nData;
203 pE = pE->pPrev;
204 }
205 while( pE );
206
207 bRet = sal_True;
208 }
209
210 return bRet;
211 }
212