1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
26 class GIFImageDataOutputStream
31 inline void FlushBitsBufsFullBytes();
34 std::array
<sal_uInt8
, 255>
36 sal_uInt8 nBlockBufSize
;
38 sal_uInt16 nBitsBufSize
;
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 )
56 pBlockBuf
[nBlockBufSize
++] = static_cast<sal_uInt8
>(nBitsBuf
);
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()
83 FlushBitsBufsFullBytes();
85 rStream
.WriteUChar( 0 );
89 void GIFImageDataOutputStream::FlushBlockBuf()
93 rStream
.WriteUChar( nBlockBufSize
);
94 rStream
.WriteBytes(pBlockBuf
.data(), nBlockBufSize
);
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
)
130 nDataSize
= nPixelSize
;
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;
147 pTable
[i
].nValue
= static_cast<sal_uInt8
>( i
);
151 pIDOS
->WriteBits( nClearCode
,nCodeSize
);
154 void GIFLZWCompressor::Compress(sal_uInt8
* pSrc
, sal_uInt32 nSize
)
163 if( !pPrefix
&& nSize
)
165 pPrefix
=&pTable
[*pSrc
++];
173 for( p
=pPrefix
->pFirstChild
; p
!=nullptr; p
=p
->pBrother
)
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;
197 if(nTableSize
==static_cast<sal_uInt16
>(1<<nCodeSize
))
200 p
=&pTable
[nTableSize
++];
201 p
->pBrother
=pPrefix
->pFirstChild
;
202 pPrefix
->pFirstChild
=p
;
204 p
->pFirstChild
=nullptr;
212 void GIFLZWCompressor::EndCompression()
217 pIDOS
->WriteBits(pPrefix
->nCode
,nCodeSize
);
219 pIDOS
->WriteBits( nEOICode
,nCodeSize
);
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */