xref: /AOO41X/main/filter/source/graphicfilter/egif/giflzwc.cxx (revision 9e0fc027f109ec4ffcb6033aeec742a099701108)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include <tools/stream.hxx>
28 #include "giflzwc.hxx"
29 
30 // ----------------------------
31 // - GIFImageDataOutputStream -
32 // ----------------------------
33 
34 class GIFImageDataOutputStream
35 {
36 private:
37 
38     void        FlushBlockBuf();
39     inline void FlushBitsBufsFullBytes();
40 
41     SvStream&   rStream;
42     sal_uInt8*      pBlockBuf;
43     sal_uInt8       nBlockBufSize;
44     sal_uLong       nBitsBuf;
45     sal_uInt16      nBitsBufSize;
46 
47 public:
48 
49                 GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize );
50                 ~GIFImageDataOutputStream();
51 
52     inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
53 };
54 
55 // ------------------------------------------------------------------------
56 
FlushBitsBufsFullBytes()57 inline void GIFImageDataOutputStream::FlushBitsBufsFullBytes()
58 {
59     while (nBitsBufSize>=8)
60     {
61         if( nBlockBufSize==255 )
62             FlushBlockBuf();
63 
64         pBlockBuf[nBlockBufSize++] = (sal_uInt8) nBitsBuf;
65         nBitsBuf >>= 8;
66         nBitsBufSize -= 8;
67     }
68 }
69 
70 // ------------------------------------------------------------------------
71 
WriteBits(sal_uInt16 nCode,sal_uInt16 nCodeLen)72 inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
73 {
74     if( nBitsBufSize+nCodeLen>32 )
75         FlushBitsBufsFullBytes();
76 
77     nBitsBuf |= (sal_uLong) nCode << nBitsBufSize;
78     nBitsBufSize = nBitsBufSize + nCodeLen;
79 }
80 
81 // ------------------------------------------------------------------------
82 
GIFImageDataOutputStream(SvStream & rGIF,sal_uInt8 nLZWDataSize)83 GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize ) :
84         rStream(rGIF)
85 {
86     pBlockBuf = new sal_uInt8[ 255 ];
87     nBlockBufSize = 0;
88     nBitsBufSize = 0;
89     nBitsBuf = 0;
90     rStream << nLZWDataSize;
91 }
92 
93 // ------------------------------------------------------------------------
94 
95 
~GIFImageDataOutputStream()96 GIFImageDataOutputStream::~GIFImageDataOutputStream()
97 {
98     WriteBits(0,7);
99     FlushBitsBufsFullBytes();
100     FlushBlockBuf();
101     rStream << (sal_uInt8)0;
102     delete[] pBlockBuf;
103 }
104 
105 // ------------------------------------------------------------------------
106 
FlushBlockBuf()107 void GIFImageDataOutputStream::FlushBlockBuf()
108 {
109     if( nBlockBufSize )
110     {
111         rStream << (sal_uInt8) nBlockBufSize;
112         rStream.Write( pBlockBuf,nBlockBufSize );
113         nBlockBufSize = 0;
114     }
115 }
116 
117 // -------------------
118 // - GIFLZWCTreeNode -
119 // -------------------
120 
121 struct GIFLZWCTreeNode
122 {
123 
124     GIFLZWCTreeNode*    pBrother;       // naechster Knoten, der den selben Vater hat
125     GIFLZWCTreeNode*    pFirstChild;    // erster Sohn
126     sal_uInt16              nCode;          // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn
127     sal_uInt16              nValue;         // Der Pixelwert
128 };
129 
130 // --------------------
131 // - GIFLZWCompressor -
132 // --------------------
133 
GIFLZWCompressor()134 GIFLZWCompressor::GIFLZWCompressor()
135 {
136     pIDOS=NULL;
137 }
138 
139 // ------------------------------------------------------------------------
140 
~GIFLZWCompressor()141 GIFLZWCompressor::~GIFLZWCompressor()
142 {
143     if (pIDOS!=NULL) EndCompression();
144 }
145 
146 // ------------------------------------------------------------------------
147 
StartCompression(SvStream & rGIF,sal_uInt16 nPixelSize)148 void GIFLZWCompressor::StartCompression( SvStream& rGIF, sal_uInt16 nPixelSize )
149 {
150     if( !pIDOS )
151     {
152         sal_uInt16 i;
153 
154         nDataSize = nPixelSize;
155 
156         if( nDataSize < 2 )
157             nDataSize=2;
158 
159         nClearCode=1<<nDataSize;
160         nEOICode=nClearCode+1;
161         nTableSize=nEOICode+1;
162         nCodeSize=nDataSize+1;
163 
164         pIDOS=new GIFImageDataOutputStream(rGIF,(sal_uInt8)nDataSize);
165         pTable=new GIFLZWCTreeNode[4096];
166 
167         for (i=0; i<4096; i++)
168         {
169             pTable[i].pBrother = pTable[i].pFirstChild = NULL;
170             pTable[i].nValue = (sal_uInt8) ( pTable[i].nCode = i );
171         }
172 
173         pPrefix = NULL;
174         pIDOS->WriteBits( nClearCode,nCodeSize );
175     }
176 }
177 
178 // ------------------------------------------------------------------------
179 
Compress(HPBYTE pSrc,sal_uLong nSize)180 void GIFLZWCompressor::Compress( HPBYTE pSrc, sal_uLong nSize )
181 {
182     if( pIDOS )
183     {
184         GIFLZWCTreeNode*    p;
185         sal_uInt16              i;
186         sal_uInt8               nV;
187 
188         if( !pPrefix && nSize )
189         {
190             pPrefix=pTable+(*pSrc++);
191             nSize--;
192         }
193 
194         while( nSize )
195         {
196             nSize--;
197             nV=*pSrc++;
198             for( p=pPrefix->pFirstChild; p!=NULL; p=p->pBrother )
199             {
200                 if (p->nValue==nV)
201                     break;
202             }
203 
204             if( p)
205                 pPrefix=p;
206             else
207             {
208                 pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
209 
210                 if (nTableSize==4096)
211                 {
212                     pIDOS->WriteBits(nClearCode,nCodeSize);
213 
214                     for (i=0; i<nClearCode; i++)
215                         pTable[i].pFirstChild=NULL;
216 
217                     nCodeSize=nDataSize+1;
218                     nTableSize=nEOICode+1;
219                 }
220                 else
221                 {
222                     if(nTableSize==(sal_uInt16)(1<<nCodeSize))
223                         nCodeSize++;
224 
225                     p=pTable+(nTableSize++);
226                     p->pBrother=pPrefix->pFirstChild;
227                     pPrefix->pFirstChild=p;
228                     p->nValue=nV;
229                     p->pFirstChild=NULL;
230                 }
231 
232                 pPrefix=pTable+nV;
233             }
234         }
235     }
236 }
237 
238 // ------------------------------------------------------------------------
239 
EndCompression()240 void GIFLZWCompressor::EndCompression()
241 {
242     if( pIDOS )
243     {
244         if( pPrefix )
245             pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
246 
247         pIDOS->WriteBits( nEOICode,nCodeSize );
248         delete[] pTable;
249         delete pIDOS;
250         pIDOS=NULL;
251     }
252 }
253