nss: upgrade to release 3.73
[LibreOffice.git] / filter / source / graphicfilter / egif / giflzwc.cxx
blob41c65d2da4c2329843bba8e750af8d8d3502fdc6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <tools/stream.hxx>
22 #include "giflzwc.hxx"
23 #include <array>
26 class GIFImageDataOutputStream
28 private:
30 void FlushBlockBuf();
31 inline void FlushBitsBufsFullBytes();
33 SvStream& rStream;
34 std::array<sal_uInt8, 255>
35 pBlockBuf;
36 sal_uInt8 nBlockBufSize;
37 sal_uInt32 nBitsBuf;
38 sal_uInt16 nBitsBufSize;
40 public:
42 GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize );
43 ~GIFImageDataOutputStream();
45 inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
49 inline void GIFImageDataOutputStream::FlushBitsBufsFullBytes()
51 while (nBitsBufSize>=8)
53 if( nBlockBufSize==255 )
54 FlushBlockBuf();
56 pBlockBuf[nBlockBufSize++] = static_cast<sal_uInt8>(nBitsBuf);
57 nBitsBuf >>= 8;
58 nBitsBufSize -= 8;
63 inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
65 if( nBitsBufSize+nCodeLen>32 )
66 FlushBitsBufsFullBytes();
68 nBitsBuf |= static_cast<sal_uInt32>(nCode) << nBitsBufSize;
69 nBitsBufSize = nBitsBufSize + nCodeLen;
73 GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize ) :
74 rStream(rGIF), nBlockBufSize(0), nBitsBuf(0), nBitsBufSize(0)
76 rStream.WriteUChar( nLZWDataSize );
80 GIFImageDataOutputStream::~GIFImageDataOutputStream()
82 WriteBits(0,7);
83 FlushBitsBufsFullBytes();
84 FlushBlockBuf();
85 rStream.WriteUChar( 0 );
89 void GIFImageDataOutputStream::FlushBlockBuf()
91 if( nBlockBufSize )
93 rStream.WriteUChar( nBlockBufSize );
94 rStream.WriteBytes(pBlockBuf.data(), nBlockBufSize);
95 nBlockBufSize = 0;
100 struct GIFLZWCTreeNode
103 GIFLZWCTreeNode* pBrother; // next node which has the same father
104 GIFLZWCTreeNode* pFirstChild; // first
105 sal_uInt16 nCode; // the code for the string of pixel values which comes about
106 sal_uInt16 nValue; // the pixel value
110 GIFLZWCompressor::GIFLZWCompressor()
111 : pPrefix(nullptr), nDataSize(0), nClearCode(0),
112 nEOICode(0), nTableSize(0), nCodeSize(0)
117 GIFLZWCompressor::~GIFLZWCompressor()
119 if (pIDOS!=nullptr) EndCompression();
123 void GIFLZWCompressor::StartCompression( SvStream& rGIF, sal_uInt16 nPixelSize )
125 if( pIDOS )
126 return;
128 sal_uInt16 i;
130 nDataSize = nPixelSize;
132 if( nDataSize < 2 )
133 nDataSize=2;
135 nClearCode=1<<nDataSize;
136 nEOICode=nClearCode+1;
137 nTableSize=nEOICode+1;
138 nCodeSize=nDataSize+1;
140 pIDOS.reset(new GIFImageDataOutputStream(rGIF,static_cast<sal_uInt8>(nDataSize)));
141 pTable.reset(new GIFLZWCTreeNode[4096]);
143 for (i=0; i<4096; i++)
145 pTable[i].pBrother = pTable[i].pFirstChild = nullptr;
146 pTable[i].nCode = i;
147 pTable[i].nValue = static_cast<sal_uInt8>( i );
150 pPrefix = nullptr;
151 pIDOS->WriteBits( nClearCode,nCodeSize );
154 void GIFLZWCompressor::Compress(sal_uInt8* pSrc, sal_uInt32 nSize)
156 if( !pIDOS )
157 return;
159 GIFLZWCTreeNode* p;
160 sal_uInt16 i;
161 sal_uInt8 nV;
163 if( !pPrefix && nSize )
165 pPrefix=&pTable[*pSrc++];
166 nSize--;
169 while( nSize )
171 nSize--;
172 nV=*pSrc++;
173 for( p=pPrefix->pFirstChild; p!=nullptr; p=p->pBrother )
175 if (p->nValue==nV)
176 break;
179 if( p)
180 pPrefix=p;
181 else
183 pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
185 if (nTableSize==4096)
187 pIDOS->WriteBits(nClearCode,nCodeSize);
189 for (i=0; i<nClearCode; i++)
190 pTable[i].pFirstChild=nullptr;
192 nCodeSize=nDataSize+1;
193 nTableSize=nEOICode+1;
195 else
197 if(nTableSize==static_cast<sal_uInt16>(1<<nCodeSize))
198 nCodeSize++;
200 p=&pTable[nTableSize++];
201 p->pBrother=pPrefix->pFirstChild;
202 pPrefix->pFirstChild=p;
203 p->nValue=nV;
204 p->pFirstChild=nullptr;
207 pPrefix=&pTable[nV];
212 void GIFLZWCompressor::EndCompression()
214 if( pIDOS )
216 if( pPrefix )
217 pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
219 pIDOS->WriteBits( nEOICode,nCodeSize );
220 pTable.reset();
221 pIDOS.reset();
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */