LibreOffice Module vcl (master)  1
lzwdecom.cxx
Go to the documentation of this file.
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 "lzwdecom.hxx"
22 #include <sal/log.hxx>
23 #include <tools/stream.hxx>
24 
26  : pIStream(nullptr)
27  , aTable{{}}
28  , nTableSize(0)
29  , bEOIFound(false)
30  , bInvert(false)
31  , bFirst(true)
32  , nOldCode(0)
33  , pOutBufData(nullptr)
34  , nOutBufDataLen(0)
35  , nInputBitsBuf(0)
36  , nInputBitsBufSize(0)
37 {
38  for (sal_uInt16 i=0; i<MAX_TABLE_SIZE; i++)
39  {
40  aTable[i].nPrevCode=0;
41  aTable[i].nDataCount=1;
42  aTable[i].nData=static_cast<sal_uInt8>(i);
43  }
44 }
45 
46 
48 {
49 }
50 
51 
53 {
54  pIStream=&rIStream;
55 
56  nTableSize=258;
57 
58  bEOIFound=false;
59 
61 
63 
65 
66  if ( bFirst )
67  {
68  bInvert = nInputBitsBuf == 1;
69  bFirst = false;
70  }
71 
72  if ( bInvert )
73  nInputBitsBuf = ( ( nInputBitsBuf & 1 ) << 7 ) | ( ( nInputBitsBuf & 2 ) << 5 ) | ( ( nInputBitsBuf & 4 ) << 3 ) | ( ( nInputBitsBuf & 8 ) << 1 ) | ( ( nInputBitsBuf & 16 ) >> 1 ) | ( ( nInputBitsBuf & 32 ) >> 3 ) | ( ( nInputBitsBuf & 64 ) >> 5 ) | ( (nInputBitsBuf & 128 ) >> 7 );
74 }
75 
76 
77 sal_uInt64 LZWDecompressor::Decompress(sal_uInt8 * pTarget, sal_uInt32 nMaxCount)
78 {
79  sal_uInt32 nCount;
80 
81  if (pIStream==nullptr) return 0;
82 
83  nCount=0;
84  for (;;) {
85 
86  if (pIStream->GetError()) break;
87 
88  if (nOutBufDataLen>=nMaxCount) {
89  nOutBufDataLen = nOutBufDataLen - static_cast<sal_uInt16>(nMaxCount);
90  nCount+=nMaxCount;
91  while (nMaxCount>0) {
92  *(pTarget++)=*(pOutBufData++);
93  nMaxCount--;
94  }
95  break;
96  }
97 
98  nMaxCount-=static_cast<sal_uInt32>(nOutBufDataLen);
99  nCount+=nOutBufDataLen;
100  while (nOutBufDataLen>0) {
101  *(pTarget++)=*(pOutBufData++);
102  nOutBufDataLen--;
103  }
104 
105  if (bEOIFound) break;
106 
107  DecompressSome();
108 
109  }
110 
111  return nCount;
112 }
113 
114 
116 {
117  sal_uInt16 nBits,nCode;
118 
119  if (nTableSize<511) nBits=9;
120  else if (nTableSize<1023) nBits=10;
121  else if (nTableSize<2047) nBits=11;
122  else nBits=12;
123 
124  nCode=0;
125  do {
126  if (nInputBitsBufSize<=nBits)
127  {
128  nCode=(nCode<<nInputBitsBufSize) | nInputBitsBuf;
129  nBits = nBits - nInputBitsBufSize;
131  if ( bInvert )
132  nInputBitsBuf = ( ( nInputBitsBuf & 1 ) << 7 ) | ( ( nInputBitsBuf & 2 ) << 5 ) | ( ( nInputBitsBuf & 4 ) << 3 ) | ( ( nInputBitsBuf & 8 ) << 1 ) | ( ( nInputBitsBuf & 16 ) >> 1 ) | ( ( nInputBitsBuf & 32 ) >> 3 ) | ( ( nInputBitsBuf & 64 ) >> 5 ) | ( (nInputBitsBuf & 128 ) >> 7 );
133  nInputBitsBufSize=8;
134  }
135  else
136  {
137  nCode=(nCode<<nBits) | (nInputBitsBuf>>(nInputBitsBufSize-nBits));
139  nInputBitsBuf&=0x00ff>>(8-nInputBitsBufSize);
140  nBits=0;
141  }
142  } while (nBits>0);
143 
144  return nCode;
145 }
146 
147 
148 void LZWDecompressor::AddToTable(sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData)
149 {
150  if (nTableSize >= MAX_TABLE_SIZE)
151  {
152  //It might be possible to force emit a 256 to flush the buffer and try
153  //to continue later?
154  SAL_WARN("filter.tiff", "Too much data at scanline");
155  bEOIFound = true;
156  return;
157  }
158 
159  unsigned char aSeenIndexes[MAX_TABLE_SIZE] = {0};
160  while (aTable[nCodeFirstData].nDataCount>1)
161  {
162  if (aSeenIndexes[nCodeFirstData])
163  {
164  SAL_WARN("filter.tiff", "Loop in chain");
165  bEOIFound = true;
166  return;
167  }
168  aSeenIndexes[nCodeFirstData] = 1;
169  nCodeFirstData=aTable[nCodeFirstData].nPrevCode;
170  }
171 
172  aTable[nTableSize].nPrevCode=nPrevCode;
173  aTable[nTableSize].nDataCount=aTable[nPrevCode].nDataCount+1;
174  aTable[nTableSize].nData=aTable[nCodeFirstData].nData;
175 
176  nTableSize++;
177 }
178 
179 
181 {
182  sal_uInt16 i,nCode;
183 
184  nCode=GetNextCode();
185  if (nCode==256)
186  {
187  nTableSize=258;
188  nCode=GetNextCode();
189  if (nCode==257)
190  {
191  bEOIFound=true;
192  }
193  }
194  else if (nCode<nTableSize)
195  AddToTable(nOldCode,nCode);
196  else if (nCode==nTableSize)
198  else
199  {
200  bEOIFound=true;
201  }
202 
203  if (bEOIFound)
204  return;
205 
206  nOldCode=nCode;
207 
208  nOutBufDataLen=aTable[nCode].nDataCount;
210  for (i=0; i<nOutBufDataLen; i++)
211  {
212  *(--pOutBufData)=aTable[nCode].nData;
213  nCode=aTable[nCode].nPrevCode;
214  }
215 }
216 
217 
218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define MAX_TABLE_SIZE
Definition: lzwdecom.hxx:26
sal_uInt16 GetNextCode()
Definition: lzwdecom.cxx:115
void AddToTable(sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData)
Definition: lzwdecom.cxx:148
sal_uInt8 nInputBitsBuf
Definition: lzwdecom.hxx:67
std::array< LZWTableEntry, MAX_TABLE_SIZE > aTable
Definition: lzwdecom.hxx:56
sal_uInt16 nTableSize
Definition: lzwdecom.hxx:57
ErrCode GetError() const
int nCount
SvStream * pIStream
Definition: lzwdecom.hxx:54
sal_uInt16 nCode
sal_uInt8 * pOutBufData
Definition: lzwdecom.hxx:64
void StartDecompression(SvStream &rIStream)
Definition: lzwdecom.cxx:52
int i
sal_uInt16 nOutBufDataLen
Definition: lzwdecom.hxx:65
SvStream & ReadUChar(unsigned char &rChar)
std::array< sal_uInt8, MAX_TABLE_SIZE > pOutBuf
Definition: lzwdecom.hxx:63
unsigned char sal_uInt8
sal_uInt16 nOldCode
Definition: lzwdecom.hxx:61
sal_uInt64 Decompress(sal_uInt8 *pTarget, sal_uInt32 nMaxCount)
Definition: lzwdecom.cxx:77
sal_uInt16 nInputBitsBufSize
Definition: lzwdecom.hxx:68
#define SAL_WARN(area, stream)
void DecompressSome()
Definition: lzwdecom.cxx:180