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 assert(nBlockBufSize
!= 255 && "FlushBlockBuf ensures this is incrementable without overflow");
57 pBlockBuf
[nBlockBufSize
++] = static_cast<sal_uInt8
>(nBitsBuf
);
64 inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode
, sal_uInt16 nCodeLen
)
66 if( nBitsBufSize
+nCodeLen
>32 )
67 FlushBitsBufsFullBytes();
69 nBitsBuf
|= static_cast<sal_uInt32
>(nCode
) << nBitsBufSize
;
70 nBitsBufSize
= nBitsBufSize
+ nCodeLen
;
74 GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream
& rGIF
, sal_uInt8 nLZWDataSize
) :
75 rStream(rGIF
), nBlockBufSize(0), nBitsBuf(0), nBitsBufSize(0)
77 rStream
.WriteUChar( nLZWDataSize
);
81 GIFImageDataOutputStream::~GIFImageDataOutputStream()
84 FlushBitsBufsFullBytes();
86 rStream
.WriteUChar( 0 );
90 void GIFImageDataOutputStream::FlushBlockBuf()
94 rStream
.WriteUChar( nBlockBufSize
);
95 rStream
.WriteBytes(pBlockBuf
.data(), nBlockBufSize
);
101 struct GIFLZWCTreeNode
104 GIFLZWCTreeNode
* pBrother
; // next node which has the same father
105 GIFLZWCTreeNode
* pFirstChild
; // first
106 sal_uInt16 nCode
; // the code for the string of pixel values which comes about
107 sal_uInt16 nValue
; // the pixel value
111 GIFLZWCompressor::GIFLZWCompressor()
112 : pPrefix(nullptr), nDataSize(0), nClearCode(0),
113 nEOICode(0), nTableSize(0), nCodeSize(0)
118 GIFLZWCompressor::~GIFLZWCompressor()
120 if (pIDOS
!=nullptr) EndCompression();
124 void GIFLZWCompressor::StartCompression( SvStream
& rGIF
, sal_uInt16 nPixelSize
)
131 nDataSize
= nPixelSize
;
136 nClearCode
=1<<nDataSize
;
137 nEOICode
=nClearCode
+1;
138 nTableSize
=nEOICode
+1;
139 nCodeSize
=nDataSize
+1;
141 pIDOS
.reset(new GIFImageDataOutputStream(rGIF
,static_cast<sal_uInt8
>(nDataSize
)));
142 pTable
.reset(new GIFLZWCTreeNode
[4096]);
144 for (i
=0; i
<4096; i
++)
146 pTable
[i
].pBrother
= pTable
[i
].pFirstChild
= nullptr;
148 pTable
[i
].nValue
= static_cast<sal_uInt8
>( i
);
152 pIDOS
->WriteBits( nClearCode
,nCodeSize
);
155 void GIFLZWCompressor::Compress(sal_uInt8
* pSrc
, sal_uInt32 nSize
)
164 if( !pPrefix
&& nSize
)
166 pPrefix
=&pTable
[*pSrc
++];
174 for( p
=pPrefix
->pFirstChild
; p
!=nullptr; p
=p
->pBrother
)
184 pIDOS
->WriteBits(pPrefix
->nCode
,nCodeSize
);
186 if (nTableSize
==4096)
188 pIDOS
->WriteBits(nClearCode
,nCodeSize
);
190 for (i
=0; i
<nClearCode
; i
++)
191 pTable
[i
].pFirstChild
=nullptr;
193 nCodeSize
=nDataSize
+1;
194 nTableSize
=nEOICode
+1;
198 if(nTableSize
==static_cast<sal_uInt16
>(1<<nCodeSize
))
201 p
=&pTable
[nTableSize
++];
202 p
->pBrother
=pPrefix
->pFirstChild
;
203 pPrefix
->pFirstChild
=p
;
205 p
->pFirstChild
=nullptr;
213 void GIFLZWCompressor::EndCompression()
218 pIDOS
->WriteBits(pPrefix
->nCode
,nCodeSize
);
220 pIDOS
->WriteBits( nEOICode
,nCodeSize
);
226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */