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