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