| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_filter.hxx" |
| |
| #include <tools/stream.hxx> |
| #include "giflzwc.hxx" |
| |
| // ---------------------------- |
| // - GIFImageDataOutputStream - |
| // ---------------------------- |
| |
| class GIFImageDataOutputStream |
| { |
| private: |
| |
| void FlushBlockBuf(); |
| inline void FlushBitsBufsFullBytes(); |
| |
| SvStream& rStream; |
| sal_uInt8* pBlockBuf; |
| sal_uInt8 nBlockBufSize; |
| sal_uLong 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++] = (sal_uInt8) nBitsBuf; |
| nBitsBuf >>= 8; |
| nBitsBufSize -= 8; |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen ) |
| { |
| if( nBitsBufSize+nCodeLen>32 ) |
| FlushBitsBufsFullBytes(); |
| |
| nBitsBuf |= (sal_uLong) nCode << nBitsBufSize; |
| nBitsBufSize = nBitsBufSize + nCodeLen; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize ) : |
| rStream(rGIF) |
| { |
| pBlockBuf = new sal_uInt8[ 255 ]; |
| nBlockBufSize = 0; |
| nBitsBufSize = 0; |
| nBitsBuf = 0; |
| rStream << nLZWDataSize; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| |
| GIFImageDataOutputStream::~GIFImageDataOutputStream() |
| { |
| WriteBits(0,7); |
| FlushBitsBufsFullBytes(); |
| FlushBlockBuf(); |
| rStream << (sal_uInt8)0; |
| delete[] pBlockBuf; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void GIFImageDataOutputStream::FlushBlockBuf() |
| { |
| if( nBlockBufSize ) |
| { |
| rStream << (sal_uInt8) nBlockBufSize; |
| rStream.Write( pBlockBuf,nBlockBufSize ); |
| nBlockBufSize = 0; |
| } |
| } |
| |
| // ------------------- |
| // - GIFLZWCTreeNode - |
| // ------------------- |
| |
| struct GIFLZWCTreeNode |
| { |
| |
| GIFLZWCTreeNode* pBrother; // naechster Knoten, der den selben Vater hat |
| GIFLZWCTreeNode* pFirstChild; // erster Sohn |
| sal_uInt16 nCode; // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn |
| sal_uInt16 nValue; // Der Pixelwert |
| }; |
| |
| // -------------------- |
| // - GIFLZWCompressor - |
| // -------------------- |
| |
| GIFLZWCompressor::GIFLZWCompressor() |
| { |
| pIDOS=NULL; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| GIFLZWCompressor::~GIFLZWCompressor() |
| { |
| if (pIDOS!=NULL) 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=new GIFImageDataOutputStream(rGIF,(sal_uInt8)nDataSize); |
| pTable=new GIFLZWCTreeNode[4096]; |
| |
| for (i=0; i<4096; i++) |
| { |
| pTable[i].pBrother = pTable[i].pFirstChild = NULL; |
| pTable[i].nValue = (sal_uInt8) ( pTable[i].nCode = i ); |
| } |
| |
| pPrefix = NULL; |
| pIDOS->WriteBits( nClearCode,nCodeSize ); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void GIFLZWCompressor::Compress( HPBYTE pSrc, sal_uLong 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!=NULL; 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=NULL; |
| |
| nCodeSize=nDataSize+1; |
| nTableSize=nEOICode+1; |
| } |
| else |
| { |
| if(nTableSize==(sal_uInt16)(1<<nCodeSize)) |
| nCodeSize++; |
| |
| p=pTable+(nTableSize++); |
| p->pBrother=pPrefix->pFirstChild; |
| pPrefix->pFirstChild=p; |
| p->nValue=nV; |
| p->pFirstChild=NULL; |
| } |
| |
| pPrefix=pTable+nV; |
| } |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void GIFLZWCompressor::EndCompression() |
| { |
| if( pIDOS ) |
| { |
| if( pPrefix ) |
| pIDOS->WriteBits(pPrefix->nCode,nCodeSize); |
| |
| pIDOS->WriteBits( nEOICode,nCodeSize ); |
| delete[] pTable; |
| delete pIDOS; |
| pIDOS=NULL; |
| } |
| } |