xref: /trunk/main/svtools/source/filter/igif/decode.cxx (revision 5900e8ec)
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