LibreOffice Module vcl (master)  1
giflzwc.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 <tools/stream.hxx>
22 #include "giflzwc.hxx"
23 #include <array>
24 
25 
27 {
28 private:
29 
30  void FlushBlockBuf();
31  inline void FlushBitsBufsFullBytes();
32 
34  std::array<sal_uInt8, 255>
37  sal_uInt32 nBitsBuf;
38  sal_uInt16 nBitsBufSize;
39 
40 public:
41 
42  GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize );
44 
45  inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
46 };
47 
48 
50 {
51  while (nBitsBufSize>=8)
52  {
53  if( nBlockBufSize==255 )
54  FlushBlockBuf();
55 
56  pBlockBuf[nBlockBufSize++] = static_cast<sal_uInt8>(nBitsBuf);
57  nBitsBuf >>= 8;
58  nBitsBufSize -= 8;
59  }
60 }
61 
62 
63 inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
64 {
65  if( nBitsBufSize+nCodeLen>32 )
67 
68  nBitsBuf |= static_cast<sal_uInt32>(nCode) << nBitsBufSize;
69  nBitsBufSize = nBitsBufSize + nCodeLen;
70 }
71 
72 
74  rStream(rGIF), nBlockBufSize(0), nBitsBuf(0), nBitsBufSize(0)
75 {
76  rStream.WriteUChar( nLZWDataSize );
77 }
78 
79 
81 {
82  WriteBits(0,7);
84  FlushBlockBuf();
85  rStream.WriteUChar( 0 );
86 }
87 
88 
90 {
91  if( nBlockBufSize )
92  {
95  nBlockBufSize = 0;
96  }
97 }
98 
99 
101 {
102 
103  GIFLZWCTreeNode* pBrother; // next node which has the same father
105  sal_uInt16 nCode; // the code for the string of pixel values which comes about
106  sal_uInt16 nValue; // the pixel value
107 };
108 
109 
111  : pPrefix(nullptr), nDataSize(0), nClearCode(0),
112  nEOICode(0), nTableSize(0), nCodeSize(0)
113 {
114 }
115 
116 
118 {
119  if (pIDOS!=nullptr) EndCompression();
120 }
121 
122 
123 void GIFLZWCompressor::StartCompression( SvStream& rGIF, sal_uInt16 nPixelSize )
124 {
125  if( pIDOS )
126  return;
127 
128  sal_uInt16 i;
129 
130  nDataSize = nPixelSize;
131 
132  if( nDataSize < 2 )
133  nDataSize=2;
134 
139 
140  pIDOS.reset(new GIFImageDataOutputStream(rGIF,static_cast<sal_uInt8>(nDataSize)));
141  pTable.reset(new GIFLZWCTreeNode[4096]);
142 
143  for (i=0; i<4096; i++)
144  {
145  pTable[i].pBrother = pTable[i].pFirstChild = nullptr;
146  pTable[i].nCode = i;
147  pTable[i].nValue = static_cast<sal_uInt8>( i );
148  }
149 
150  pPrefix = nullptr;
151  pIDOS->WriteBits( nClearCode,nCodeSize );
152 }
153 
154 void GIFLZWCompressor::Compress(sal_uInt8* pSrc, sal_uInt32 nSize)
155 {
156  if( !pIDOS )
157  return;
158 
160  sal_uInt16 i;
161  sal_uInt8 nV;
162 
163  if( !pPrefix && nSize )
164  {
165  pPrefix=&pTable[*pSrc++];
166  nSize--;
167  }
168 
169  while( nSize )
170  {
171  nSize--;
172  nV=*pSrc++;
173  for( p=pPrefix->pFirstChild; p!=nullptr; p=p->pBrother )
174  {
175  if (p->nValue==nV)
176  break;
177  }
178 
179  if( p)
180  pPrefix=p;
181  else
182  {
183  pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
184 
185  if (nTableSize==4096)
186  {
187  pIDOS->WriteBits(nClearCode,nCodeSize);
188 
189  for (i=0; i<nClearCode; i++)
190  pTable[i].pFirstChild=nullptr;
191 
194  }
195  else
196  {
197  if(nTableSize==static_cast<sal_uInt16>(1<<nCodeSize))
198  nCodeSize++;
199 
200  p=&pTable[nTableSize++];
202  pPrefix->pFirstChild=p;
203  p->nValue=nV;
204  p->pFirstChild=nullptr;
205  }
206 
207  pPrefix=&pTable[nV];
208  }
209  }
210 }
211 
213 {
214  if( pIDOS )
215  {
216  if( pPrefix )
217  pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
218 
219  pIDOS->WriteBits( nEOICode,nCodeSize );
220  pTable.reset();
221  pIDOS.reset();
222  }
223 }
224 
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 nBitsBufSize
Definition: giflzwc.cxx:38
sal_uInt16 nCodeSize
Definition: giflzwc.hxx:41
sal_uInt16 nTableSize
Definition: giflzwc.hxx:40
GIFImageDataOutputStream(SvStream &rGIF, sal_uInt8 nLZWDataSize)
Definition: giflzwc.cxx:73
std::unique_ptr< GIFImageDataOutputStream > pIDOS
Definition: giflzwc.hxx:34
int i
sal_uInt16 nDataSize
Definition: giflzwc.hxx:37
sal_uInt16 nValue
Definition: giflzwc.cxx:106
std::size_t WriteBytes(const void *pData, std::size_t nSize)
GIFLZWCTreeNode * pBrother
Definition: giflzwc.cxx:103
GIFLZWCTreeNode * pFirstChild
Definition: giflzwc.cxx:104
std::unique_ptr< GIFLZWCTreeNode[]> pTable
Definition: giflzwc.hxx:35
sal_uInt16 nClearCode
Definition: giflzwc.hxx:38
unsigned char sal_uInt8
sal_uInt16 nCode
Definition: giflzwc.cxx:105
sal_uInt16 nEOICode
Definition: giflzwc.hxx:39
SvStream & WriteUChar(unsigned char nChar)
GIFLZWCTreeNode * pPrefix
Definition: giflzwc.hxx:36
void * p
void EndCompression()
Definition: giflzwc.cxx:212
std::array< sal_uInt8, 255 > pBlockBuf
Definition: giflzwc.cxx:35
void Compress(sal_uInt8 *pSrc, sal_uInt32 nSize)
Definition: giflzwc.cxx:154
void WriteBits(sal_uInt16 nCode, sal_uInt16 nCodeLen)
Definition: giflzwc.cxx:63
void StartCompression(SvStream &rGIF, sal_uInt16 nPixelSize)
Definition: giflzwc.cxx:123