diff options
Diffstat (limited to 'sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx')
-rw-r--r-- | sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx | 419 |
1 files changed, 0 insertions, 419 deletions
diff --git a/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx b/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx deleted file mode 100644 index 6029e33..0000000 --- a/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx +++ /dev/null @@ -1,419 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * OpenOffice.org - a multi-platform office productivity suite - * - * The Contents of this file are made available subject to - * the terms of GNU General Public License Version 2. - * - * - * GNU General Public License, version 2 - * ============================================= - * Copyright 2005 by Sun Microsystems, Inc. - * 901 San Antonio Road, Palo Alto, CA 94303, USA - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************/ - -#include "pnghelper.hxx" -#include <sal/macros.h> - -#ifdef SYSTEM_ZLIB -#include "zlib.h" -#else -#define ZLIB_INTERNAL 1 -#include <zlib/zlib.h> -#endif - -using namespace pdfi; - -// checksum helpers, courtesy of libpng.org - -/* Table of CRCs of all 8-bit messages. */ -sal_uInt32 PngHelper::crc_table[256]; - -/* Flag: has the table been computed? Initially false. */ -bool PngHelper::bCRCTableInit = true; - -/* Make the table for a fast CRC. */ -void PngHelper::initCRCTable() -{ - for (sal_uInt32 n = 0; n < 256; n++) - { - sal_uInt32 c = n; - for (int k = 0; k < 8; k++) - { - if (c & 1) - c = 0xedb88320L ^ (c >> 1); - else - c = c >> 1; - } - crc_table[n] = c; - } - bCRCTableInit = false; -} - -/* Update a running CRC with the bytes buf[0..len-1]--the CRC - should be initialized to all 1's, and the transmitted value - is the 1's complement of the final running CRC (see the - crc() routine below)). */ - -void PngHelper::updateCRC( sal_uInt32& io_rCRC, const sal_uInt8* i_pBuf, size_t i_nLen ) -{ - if( bCRCTableInit ) - initCRCTable(); - - sal_uInt32 nCRC = io_rCRC; - for( size_t n = 0; n < i_nLen; n++ ) - nCRC = crc_table[(nCRC ^ i_pBuf[n]) & 0xff] ^ (nCRC >> 8); - io_rCRC = nCRC; -} - -sal_uInt32 PngHelper::getCRC( const sal_uInt8* i_pBuf, size_t i_nLen ) -{ - sal_uInt32 nCRC = 0xffffffff; - updateCRC( nCRC, i_pBuf, i_nLen ); - return nCRC ^ 0xffffffff; -} - -sal_uInt32 PngHelper::deflateBuffer( const Output_t* i_pBuf, size_t i_nLen, OutputBuffer& o_rOut ) -{ - size_t nOrigSize = o_rOut.size(); - - // prepare z stream - z_stream aStream; - aStream.zalloc = Z_NULL; - aStream.zfree = Z_NULL; - aStream.opaque = Z_NULL; - deflateInit( &aStream, Z_BEST_COMPRESSION ); - aStream.avail_in = uInt(i_nLen); - aStream.next_in = (Bytef*)i_pBuf; - - sal_uInt8 aOutBuf[ 32768 ]; - do - { - aStream.avail_out = sizeof( aOutBuf ); - aStream.next_out = aOutBuf; - - if( deflate( &aStream, Z_FINISH ) == Z_STREAM_ERROR ) - { - deflateEnd( &aStream ); - // scrao the data of this broken stream - o_rOut.resize( nOrigSize ); - return 0; - } - - // append compressed bytes - sal_uInt32 nCompressedBytes = sizeof( aOutBuf ) - aStream.avail_out; - if( nCompressedBytes ) - o_rOut.insert( o_rOut.end(), aOutBuf, aOutBuf+nCompressedBytes ); - - } while( aStream.avail_out == 0 ); - - // cleanup - deflateEnd( &aStream ); - - return sal_uInt32( o_rOut.size() - nOrigSize ); -} - -void PngHelper::appendFileHeader( OutputBuffer& o_rOutputBuf ) -{ - static const unsigned char aHeader[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; - - o_rOutputBuf.insert( o_rOutputBuf.end(), aHeader, aHeader + SAL_N_ELEMENTS(aHeader) ); -} - -size_t PngHelper::startChunk( const char* pChunkName, OutputBuffer& o_rOutputBuf ) -{ - size_t nIndex = sal_uInt32( o_rOutputBuf.size() ); - o_rOutputBuf.insert( o_rOutputBuf.end(), 4, (Output_t)0 ); - o_rOutputBuf.push_back( pChunkName[0] ); - o_rOutputBuf.push_back( pChunkName[1] ); - o_rOutputBuf.push_back( pChunkName[2] ); - o_rOutputBuf.push_back( pChunkName[3] ); - return nIndex; -} - -void PngHelper::set( sal_uInt32 i_nValue, OutputBuffer& o_rOutputBuf, size_t i_nIndex ) -{ - o_rOutputBuf[ i_nIndex ] = (i_nValue & 0xff000000) >> 24; - o_rOutputBuf[ i_nIndex+1 ] = (i_nValue & 0x00ff0000) >> 16; - o_rOutputBuf[ i_nIndex+2 ] = (i_nValue & 0x0000ff00) >> 8; - o_rOutputBuf[ i_nIndex+3 ] = (i_nValue & 0x000000ff); -} - -void PngHelper::endChunk( size_t nStart, OutputBuffer& o_rOutputBuf ) -{ - if( nStart+8 > o_rOutputBuf.size() ) - return; // something broken is going on - - // update chunk length - size_t nLen = o_rOutputBuf.size() - nStart; - sal_uInt32 nDataLen = sal_uInt32(nLen)-8; - set( nDataLen, o_rOutputBuf, nStart ); - - // append chunk crc - sal_uInt32 nChunkCRC = getCRC( (sal_uInt8*)&o_rOutputBuf[nStart+4], nLen-4 ); - append( nChunkCRC, o_rOutputBuf ); -} - -void PngHelper::appendIHDR( OutputBuffer& o_rOutputBuf, int width, int height, int depth, int colortype ) -{ - size_t nStart = startChunk( "IHDR", o_rOutputBuf ); - append( width, o_rOutputBuf ); - append( height, o_rOutputBuf ); - o_rOutputBuf.push_back( Output_t(depth) ); - o_rOutputBuf.push_back( Output_t(colortype) ); - o_rOutputBuf.push_back( 0 ); // compression method deflate - o_rOutputBuf.push_back( 0 ); // filtering method 0 (default) - o_rOutputBuf.push_back( 0 ); // no interlacing - endChunk( nStart, o_rOutputBuf ); -} - -void PngHelper::appendIEND( OutputBuffer& o_rOutputBuf ) -{ - size_t nStart = startChunk( "IEND", o_rOutputBuf ); - endChunk( nStart, o_rOutputBuf ); -} - -void PngHelper::createPng( OutputBuffer& o_rOutputBuf, - Stream* str, - int width, - int height, - GfxRGB& zeroColor, - GfxRGB& oneColor, - bool bIsMask - ) -{ - appendFileHeader( o_rOutputBuf ); - appendIHDR( o_rOutputBuf, width, height, 1, 3 ); - - // write palette - size_t nIdx = startChunk( "PLTE", o_rOutputBuf ); - // write colors 0 and 1 - o_rOutputBuf.push_back(colToByte(zeroColor.r)); - o_rOutputBuf.push_back(colToByte(zeroColor.g)); - o_rOutputBuf.push_back(colToByte(zeroColor.b)); - o_rOutputBuf.push_back(colToByte(oneColor.r)); - o_rOutputBuf.push_back(colToByte(oneColor.g)); - o_rOutputBuf.push_back(colToByte(oneColor.b)); - // end PLTE chunk - endChunk( nIdx, o_rOutputBuf ); - - if( bIsMask ) - { - // write tRNS chunk - nIdx = startChunk( "tRNS", o_rOutputBuf ); - o_rOutputBuf.push_back( 0xff ); - o_rOutputBuf.push_back( 0 ); - // end tRNS chunk - endChunk( nIdx, o_rOutputBuf ); - } - - // create scan line data buffer - OutputBuffer aScanlines; - int nLineSize = (width + 7)/8; - aScanlines.reserve( nLineSize * height + height ); - - str->reset(); - for( int y = 0; y < height; y++ ) - { - // determine filter type (none) for this scanline - aScanlines.push_back( 0 ); - for( int x = 0; x < nLineSize; x++ ) - aScanlines.push_back( str->getChar() ); - } - - // begin IDAT chunk for scanline data - nIdx = startChunk( "IDAT", o_rOutputBuf ); - // compress scanlines - deflateBuffer( &aScanlines[0], aScanlines.size(), o_rOutputBuf ); - // end IDAT chunk - endChunk( nIdx, o_rOutputBuf ); - - // output IEND - appendIEND( o_rOutputBuf ); -} - -void PngHelper::createPng( OutputBuffer& o_rOutputBuf, - Stream* str, - int width, int height, GfxImageColorMap* colorMap, - Stream* maskStr, - int maskWidth, int maskHeight, GfxImageColorMap* maskColorMap ) -{ - appendFileHeader( o_rOutputBuf ); - appendIHDR( o_rOutputBuf, width, height, 8, 6 ); // RGBA image - - // initialize stream - Guchar *p, *pm; - GfxRGB rgb; - GfxGray alpha; - ImageStream* imgStr = - new ImageStream(str, - width, - colorMap->getNumPixelComps(), - colorMap->getBits()); - imgStr->reset(); - - // create scan line data buffer - OutputBuffer aScanlines; - aScanlines.reserve( width*height*4 + height ); - - for( int y=0; y<height; ++y) - { - aScanlines.push_back( 0 ); - p = imgStr->getLine(); - for( int x=0; x<width; ++x) - { - colorMap->getRGB(p, &rgb); - aScanlines.push_back(colToByte(rgb.r)); - aScanlines.push_back(colToByte(rgb.g)); - aScanlines.push_back(colToByte(rgb.b)); - aScanlines.push_back( 0xff ); - - p +=colorMap->getNumPixelComps(); - } - } - - - // now fill in the mask data - - // CAUTION: originally this was done in one single loop - // it caused merry chaos; the reason is that maskStr and str are - // not independent streams, it happens that reading one advances - // the other, too. Hence the two passes are imperative ! - - // initialize mask stream - ImageStream* imgStrMask = - new ImageStream(maskStr, - maskWidth, - maskColorMap->getNumPixelComps(), - maskColorMap->getBits()); - - imgStrMask->reset(); - for( int y = 0; y < maskHeight; ++y ) - { - pm = imgStrMask->getLine(); - for( int x = 0; x < maskWidth; ++x ) - { - maskColorMap->getGray(pm,&alpha); - pm += maskColorMap->getNumPixelComps(); - int nIndex = (y*height/maskHeight) * (width*4+1) + // mapped line - (x*width/maskWidth)*4 + 1 + 3 // mapped column - ; - aScanlines[ nIndex ] = colToByte(alpha); - } - } - - delete imgStr; - delete imgStrMask; - - // begind IDAT chunk for scanline data - size_t nIdx = startChunk( "IDAT", o_rOutputBuf ); - // compress scanlines - deflateBuffer( &aScanlines[0], aScanlines.size(), o_rOutputBuf ); - // end IDAT chunk - endChunk( nIdx, o_rOutputBuf ); - // output IEND - appendIEND( o_rOutputBuf ); -} - -// one bit mask; 0 bits opaque -void PngHelper::createPng( OutputBuffer& o_rOutputBuf, - Stream* str, - int width, int height, GfxImageColorMap* colorMap, - Stream* maskStr, - int maskWidth, int maskHeight, - bool maskInvert - ) -{ - appendFileHeader( o_rOutputBuf ); - appendIHDR( o_rOutputBuf, width, height, 8, 6 ); // RGBA image - - // initialize stream - Guchar *p; - GfxRGB rgb; - ImageStream* imgStr = - new ImageStream(str, - width, - colorMap->getNumPixelComps(), - colorMap->getBits()); - imgStr->reset(); - - // create scan line data buffer - OutputBuffer aScanlines; - aScanlines.reserve( width*height*4 + height ); - - for( int y=0; y<height; ++y) - { - aScanlines.push_back( 0 ); - p = imgStr->getLine(); - for( int x=0; x<width; ++x) - { - colorMap->getRGB(p, &rgb); - aScanlines.push_back(colToByte(rgb.r)); - aScanlines.push_back(colToByte(rgb.g)); - aScanlines.push_back(colToByte(rgb.b)); - aScanlines.push_back( 0xff ); - - p +=colorMap->getNumPixelComps(); - } - } - - - // now fill in the mask data - - // CAUTION: originally this was done in one single loop - // it caused merry chaos; the reason is that maskStr and str are - // not independent streams, it happens that reading one advances - // the other, too. Hence the two passes are imperative ! - - // initialize mask stream - ImageStream* imgStrMask = - new ImageStream(maskStr, maskWidth, 1, 1); - - imgStrMask->reset(); - for( int y = 0; y < maskHeight; ++y ) - { - for( int x = 0; x < maskWidth; ++x ) - { - Guchar aPixel = 0; - imgStrMask->getPixel( &aPixel ); - int nIndex = (y*height/maskHeight) * (width*4+1) + // mapped line - (x*width/maskWidth)*4 + 1 + 3 // mapped column - ; - if( maskInvert ) - aScanlines[ nIndex ] = aPixel ? 0xff : 0x00; - else - aScanlines[ nIndex ] = aPixel ? 0x00 : 0xff; - } - } - - delete imgStr; - delete imgStrMask; - - // begind IDAT chunk for scanline data - size_t nIdx = startChunk( "IDAT", o_rOutputBuf ); - // compress scanlines - deflateBuffer( &aScanlines[0], aScanlines.size(), o_rOutputBuf ); - // end IDAT chunk - endChunk( nIdx, o_rOutputBuf ); - // output IEND - appendIEND( o_rOutputBuf ); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |