1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_vcl.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <vcl/pngwrite.hxx> 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include <cmath> 34*cdf0e10cSrcweir #include <limits> 35*cdf0e10cSrcweir #include <rtl/crc.h> 36*cdf0e10cSrcweir #include <rtl/memory.h> 37*cdf0e10cSrcweir #include <rtl/alloc.h> 38*cdf0e10cSrcweir #include <tools/zcodec.hxx> 39*cdf0e10cSrcweir #include <tools/stream.hxx> 40*cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 41*cdf0e10cSrcweir #include <vcl/svapp.hxx> 42*cdf0e10cSrcweir #include <vcl/alpha.hxx> 43*cdf0e10cSrcweir #include <osl/endian.h> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir // ----------- 46*cdf0e10cSrcweir // - Defines - 47*cdf0e10cSrcweir // ----------- 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #define PNG_DEF_COMPRESSION 6 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir #define PNGCHUNK_IHDR 0x49484452 52*cdf0e10cSrcweir #define PNGCHUNK_PLTE 0x504c5445 53*cdf0e10cSrcweir #define PNGCHUNK_IDAT 0x49444154 54*cdf0e10cSrcweir #define PNGCHUNK_IEND 0x49454e44 55*cdf0e10cSrcweir #define PNGCHUNK_bKGD 0x624b4744 56*cdf0e10cSrcweir #define PNGCHUNK_cHRM 0x6348524d 57*cdf0e10cSrcweir #define PNGCHUNK_gAMA 0x67414d41 58*cdf0e10cSrcweir #define PNGCHUNK_hIST 0x68495354 59*cdf0e10cSrcweir #define PNGCHUNK_pHYs 0x70485973 60*cdf0e10cSrcweir #define PNGCHUNK_sBIT 0x73425420 61*cdf0e10cSrcweir #define PNGCHUNK_tIME 0x74494d45 62*cdf0e10cSrcweir #define PNGCHUNK_tEXt 0x74455874 63*cdf0e10cSrcweir #define PNGCHUNK_tRNS 0x74524e53 64*cdf0e10cSrcweir #define PNGCHUNK_zTXt 0x7a545874 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir namespace vcl 67*cdf0e10cSrcweir { 68*cdf0e10cSrcweir // ----------------- 69*cdf0e10cSrcweir // - PNGWriterImplImpl - 70*cdf0e10cSrcweir // ----------------- 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir class PNGWriterImpl 73*cdf0e10cSrcweir { 74*cdf0e10cSrcweir public: 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir PNGWriterImpl( const BitmapEx& BmpEx, 77*cdf0e10cSrcweir const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData = NULL ); 78*cdf0e10cSrcweir ~PNGWriterImpl(); 79*cdf0e10cSrcweir 80*cdf0e10cSrcweir sal_Bool Write( SvStream& rOStm ); 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir std::vector< vcl::PNGWriter::ChunkData >& GetChunks(); 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir private: 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir std::vector< vcl::PNGWriter::ChunkData > maChunkSeq; 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir sal_Int32 mnCompLevel; 89*cdf0e10cSrcweir sal_Int32 mnInterlaced; 90*cdf0e10cSrcweir sal_uInt32 mnMaxChunkSize; 91*cdf0e10cSrcweir sal_Bool mbStatus; 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir BitmapReadAccess* mpAccess; 94*cdf0e10cSrcweir BitmapReadAccess* mpMaskAccess; 95*cdf0e10cSrcweir ZCodec* mpZCodec; 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir sal_uInt8* mpDeflateInBuf; // as big as the size of a scanline + alphachannel + 1 98*cdf0e10cSrcweir sal_uInt8* mpPreviousScan; // as big as mpDeflateInBuf 99*cdf0e10cSrcweir sal_uInt8* mpCurrentScan; 100*cdf0e10cSrcweir sal_uLong mnDeflateInSize; 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir sal_uLong mnWidth, mnHeight; 103*cdf0e10cSrcweir sal_uInt8 mnBitsPerPixel; 104*cdf0e10cSrcweir sal_uInt8 mnFilterType; // 0 oder 4; 105*cdf0e10cSrcweir sal_uLong mnBBP; // bytes per pixel ( needed for filtering ) 106*cdf0e10cSrcweir sal_Bool mbTrueAlpha; 107*cdf0e10cSrcweir sal_uLong mnCRC; 108*cdf0e10cSrcweir long mnChunkDatSize; 109*cdf0e10cSrcweir sal_uLong mnLastPercent; 110*cdf0e10cSrcweir 111*cdf0e10cSrcweir void ImplWritepHYs( const BitmapEx& rBitmapEx ); 112*cdf0e10cSrcweir void ImplWriteIDAT(); 113*cdf0e10cSrcweir sal_uLong ImplGetFilter( sal_uLong nY, sal_uLong nXStart=0, sal_uLong nXAdd=1 ); 114*cdf0e10cSrcweir void ImplClearFirstScanline(); 115*cdf0e10cSrcweir void ImplWriteTransparent(); 116*cdf0e10cSrcweir sal_Bool ImplWriteHeader(); 117*cdf0e10cSrcweir void ImplWritePalette(); 118*cdf0e10cSrcweir void ImplOpenChunk( sal_uLong nChunkType ); 119*cdf0e10cSrcweir void ImplWriteChunk( sal_uInt8 nNumb ); 120*cdf0e10cSrcweir void ImplWriteChunk( sal_uInt32 nNumb ); 121*cdf0e10cSrcweir void ImplWriteChunk( unsigned char* pSource, sal_uInt32 nDatSize ); 122*cdf0e10cSrcweir void ImplCloseChunk( void ); 123*cdf0e10cSrcweir }; 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir // ------------------------------------------------------------------------ 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx, 128*cdf0e10cSrcweir const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) : 129*cdf0e10cSrcweir mnCompLevel ( PNG_DEF_COMPRESSION ), 130*cdf0e10cSrcweir mbStatus ( sal_True ), 131*cdf0e10cSrcweir mpAccess ( NULL ), 132*cdf0e10cSrcweir mpMaskAccess ( NULL ), 133*cdf0e10cSrcweir mpZCodec ( new ZCodec( DEFAULT_IN_BUFSIZE, DEFAULT_OUT_BUFSIZE, MAX_MEM_USAGE ) ), 134*cdf0e10cSrcweir mnCRC(0UL), 135*cdf0e10cSrcweir mnLastPercent ( 0UL ) 136*cdf0e10cSrcweir { 137*cdf0e10cSrcweir if ( !rBmpEx.IsEmpty() ) 138*cdf0e10cSrcweir { 139*cdf0e10cSrcweir Bitmap aBmp( rBmpEx.GetBitmap() ); 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir mnInterlaced = 0; // ( aBmp.GetSizePixel().Width() > 128 ) || ( aBmp.GetSizePixel().Height() > 128 ) ? 1 : 0; #i67236# 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir // #i67234# defaulting max chunk size to 256kb when using interlace mode 144*cdf0e10cSrcweir mnMaxChunkSize = mnInterlaced == 0 ? std::numeric_limits< sal_uInt32 >::max() : 0x40000; 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir if ( pFilterData ) 147*cdf0e10cSrcweir { 148*cdf0e10cSrcweir sal_Int32 i = 0; 149*cdf0e10cSrcweir for ( i = 0; i < pFilterData->getLength(); i++ ) 150*cdf0e10cSrcweir { 151*cdf0e10cSrcweir if ( (*pFilterData)[ i ].Name.equalsAscii( "Compression" ) ) 152*cdf0e10cSrcweir (*pFilterData)[ i ].Value >>= mnCompLevel; 153*cdf0e10cSrcweir else if ( (*pFilterData)[ i ].Name.equalsAscii( "Interlaced" ) ) 154*cdf0e10cSrcweir (*pFilterData)[ i ].Value >>= mnInterlaced; 155*cdf0e10cSrcweir else if ( (*pFilterData)[ i ].Name.equalsAscii( "MaxChunkSize" ) ) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir sal_Int32 nVal = 0; 158*cdf0e10cSrcweir if ( (*pFilterData)[ i ].Value >>= nVal ) 159*cdf0e10cSrcweir mnMaxChunkSize = (sal_uInt32)nVal; 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir } 162*cdf0e10cSrcweir } 163*cdf0e10cSrcweir mnBitsPerPixel = (sal_uInt8)aBmp.GetBitCount(); 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir if( rBmpEx.IsTransparent() ) 166*cdf0e10cSrcweir { 167*cdf0e10cSrcweir if ( mnBitsPerPixel <= 8 && rBmpEx.IsAlpha() ) 168*cdf0e10cSrcweir { 169*cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_24BIT ); 170*cdf0e10cSrcweir mnBitsPerPixel = 24; 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir if ( mnBitsPerPixel <= 8 ) // transparent palette 174*cdf0e10cSrcweir { 175*cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_8BIT_TRANS ); 176*cdf0e10cSrcweir aBmp.Replace( rBmpEx.GetMask(), BMP_COL_TRANS ); 177*cdf0e10cSrcweir mnBitsPerPixel = 8; 178*cdf0e10cSrcweir mpAccess = aBmp.AcquireReadAccess(); 179*cdf0e10cSrcweir if ( mpAccess ) 180*cdf0e10cSrcweir { 181*cdf0e10cSrcweir if ( ImplWriteHeader() ) 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir ImplWritepHYs( rBmpEx ); 184*cdf0e10cSrcweir ImplWritePalette(); 185*cdf0e10cSrcweir ImplWriteTransparent(); 186*cdf0e10cSrcweir ImplWriteIDAT(); 187*cdf0e10cSrcweir } 188*cdf0e10cSrcweir aBmp.ReleaseAccess( mpAccess ); 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir else 191*cdf0e10cSrcweir mbStatus = sal_False; 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir else 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir mpAccess = aBmp.AcquireReadAccess(); // sal_True RGB with alphachannel 196*cdf0e10cSrcweir if( mpAccess ) 197*cdf0e10cSrcweir { 198*cdf0e10cSrcweir if ( ( mbTrueAlpha = rBmpEx.IsAlpha() ) != sal_False ) 199*cdf0e10cSrcweir { 200*cdf0e10cSrcweir AlphaMask aMask( rBmpEx.GetAlpha() ); 201*cdf0e10cSrcweir mpMaskAccess = aMask.AcquireReadAccess(); 202*cdf0e10cSrcweir if ( mpMaskAccess ) 203*cdf0e10cSrcweir { 204*cdf0e10cSrcweir if ( ImplWriteHeader() ) 205*cdf0e10cSrcweir { 206*cdf0e10cSrcweir ImplWritepHYs( rBmpEx ); 207*cdf0e10cSrcweir ImplWriteIDAT(); 208*cdf0e10cSrcweir } 209*cdf0e10cSrcweir aMask.ReleaseAccess( mpMaskAccess ); 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir else 212*cdf0e10cSrcweir mbStatus = sal_False; 213*cdf0e10cSrcweir } 214*cdf0e10cSrcweir else 215*cdf0e10cSrcweir { 216*cdf0e10cSrcweir Bitmap aMask( rBmpEx.GetMask() ); 217*cdf0e10cSrcweir mpMaskAccess = aMask.AcquireReadAccess(); 218*cdf0e10cSrcweir if( mpMaskAccess ) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir if ( ImplWriteHeader() ) 221*cdf0e10cSrcweir { 222*cdf0e10cSrcweir ImplWritepHYs( rBmpEx ); 223*cdf0e10cSrcweir ImplWriteIDAT(); 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir aMask.ReleaseAccess( mpMaskAccess ); 226*cdf0e10cSrcweir } 227*cdf0e10cSrcweir else 228*cdf0e10cSrcweir mbStatus = sal_False; 229*cdf0e10cSrcweir } 230*cdf0e10cSrcweir aBmp.ReleaseAccess( mpAccess ); 231*cdf0e10cSrcweir } 232*cdf0e10cSrcweir else 233*cdf0e10cSrcweir mbStatus = sal_False; 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir } 236*cdf0e10cSrcweir else 237*cdf0e10cSrcweir { 238*cdf0e10cSrcweir mpAccess = aBmp.AcquireReadAccess(); // palette + RGB without alphachannel 239*cdf0e10cSrcweir if( mpAccess ) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir if ( ImplWriteHeader() ) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir ImplWritepHYs( rBmpEx ); 244*cdf0e10cSrcweir if( mpAccess->HasPalette() ) 245*cdf0e10cSrcweir ImplWritePalette(); 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir ImplWriteIDAT(); 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir aBmp.ReleaseAccess( mpAccess ); 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir else 252*cdf0e10cSrcweir mbStatus = sal_False; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir if ( mbStatus ) 255*cdf0e10cSrcweir { 256*cdf0e10cSrcweir ImplOpenChunk( PNGCHUNK_IEND ); // create an IEND chunk 257*cdf0e10cSrcweir ImplCloseChunk(); 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir // ------------------------------------------------------------------------ 263*cdf0e10cSrcweir 264*cdf0e10cSrcweir PNGWriterImpl::~PNGWriterImpl() 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir delete mpZCodec; 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir // ------------------------------------------------------------------------ 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir sal_Bool PNGWriterImpl::Write( SvStream& rOStm ) 272*cdf0e10cSrcweir { 273*cdf0e10cSrcweir /* png signature is always an array of 8 bytes */ 274*cdf0e10cSrcweir sal_uInt16 nOldMode = rOStm.GetNumberFormatInt(); 275*cdf0e10cSrcweir rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); 276*cdf0e10cSrcweir rOStm << static_cast<sal_uInt32>(0x89504e47); 277*cdf0e10cSrcweir rOStm << static_cast<sal_uInt32>(0x0d0a1a0a); 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir std::vector< vcl::PNGWriter::ChunkData >::iterator aBeg( maChunkSeq.begin() ); 280*cdf0e10cSrcweir std::vector< vcl::PNGWriter::ChunkData >::iterator aEnd( maChunkSeq.end() ); 281*cdf0e10cSrcweir while( aBeg != aEnd ) 282*cdf0e10cSrcweir { 283*cdf0e10cSrcweir sal_uInt32 nType = aBeg->nType; 284*cdf0e10cSrcweir #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN) 285*cdf0e10cSrcweir nType = SWAPLONG( nType ); 286*cdf0e10cSrcweir #endif 287*cdf0e10cSrcweir sal_uInt32 nCRC = rtl_crc32( 0, &nType, 4 ); 288*cdf0e10cSrcweir sal_uInt32 nDataSize = aBeg->aData.size(); 289*cdf0e10cSrcweir if ( nDataSize ) 290*cdf0e10cSrcweir nCRC = rtl_crc32( nCRC, &aBeg->aData[ 0 ], nDataSize ); 291*cdf0e10cSrcweir rOStm << nDataSize 292*cdf0e10cSrcweir << aBeg->nType; 293*cdf0e10cSrcweir if ( nDataSize ) 294*cdf0e10cSrcweir rOStm.Write( &aBeg->aData[ 0 ], nDataSize ); 295*cdf0e10cSrcweir rOStm << nCRC; 296*cdf0e10cSrcweir aBeg++; 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir rOStm.SetNumberFormatInt( nOldMode ); 299*cdf0e10cSrcweir return mbStatus; 300*cdf0e10cSrcweir } 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir // ------------------------------------------------------------------------ 303*cdf0e10cSrcweir 304*cdf0e10cSrcweir std::vector< vcl::PNGWriter::ChunkData >& PNGWriterImpl::GetChunks() 305*cdf0e10cSrcweir { 306*cdf0e10cSrcweir return maChunkSeq; 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir // ------------------------------------------------------------------------ 310*cdf0e10cSrcweir 311*cdf0e10cSrcweir sal_Bool PNGWriterImpl::ImplWriteHeader() 312*cdf0e10cSrcweir { 313*cdf0e10cSrcweir ImplOpenChunk(PNGCHUNK_IHDR); 314*cdf0e10cSrcweir ImplWriteChunk( sal_uInt32( mnWidth = mpAccess->Width() ) ); 315*cdf0e10cSrcweir ImplWriteChunk( sal_uInt32( mnHeight = mpAccess->Height() ) ); 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus ) 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir sal_uInt8 nBitDepth = mnBitsPerPixel; 320*cdf0e10cSrcweir if ( mnBitsPerPixel <= 8 ) 321*cdf0e10cSrcweir mnFilterType = 0; 322*cdf0e10cSrcweir else 323*cdf0e10cSrcweir mnFilterType = 4; 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir sal_uInt8 nColorType = 2; // colortype: 326*cdf0e10cSrcweir // bit 0 -> palette is used 327*cdf0e10cSrcweir if ( mpAccess->HasPalette() ) // bit 1 -> color is used 328*cdf0e10cSrcweir nColorType |= 1; // bit 2 -> alpha channel is used 329*cdf0e10cSrcweir else 330*cdf0e10cSrcweir nBitDepth /= 3; 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir if ( mpMaskAccess ) 333*cdf0e10cSrcweir nColorType |= 4; 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir ImplWriteChunk( nBitDepth ); 336*cdf0e10cSrcweir ImplWriteChunk( nColorType ); // colortype 337*cdf0e10cSrcweir ImplWriteChunk((sal_uInt8) 0 ); // compression type 338*cdf0e10cSrcweir ImplWriteChunk((sal_uInt8) 0 ); // filter type - is not supported in this version 339*cdf0e10cSrcweir ImplWriteChunk((sal_uInt8) mnInterlaced ); // interlace type 340*cdf0e10cSrcweir ImplCloseChunk(); 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir else 343*cdf0e10cSrcweir mbStatus = sal_False; 344*cdf0e10cSrcweir return mbStatus; 345*cdf0e10cSrcweir } 346*cdf0e10cSrcweir 347*cdf0e10cSrcweir // ------------------------------------------------------------------------ 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir void PNGWriterImpl::ImplWritePalette() 350*cdf0e10cSrcweir { 351*cdf0e10cSrcweir const sal_uLong nCount = mpAccess->GetPaletteEntryCount(); 352*cdf0e10cSrcweir sal_uInt8* pTempBuf = new sal_uInt8[ nCount*3 ]; 353*cdf0e10cSrcweir sal_uInt8* pTmp = pTempBuf; 354*cdf0e10cSrcweir 355*cdf0e10cSrcweir ImplOpenChunk( PNGCHUNK_PLTE ); 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nCount; i++ ) 358*cdf0e10cSrcweir { 359*cdf0e10cSrcweir const BitmapColor& rColor = mpAccess->GetPaletteColor( i ); 360*cdf0e10cSrcweir *pTmp++ = rColor.GetRed(); 361*cdf0e10cSrcweir *pTmp++ = rColor.GetGreen(); 362*cdf0e10cSrcweir *pTmp++ = rColor.GetBlue(); 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir ImplWriteChunk( pTempBuf, nCount*3 ); 365*cdf0e10cSrcweir ImplCloseChunk(); 366*cdf0e10cSrcweir delete[] pTempBuf; 367*cdf0e10cSrcweir } 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir // ------------------------------------------------------------------------ 370*cdf0e10cSrcweir 371*cdf0e10cSrcweir void PNGWriterImpl::ImplWriteTransparent () 372*cdf0e10cSrcweir { 373*cdf0e10cSrcweir const sal_uLong nTransIndex = mpAccess->GetBestMatchingColor( BMP_COL_TRANS ); 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir ImplOpenChunk( PNGCHUNK_tRNS ); 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir for ( sal_uLong n = 0UL; n <= nTransIndex; n++ ) 378*cdf0e10cSrcweir ImplWriteChunk( ( nTransIndex == n ) ? (sal_uInt8) 0x0 : (sal_uInt8) 0xff ); 379*cdf0e10cSrcweir 380*cdf0e10cSrcweir ImplCloseChunk(); 381*cdf0e10cSrcweir } 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir // ------------------------------------------------------------------------ 384*cdf0e10cSrcweir 385*cdf0e10cSrcweir void PNGWriterImpl::ImplWritepHYs( const BitmapEx& rBmpEx ) 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir if ( rBmpEx.GetPrefMapMode() == MAP_100TH_MM ) 388*cdf0e10cSrcweir { 389*cdf0e10cSrcweir Size aPrefSize( rBmpEx.GetPrefSize() ); 390*cdf0e10cSrcweir if ( aPrefSize.Width() && aPrefSize.Height() ) 391*cdf0e10cSrcweir { 392*cdf0e10cSrcweir ImplOpenChunk( PNGCHUNK_pHYs ); 393*cdf0e10cSrcweir sal_uInt8 nMapUnit = 1; 394*cdf0e10cSrcweir sal_uInt32 nPrefSizeX = (sal_uInt32)( (double)100000.0 / ( (double)aPrefSize.Width() / mnWidth ) + 0.5 ); 395*cdf0e10cSrcweir sal_uInt32 nPrefSizeY = (sal_uInt32)( (double)100000.0 / ( (double)aPrefSize.Height() / mnHeight ) + 0.5 ); 396*cdf0e10cSrcweir ImplWriteChunk( nPrefSizeX ); 397*cdf0e10cSrcweir ImplWriteChunk( nPrefSizeY ); 398*cdf0e10cSrcweir ImplWriteChunk( nMapUnit ); 399*cdf0e10cSrcweir ImplCloseChunk(); 400*cdf0e10cSrcweir } 401*cdf0e10cSrcweir } 402*cdf0e10cSrcweir } 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir // ------------------------------------------------------------------------ 405*cdf0e10cSrcweir 406*cdf0e10cSrcweir void PNGWriterImpl::ImplWriteIDAT () 407*cdf0e10cSrcweir { 408*cdf0e10cSrcweir mnDeflateInSize = mnBitsPerPixel; 409*cdf0e10cSrcweir 410*cdf0e10cSrcweir if( mpMaskAccess ) 411*cdf0e10cSrcweir mnDeflateInSize += 8; 412*cdf0e10cSrcweir 413*cdf0e10cSrcweir mnBBP = ( mnDeflateInSize + 7 ) >> 3; 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir mnDeflateInSize = mnBBP * mnWidth + 1; 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir mpDeflateInBuf = new sal_uInt8[ mnDeflateInSize ]; 418*cdf0e10cSrcweir 419*cdf0e10cSrcweir if ( mnFilterType ) // using filter type 4 we need memory for the scanline 3 times 420*cdf0e10cSrcweir { 421*cdf0e10cSrcweir mpPreviousScan = new sal_uInt8[ mnDeflateInSize ]; 422*cdf0e10cSrcweir mpCurrentScan = new sal_uInt8[ mnDeflateInSize ]; 423*cdf0e10cSrcweir ImplClearFirstScanline(); 424*cdf0e10cSrcweir } 425*cdf0e10cSrcweir mpZCodec->BeginCompression( ZCODEC_PNG_DEFAULT + mnCompLevel ); 426*cdf0e10cSrcweir mpZCodec->SetCRC( mnCRC ); 427*cdf0e10cSrcweir SvMemoryStream aOStm; 428*cdf0e10cSrcweir if ( mnInterlaced == 0 ) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir for ( sal_uLong nY = 0; nY < mnHeight; nY++ ) 431*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter( nY ) ); 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir else 434*cdf0e10cSrcweir { 435*cdf0e10cSrcweir // interlace mode 436*cdf0e10cSrcweir sal_uLong nY; 437*cdf0e10cSrcweir for ( nY = 0; nY < mnHeight; nY+=8 ) // pass 1 438*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 8 ) ); 439*cdf0e10cSrcweir ImplClearFirstScanline(); 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir for ( nY = 0; nY < mnHeight; nY+=8 ) // pass 2 442*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 4, 8 ) ); 443*cdf0e10cSrcweir ImplClearFirstScanline(); 444*cdf0e10cSrcweir 445*cdf0e10cSrcweir if ( mnHeight >= 5 ) // pass 3 446*cdf0e10cSrcweir { 447*cdf0e10cSrcweir for ( nY = 4; nY < mnHeight; nY+=8 ) 448*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 4 ) ); 449*cdf0e10cSrcweir ImplClearFirstScanline(); 450*cdf0e10cSrcweir } 451*cdf0e10cSrcweir 452*cdf0e10cSrcweir for ( nY = 0; nY < mnHeight; nY+=4 ) // pass 4 453*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 2, 4 ) ); 454*cdf0e10cSrcweir ImplClearFirstScanline(); 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir if ( mnHeight >= 3 ) // pass 5 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir for ( nY = 2; nY < mnHeight; nY+=4 ) 459*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 2 ) ); 460*cdf0e10cSrcweir ImplClearFirstScanline(); 461*cdf0e10cSrcweir } 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir for ( nY = 0; nY < mnHeight; nY+=2 ) // pass 6 464*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 1, 2 ) ); 465*cdf0e10cSrcweir ImplClearFirstScanline(); 466*cdf0e10cSrcweir 467*cdf0e10cSrcweir if ( mnHeight >= 2 ) // pass 7 468*cdf0e10cSrcweir { 469*cdf0e10cSrcweir for ( nY = 1; nY < mnHeight; nY+=2 ) 470*cdf0e10cSrcweir mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 1 ) ); 471*cdf0e10cSrcweir } 472*cdf0e10cSrcweir } 473*cdf0e10cSrcweir mpZCodec->EndCompression(); 474*cdf0e10cSrcweir mnCRC = mpZCodec->GetCRC(); 475*cdf0e10cSrcweir 476*cdf0e10cSrcweir if ( mnFilterType ) // using filter type 4 we need memory for the scanline 3 times 477*cdf0e10cSrcweir { 478*cdf0e10cSrcweir delete[] mpCurrentScan; 479*cdf0e10cSrcweir delete[] mpPreviousScan; 480*cdf0e10cSrcweir } 481*cdf0e10cSrcweir delete[] mpDeflateInBuf; 482*cdf0e10cSrcweir 483*cdf0e10cSrcweir sal_uInt32 nIDATSize = aOStm.Tell(); 484*cdf0e10cSrcweir sal_uInt32 nBytes, nBytesToWrite = nIDATSize; 485*cdf0e10cSrcweir while( nBytesToWrite ) 486*cdf0e10cSrcweir { 487*cdf0e10cSrcweir nBytes = nBytesToWrite <= mnMaxChunkSize ? nBytesToWrite : mnMaxChunkSize; 488*cdf0e10cSrcweir ImplOpenChunk( PNGCHUNK_IDAT ); 489*cdf0e10cSrcweir ImplWriteChunk( (unsigned char*)aOStm.GetData() + ( nIDATSize - nBytesToWrite ), nBytes ); 490*cdf0e10cSrcweir ImplCloseChunk(); 491*cdf0e10cSrcweir nBytesToWrite -= nBytes; 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir } 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir // --------------------------------------------------------------------------------------------------- 496*cdf0e10cSrcweir // ImplGetFilter writes the complete Scanline (nY) - in interlace mode the parameter nXStart and nXAdd 497*cdf0e10cSrcweir // appends to the currently used pass 498*cdf0e10cSrcweir // the complete size of scanline will be returned - in interlace mode zero is possible! 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir sal_uLong PNGWriterImpl::ImplGetFilter ( sal_uLong nY, sal_uLong nXStart, sal_uLong nXAdd ) 501*cdf0e10cSrcweir { 502*cdf0e10cSrcweir sal_uInt8* pDest; 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir if ( mnFilterType ) 505*cdf0e10cSrcweir pDest = mpCurrentScan; 506*cdf0e10cSrcweir else 507*cdf0e10cSrcweir pDest = mpDeflateInBuf; 508*cdf0e10cSrcweir 509*cdf0e10cSrcweir if ( nXStart < mnWidth ) 510*cdf0e10cSrcweir { 511*cdf0e10cSrcweir *pDest++ = mnFilterType; // in this version the filter type is either 0 or 4 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir if ( mpAccess->HasPalette() ) // alphachannel is not allowed by pictures including palette entries 514*cdf0e10cSrcweir { 515*cdf0e10cSrcweir switch ( mnBitsPerPixel ) 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir case( 1 ): 518*cdf0e10cSrcweir { 519*cdf0e10cSrcweir sal_uLong nX, nXIndex; 520*cdf0e10cSrcweir for ( nX = nXStart, nXIndex = 0; nX < mnWidth; nX+=nXAdd, nXIndex++ ) 521*cdf0e10cSrcweir { 522*cdf0e10cSrcweir sal_uLong nShift = ( nXIndex & 7 ) ^ 7; 523*cdf0e10cSrcweir if ( nShift == 7) 524*cdf0e10cSrcweir *pDest = (sal_uInt8)(mpAccess->GetPixel( nY, nX ) << nShift); 525*cdf0e10cSrcweir else if ( nShift == 0 ) 526*cdf0e10cSrcweir *pDest++ |= (sal_uInt8) mpAccess->GetPixel( nY, nX ) << nShift; 527*cdf0e10cSrcweir else 528*cdf0e10cSrcweir *pDest |= (sal_uInt8) mpAccess->GetPixel( nY, nX ) << nShift; 529*cdf0e10cSrcweir } 530*cdf0e10cSrcweir if ( ( nXIndex & 7 ) != 0 ) pDest++; // byte is not completely used, so the 531*cdf0e10cSrcweir } // bufferpointer is to correct 532*cdf0e10cSrcweir break; 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir case( 4 ): 535*cdf0e10cSrcweir { 536*cdf0e10cSrcweir sal_uLong nX, nXIndex; 537*cdf0e10cSrcweir for ( nX = nXStart, nXIndex = 0; nX < mnWidth; nX+= nXAdd, nXIndex++ ) 538*cdf0e10cSrcweir { 539*cdf0e10cSrcweir if( nXIndex & 1 ) 540*cdf0e10cSrcweir *pDest++ |= (sal_uInt8) mpAccess->GetPixel( nY, nX ); 541*cdf0e10cSrcweir else 542*cdf0e10cSrcweir *pDest = (sal_uInt8) mpAccess->GetPixel( nY, nX ) << 4; 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir if ( nXIndex & 1 ) pDest++; 545*cdf0e10cSrcweir } 546*cdf0e10cSrcweir break; 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir case( 8 ): 549*cdf0e10cSrcweir { 550*cdf0e10cSrcweir for ( sal_uLong nX = nXStart; nX < mnWidth; nX+=nXAdd ) 551*cdf0e10cSrcweir *pDest++ = mpAccess->GetPixel( nY, nX ); 552*cdf0e10cSrcweir } 553*cdf0e10cSrcweir break; 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir default : 556*cdf0e10cSrcweir mbStatus = sal_False; 557*cdf0e10cSrcweir break; 558*cdf0e10cSrcweir } 559*cdf0e10cSrcweir } 560*cdf0e10cSrcweir else 561*cdf0e10cSrcweir { 562*cdf0e10cSrcweir if ( mpMaskAccess ) // mpMaskAccess != NULL -> alphachannel is to create 563*cdf0e10cSrcweir { 564*cdf0e10cSrcweir if ( mbTrueAlpha ) 565*cdf0e10cSrcweir { 566*cdf0e10cSrcweir for ( sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd ) 567*cdf0e10cSrcweir { 568*cdf0e10cSrcweir const BitmapColor& rColor = mpAccess->GetPixel( nY, nX ); 569*cdf0e10cSrcweir *pDest++ = rColor.GetRed(); 570*cdf0e10cSrcweir *pDest++ = rColor.GetGreen(); 571*cdf0e10cSrcweir *pDest++ = rColor.GetBlue(); 572*cdf0e10cSrcweir *pDest++ = 255 - mpMaskAccess->GetPixel( nY, nX ); 573*cdf0e10cSrcweir } 574*cdf0e10cSrcweir } 575*cdf0e10cSrcweir else 576*cdf0e10cSrcweir { 577*cdf0e10cSrcweir const BitmapColor aTrans( mpMaskAccess->GetBestMatchingColor( Color( COL_WHITE ) ) ); 578*cdf0e10cSrcweir 579*cdf0e10cSrcweir for ( sal_uLong nX = nXStart; nX < mnWidth; nX+=nXAdd ) 580*cdf0e10cSrcweir { 581*cdf0e10cSrcweir const BitmapColor& rColor = mpAccess->GetPixel( nY, nX ); 582*cdf0e10cSrcweir *pDest++ = rColor.GetRed(); 583*cdf0e10cSrcweir *pDest++ = rColor.GetGreen(); 584*cdf0e10cSrcweir *pDest++ = rColor.GetBlue(); 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir if( mpMaskAccess->GetPixel( nY, nX ) == aTrans ) 587*cdf0e10cSrcweir *pDest++ = 0; 588*cdf0e10cSrcweir else 589*cdf0e10cSrcweir *pDest++ = 0xff; 590*cdf0e10cSrcweir } 591*cdf0e10cSrcweir } 592*cdf0e10cSrcweir } 593*cdf0e10cSrcweir else 594*cdf0e10cSrcweir { 595*cdf0e10cSrcweir for ( sal_uLong nX = nXStart; nX < mnWidth; nX+=nXAdd ) 596*cdf0e10cSrcweir { 597*cdf0e10cSrcweir const BitmapColor& rColor = mpAccess->GetPixel( nY, nX ); 598*cdf0e10cSrcweir *pDest++ = rColor.GetRed(); 599*cdf0e10cSrcweir *pDest++ = rColor.GetGreen(); 600*cdf0e10cSrcweir *pDest++ = rColor.GetBlue(); 601*cdf0e10cSrcweir } 602*cdf0e10cSrcweir } 603*cdf0e10cSrcweir } 604*cdf0e10cSrcweir } 605*cdf0e10cSrcweir // filter type4 ( PAETH ) will be used only for 24bit graphics 606*cdf0e10cSrcweir if ( mnFilterType ) 607*cdf0e10cSrcweir { 608*cdf0e10cSrcweir mnDeflateInSize = pDest - mpCurrentScan; 609*cdf0e10cSrcweir pDest = mpDeflateInBuf; 610*cdf0e10cSrcweir *pDest++ = 4; // filter type 611*cdf0e10cSrcweir 612*cdf0e10cSrcweir sal_uLong na, nb, nc; 613*cdf0e10cSrcweir long np, npa, npb, npc; 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir sal_uInt8* p1 = mpCurrentScan + 1; // Current Pixel 616*cdf0e10cSrcweir sal_uInt8* p2 = p1 - mnBBP; // left pixel 617*cdf0e10cSrcweir sal_uInt8* p3 = mpPreviousScan; // upper pixel 618*cdf0e10cSrcweir sal_uInt8* p4 = p3 - mnBBP; // upperleft Pixel; 619*cdf0e10cSrcweir 620*cdf0e10cSrcweir while ( pDest < mpDeflateInBuf + mnDeflateInSize ) 621*cdf0e10cSrcweir { 622*cdf0e10cSrcweir nb = *p3++; 623*cdf0e10cSrcweir if ( p2 >= mpCurrentScan + 1 ) 624*cdf0e10cSrcweir { 625*cdf0e10cSrcweir na = *p2; 626*cdf0e10cSrcweir nc = *p4; 627*cdf0e10cSrcweir } 628*cdf0e10cSrcweir else 629*cdf0e10cSrcweir na = nc = 0; 630*cdf0e10cSrcweir 631*cdf0e10cSrcweir np = na + nb; 632*cdf0e10cSrcweir np -= nc; 633*cdf0e10cSrcweir npa = np - na; 634*cdf0e10cSrcweir npb = np - nb; 635*cdf0e10cSrcweir npc = np - nc; 636*cdf0e10cSrcweir if ( npa < 0 ) 637*cdf0e10cSrcweir npa =-npa; 638*cdf0e10cSrcweir if ( npb < 0 ) 639*cdf0e10cSrcweir npb =-npb; 640*cdf0e10cSrcweir if ( npc < 0 ) 641*cdf0e10cSrcweir npc =-npc; 642*cdf0e10cSrcweir if ( ( npa <= npb ) && ( npa <= npc ) ) *pDest++ = *p1++ - (sal_uInt8)na; 643*cdf0e10cSrcweir else if ( npb <= npc ) *pDest++ = *p1++ - (sal_uInt8)nb; 644*cdf0e10cSrcweir else *pDest++ = *p1++ - (sal_uInt8)nc; 645*cdf0e10cSrcweir p4++; 646*cdf0e10cSrcweir p2++; 647*cdf0e10cSrcweir } 648*cdf0e10cSrcweir for ( long i = 0; i < (long)( mnDeflateInSize - 1 ); i++ ) 649*cdf0e10cSrcweir mpPreviousScan[ i ] = mpCurrentScan[ i + 1 ]; 650*cdf0e10cSrcweir } 651*cdf0e10cSrcweir else 652*cdf0e10cSrcweir mnDeflateInSize = pDest - mpDeflateInBuf; 653*cdf0e10cSrcweir return ( mnDeflateInSize ); 654*cdf0e10cSrcweir } 655*cdf0e10cSrcweir 656*cdf0e10cSrcweir // ------------------------------------------------------------------------ 657*cdf0e10cSrcweir 658*cdf0e10cSrcweir void PNGWriterImpl::ImplClearFirstScanline() 659*cdf0e10cSrcweir { 660*cdf0e10cSrcweir if ( mnFilterType ) 661*cdf0e10cSrcweir rtl_zeroMemory( mpPreviousScan, mnDeflateInSize ); 662*cdf0e10cSrcweir } 663*cdf0e10cSrcweir 664*cdf0e10cSrcweir // ------------------------------------------------------------------------ 665*cdf0e10cSrcweir 666*cdf0e10cSrcweir void PNGWriterImpl::ImplOpenChunk ( sal_uLong nChunkType ) 667*cdf0e10cSrcweir { 668*cdf0e10cSrcweir maChunkSeq.resize( maChunkSeq.size() + 1 ); 669*cdf0e10cSrcweir maChunkSeq.back().nType = nChunkType; 670*cdf0e10cSrcweir } 671*cdf0e10cSrcweir 672*cdf0e10cSrcweir // ------------------------------------------------------------------------ 673*cdf0e10cSrcweir 674*cdf0e10cSrcweir void PNGWriterImpl::ImplWriteChunk ( sal_uInt8 nSource ) 675*cdf0e10cSrcweir { 676*cdf0e10cSrcweir maChunkSeq.back().aData.push_back( nSource ); 677*cdf0e10cSrcweir } 678*cdf0e10cSrcweir 679*cdf0e10cSrcweir void PNGWriterImpl::ImplWriteChunk ( sal_uInt32 nSource ) 680*cdf0e10cSrcweir { 681*cdf0e10cSrcweir vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back(); 682*cdf0e10cSrcweir rChunkData.aData.push_back( (sal_uInt8)( nSource >> 24 ) ); 683*cdf0e10cSrcweir rChunkData.aData.push_back( (sal_uInt8)( nSource >> 16 ) ); 684*cdf0e10cSrcweir rChunkData.aData.push_back( (sal_uInt8)( nSource >> 8 ) ); 685*cdf0e10cSrcweir rChunkData.aData.push_back( (sal_uInt8)( nSource ) ); 686*cdf0e10cSrcweir } 687*cdf0e10cSrcweir 688*cdf0e10cSrcweir void PNGWriterImpl::ImplWriteChunk ( unsigned char* pSource, sal_uInt32 nDatSize ) 689*cdf0e10cSrcweir { 690*cdf0e10cSrcweir if ( nDatSize ) 691*cdf0e10cSrcweir { 692*cdf0e10cSrcweir vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back(); 693*cdf0e10cSrcweir sal_uInt32 nSize = rChunkData.aData.size(); 694*cdf0e10cSrcweir rChunkData.aData.resize( nSize + nDatSize ); 695*cdf0e10cSrcweir rtl_copyMemory( &rChunkData.aData[ nSize ], pSource, nDatSize ); 696*cdf0e10cSrcweir } 697*cdf0e10cSrcweir } 698*cdf0e10cSrcweir 699*cdf0e10cSrcweir // ------------------------------------------------------------------------ 700*cdf0e10cSrcweir // nothing to do 701*cdf0e10cSrcweir void PNGWriterImpl::ImplCloseChunk ( void ) 702*cdf0e10cSrcweir { 703*cdf0e10cSrcweir } 704*cdf0e10cSrcweir 705*cdf0e10cSrcweir // ------------- 706*cdf0e10cSrcweir // - PNGWriter - 707*cdf0e10cSrcweir // ------------- 708*cdf0e10cSrcweir 709*cdf0e10cSrcweir PNGWriter::PNGWriter( const BitmapEx& rBmpEx, 710*cdf0e10cSrcweir const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) : 711*cdf0e10cSrcweir mpImpl( new ::vcl::PNGWriterImpl( rBmpEx, pFilterData ) ) 712*cdf0e10cSrcweir { 713*cdf0e10cSrcweir } 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir // ------------------------------------------------------------------------ 716*cdf0e10cSrcweir 717*cdf0e10cSrcweir PNGWriter::~PNGWriter() 718*cdf0e10cSrcweir { 719*cdf0e10cSrcweir delete mpImpl; 720*cdf0e10cSrcweir } 721*cdf0e10cSrcweir 722*cdf0e10cSrcweir // ------------------------------------------------------------------------ 723*cdf0e10cSrcweir 724*cdf0e10cSrcweir sal_Bool PNGWriter::Write( SvStream& rIStm ) 725*cdf0e10cSrcweir { 726*cdf0e10cSrcweir return mpImpl->Write( rIStm ); 727*cdf0e10cSrcweir } 728*cdf0e10cSrcweir 729*cdf0e10cSrcweir // ------------------------------------------------------------------------ 730*cdf0e10cSrcweir 731*cdf0e10cSrcweir std::vector< vcl::PNGWriter::ChunkData >& PNGWriter::GetChunks() 732*cdf0e10cSrcweir { 733*cdf0e10cSrcweir return mpImpl->GetChunks(); 734*cdf0e10cSrcweir } 735*cdf0e10cSrcweir 736*cdf0e10cSrcweir } // namespace vcl 737*cdf0e10cSrcweir 738