/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <tools/stream.hxx>
#include "giflzwc.hxx"
#include <array>
class GIFImageDataOutputStream
{
private:
void FlushBlockBuf();
inline void FlushBitsBufsFullBytes();
SvStream& rStream;
std::array<sal_uInt8, 255>
pBlockBuf;
sal_uInt8 nBlockBufSize;
sal_uInt32 nBitsBuf;
sal_uInt16 nBitsBufSize;
public:
GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize );
~GIFImageDataOutputStream();
inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
};
inline void GIFImageDataOutputStream::FlushBitsBufsFullBytes()
{
while (nBitsBufSize>=8)
{
if( nBlockBufSize==255 )
FlushBlockBuf();
pBlockBuf[nBlockBufSize++] = static_cast<sal_uInt8>(nBitsBuf);
nBitsBuf >>= 8;
nBitsBufSize -= 8;
}
}
inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
{
if( nBitsBufSize+nCodeLen>32 )
FlushBitsBufsFullBytes();
nBitsBuf |= static_cast<sal_uInt32>(nCode) << nBitsBufSize;
nBitsBufSize = nBitsBufSize + nCodeLen;
}
GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize ) :
rStream(rGIF)
{
nBlockBufSize = 0;
nBitsBufSize = 0;
nBitsBuf = 0;
rStream.WriteUChar( nLZWDataSize );
}
GIFImageDataOutputStream::~GIFImageDataOutputStream()
{
WriteBits(0,7);
FlushBitsBufsFullBytes();
FlushBlockBuf();
rStream.WriteUChar( 0 );
}
void GIFImageDataOutputStream::FlushBlockBuf()
{
if( nBlockBufSize )
{
rStream.WriteUChar( nBlockBufSize );
rStream.WriteBytes(pBlockBuf.data(), nBlockBufSize);
nBlockBufSize = 0;
}
}
struct GIFLZWCTreeNode
{
GIFLZWCTreeNode* pBrother; // next node which has the same father
GIFLZWCTreeNode* pFirstChild; // first
sal_uInt16 nCode; // the code for the string of pixel values which comes about
sal_uInt16 nValue; // the pixel value
};
GIFLZWCompressor::GIFLZWCompressor()
: pPrefix(nullptr), nDataSize(0), nClearCode(0),
nEOICode(0), nTableSize(0), nCodeSize(0)
{
}
GIFLZWCompressor::~GIFLZWCompressor()
{
if (pIDOS!=nullptr) EndCompression();
}
void GIFLZWCompressor::StartCompression( SvStream& rGIF, sal_uInt16 nPixelSize )
{
if( !pIDOS )
{
sal_uInt16 i;
nDataSize = nPixelSize;
if( nDataSize < 2 )
nDataSize=2;
nClearCode=1<<nDataSize;
nEOICode=nClearCode+1;
nTableSize=nEOICode+1;
nCodeSize=nDataSize+1;
pIDOS.reset(new GIFImageDataOutputStream(rGIF,static_cast<sal_uInt8>(nDataSize)));
pTable.reset(new GIFLZWCTreeNode[4096]);
for (i=0; i<4096; i++)
{
pTable[i].pBrother = pTable[i].pFirstChild = nullptr;
pTable[i].nValue = static_cast<sal_uInt8>( pTable[i].nCode = i );
}
pPrefix = nullptr;
pIDOS->WriteBits( nClearCode,nCodeSize );
}
}
void GIFLZWCompressor::Compress(sal_uInt8* pSrc, sal_uInt32 nSize)
{
if( pIDOS )
{
GIFLZWCTreeNode* p;
sal_uInt16 i;
sal_uInt8 nV;
if( !pPrefix && nSize )
{
pPrefix=&pTable[*pSrc++];
nSize--;
}
while( nSize )
{
nSize--;
nV=*pSrc++;
for( p=pPrefix->pFirstChild; p!=nullptr; p=p->pBrother )
{
if (p->nValue==nV)
break;
}
if( p)
pPrefix=p;
else
{
pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
if (nTableSize==4096)
{
pIDOS->WriteBits(nClearCode,nCodeSize);
for (i=0; i<nClearCode; i++)
pTable[i].pFirstChild=nullptr;
nCodeSize=nDataSize+1;
nTableSize=nEOICode+1;
}
else
{
if(nTableSize==static_cast<sal_uInt16>(1<<nCodeSize))
nCodeSize++;
p=&pTable[nTableSize++];
p->pBrother=pPrefix->pFirstChild;
pPrefix->pFirstChild=p;
p->nValue=nV;
p->pFirstChild=nullptr;
}
pPrefix=&pTable[nV];
}
}
}
}
void GIFLZWCompressor::EndCompression()
{
if( pIDOS )
{
if( pPrefix )
pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
pIDOS->WriteBits( nEOICode,nCodeSize );
pTable.reset();
pIDOS.reset();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: pBlockBuf.