Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "decode.hxx"
22 :
23 : // ------------------------------------------------------------------------
24 :
25 : struct GIFLZWTableEntry
26 : {
27 : GIFLZWTableEntry* pPrev;
28 : GIFLZWTableEntry* pFirst;
29 : sal_uInt8 nData;
30 : };
31 :
32 : // ------------------------------------------------------------------------
33 :
34 56 : GIFLZWDecompressor::GIFLZWDecompressor( sal_uInt8 cDataSize ) :
35 : nInputBitsBuf ( 0 ),
36 : nOutBufDataLen ( 0 ),
37 : nInputBitsBufSize ( 0 ),
38 : bEOIFound ( sal_False ),
39 56 : nDataSize ( cDataSize )
40 : {
41 56 : pOutBuf = new sal_uInt8[ 4096 ];
42 :
43 56 : nClearCode = 1 << nDataSize;
44 56 : nEOICode = nClearCode + 1;
45 56 : nTableSize = nEOICode + 1;
46 56 : nCodeSize = nDataSize + 1;
47 56 : nOldCode = 0xffff;
48 56 : pOutBufData = pOutBuf + 4096;
49 :
50 56 : pTable = new GIFLZWTableEntry[ 4098 ];
51 :
52 8360 : for( sal_uInt16 i = 0; i < nTableSize; i++ )
53 : {
54 8304 : pTable[i].pPrev = NULL;
55 8304 : pTable[i].pFirst = pTable + i;
56 8304 : pTable[i].nData = (sal_uInt8) i;
57 : }
58 56 : }
59 :
60 : // ------------------------------------------------------------------------
61 :
62 56 : GIFLZWDecompressor::~GIFLZWDecompressor()
63 : {
64 56 : delete[] pOutBuf;
65 56 : delete[] pTable;
66 56 : }
67 :
68 : // ------------------------------------------------------------------------
69 :
70 89 : HPBYTE GIFLZWDecompressor::DecompressBlock( HPBYTE pSrc, sal_uInt8 cBufSize,
71 : sal_uLong& rCount, sal_Bool& rEOI )
72 : {
73 89 : sal_uLong nTargetSize = 4096;
74 89 : sal_uLong nCount = 0;
75 89 : HPBYTE pTarget = (HPBYTE) rtl_allocateMemory( nTargetSize );
76 89 : HPBYTE pTmpTarget = pTarget;
77 :
78 89 : nBlockBufSize = cBufSize;
79 89 : nBlockBufPos = 0;
80 89 : pBlockBuf = pSrc;
81 :
82 12624 : while( ProcessOneCode() )
83 : {
84 12502 : nCount += nOutBufDataLen;
85 :
86 12502 : if( nCount > nTargetSize )
87 : {
88 0 : sal_uLong nNewSize = nTargetSize << 1;
89 0 : sal_uLong nOffset = pTmpTarget - pTarget;
90 0 : HPBYTE pTmp = (HPBYTE) rtl_allocateMemory( nNewSize );
91 :
92 0 : memcpy( pTmp, pTarget, nTargetSize );
93 0 : rtl_freeMemory( pTarget );
94 :
95 0 : nTargetSize = nNewSize;
96 0 : pTmpTarget = ( pTarget = pTmp ) + nOffset;
97 : }
98 :
99 12502 : memcpy( pTmpTarget, pOutBufData, nOutBufDataLen );
100 12502 : pTmpTarget += nOutBufDataLen;
101 12502 : pOutBufData += nOutBufDataLen;
102 12502 : nOutBufDataLen = 0;
103 :
104 12502 : if ( bEOIFound )
105 56 : break;
106 : }
107 :
108 89 : rCount = nCount;
109 89 : rEOI = bEOIFound;
110 :
111 89 : return pTarget;
112 : }
113 :
114 : // ------------------------------------------------------------------------
115 :
116 12334 : void GIFLZWDecompressor::AddToTable( sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData )
117 : {
118 : GIFLZWTableEntry* pE;
119 :
120 12334 : if( nTableSize < 4096 )
121 : {
122 12334 : pE = pTable + nTableSize;
123 12334 : pE->pPrev = pTable + nPrevCode;
124 12334 : pE->pFirst = pE->pPrev->pFirst;
125 12334 : pE->nData = pTable[ nCodeFirstData ].pFirst->nData;
126 12334 : nTableSize++;
127 :
128 12334 : if ( ( nTableSize == (sal_uInt16) (1 << nCodeSize) ) && ( nTableSize < 4096 ) )
129 103 : nCodeSize++;
130 : }
131 12334 : }
132 :
133 : // ------------------------------------------------------------------------
134 :
135 12535 : sal_Bool GIFLZWDecompressor::ProcessOneCode()
136 : {
137 : GIFLZWTableEntry* pE;
138 : sal_uInt16 nCode;
139 12535 : sal_Bool bRet = sal_False;
140 12535 : sal_Bool bEndOfBlock = sal_False;
141 :
142 38313 : while( nInputBitsBufSize < nCodeSize )
143 : {
144 13276 : if( nBlockBufPos >= nBlockBufSize )
145 : {
146 33 : bEndOfBlock = sal_True;
147 33 : break;
148 : }
149 :
150 13243 : nInputBitsBuf |= ( (sal_uLong) pBlockBuf[ nBlockBufPos++ ] ) << nInputBitsBufSize;
151 13243 : nInputBitsBufSize += 8;
152 : }
153 :
154 12535 : if ( !bEndOfBlock )
155 : {
156 : // Einen Code aus dem Eingabe-Buffer holen:
157 : nCode = sal::static_int_cast< sal_uInt16 >(
158 12502 : ( (sal_uInt16) nInputBitsBuf ) & ( ~( 0xffff << nCodeSize ) ));
159 12502 : nInputBitsBuf >>= nCodeSize;
160 12502 : nInputBitsBufSize = nInputBitsBufSize - nCodeSize;
161 :
162 12502 : if ( nCode < nClearCode )
163 : {
164 7729 : if ( nOldCode != 0xffff )
165 7673 : AddToTable( nOldCode, nCode );
166 : }
167 4773 : else if ( ( nCode > nEOICode ) && ( nCode <= nTableSize ) )
168 : {
169 9322 : if ( nCode == nTableSize )
170 611 : AddToTable( nOldCode, nOldCode );
171 : else
172 4050 : AddToTable( nOldCode, nCode );
173 : }
174 : else
175 : {
176 112 : if ( nCode == nClearCode )
177 : {
178 56 : nTableSize = nEOICode + 1;
179 56 : nCodeSize = nDataSize + 1;
180 56 : nOldCode = 0xffff;
181 56 : nOutBufDataLen = 0;
182 : }
183 : else
184 56 : bEOIFound = sal_True;
185 :
186 112 : return sal_True;
187 : }
188 :
189 12390 : nOldCode = nCode;
190 :
191 : // Zeichen(/-folge) des Codes nCode in den Ausgabe-Buffer schreiben:
192 12390 : pE = pTable + nCode;
193 25409 : do
194 : {
195 25409 : nOutBufDataLen++;
196 25409 : *(--pOutBufData) = pE->nData;
197 25409 : pE = pE->pPrev;
198 : }
199 : while( pE );
200 :
201 12390 : bRet = sal_True;
202 : }
203 :
204 12423 : return bRet;
205 : }
206 :
207 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|