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