Update ooo320-m1
[ooovba.git] / vcl / source / gdi / pngwrite.cxx
blob1c080b0c3515823e1db2e76e029d71c06da30e9c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pngwrite.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <vcl/pngwrite.hxx>
36 #include <cmath>
37 #include <limits>
38 #include <rtl/crc.h>
39 #include <rtl/memory.h>
40 #include <rtl/alloc.h>
41 #include <tools/zcodec.hxx>
42 #include <tools/stream.hxx>
43 #include <vcl/bmpacc.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/alpha.hxx>
46 #include <osl/endian.h>
48 // -----------
49 // - Defines -
50 // -----------
52 #define PNG_DEF_COMPRESSION 6
54 #define PNGCHUNK_IHDR 0x49484452
55 #define PNGCHUNK_PLTE 0x504c5445
56 #define PNGCHUNK_IDAT 0x49444154
57 #define PNGCHUNK_IEND 0x49454e44
58 #define PNGCHUNK_bKGD 0x624b4744
59 #define PNGCHUNK_cHRM 0x6348524d
60 #define PNGCHUNK_gAMA 0x67414d41
61 #define PNGCHUNK_hIST 0x68495354
62 #define PNGCHUNK_pHYs 0x70485973
63 #define PNGCHUNK_sBIT 0x73425420
64 #define PNGCHUNK_tIME 0x74494d45
65 #define PNGCHUNK_tEXt 0x74455874
66 #define PNGCHUNK_tRNS 0x74524e53
67 #define PNGCHUNK_zTXt 0x7a545874
69 namespace vcl
71 // -----------------
72 // - PNGWriterImplImpl -
73 // -----------------
75 class PNGWriterImpl
77 public:
79 PNGWriterImpl( const BitmapEx& BmpEx,
80 const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData = NULL );
81 ~PNGWriterImpl();
83 sal_Bool Write( SvStream& rOStm );
85 std::vector< vcl::PNGWriter::ChunkData >& GetChunks();
87 private:
89 std::vector< vcl::PNGWriter::ChunkData > maChunkSeq;
91 sal_Int32 mnCompLevel;
92 sal_Int32 mnInterlaced;
93 sal_uInt32 mnMaxChunkSize;
94 BOOL mbStatus;
96 BitmapReadAccess* mpAccess;
97 BitmapReadAccess* mpMaskAccess;
98 ZCodec* mpZCodec;
100 BYTE* mpDeflateInBuf; // as big as the size of a scanline + alphachannel + 1
101 BYTE* mpPreviousScan; // as big as mpDeflateInBuf
102 BYTE* mpCurrentScan;
103 ULONG mnDeflateInSize;
105 ULONG mnWidth, mnHeight;
106 BYTE mnBitsPerPixel;
107 BYTE mnFilterType; // 0 oder 4;
108 ULONG mnBBP; // bytes per pixel ( needed for filtering )
109 BOOL mbTrueAlpha;
110 ULONG mnCRC;
111 long mnChunkDatSize;
112 ULONG mnLastPercent;
114 void ImplWritepHYs( const BitmapEx& rBitmapEx );
115 void ImplWriteIDAT();
116 ULONG ImplGetFilter( ULONG nY, ULONG nXStart=0, ULONG nXAdd=1 );
117 void ImplClearFirstScanline();
118 void ImplWriteTransparent();
119 BOOL ImplWriteHeader();
120 void ImplWritePalette();
121 void ImplOpenChunk( ULONG nChunkType );
122 void ImplWriteChunk( BYTE nNumb );
123 void ImplWriteChunk( sal_uInt32 nNumb );
124 void ImplWriteChunk( unsigned char* pSource, sal_uInt32 nDatSize );
125 void ImplCloseChunk( void );
128 // ------------------------------------------------------------------------
130 PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
131 const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) :
132 mnCompLevel ( PNG_DEF_COMPRESSION ),
133 mbStatus ( TRUE ),
134 mpAccess ( NULL ),
135 mpMaskAccess ( NULL ),
136 mpZCodec ( new ZCodec( DEFAULT_IN_BUFSIZE, DEFAULT_OUT_BUFSIZE, MAX_MEM_USAGE ) ),
137 mnLastPercent ( 0UL )
139 if ( !rBmpEx.IsEmpty() )
141 Bitmap aBmp( rBmpEx.GetBitmap() );
143 mnInterlaced = 0; // ( aBmp.GetSizePixel().Width() > 128 ) || ( aBmp.GetSizePixel().Height() > 128 ) ? 1 : 0; #i67236#
145 // #i67234# defaulting max chunk size to 256kb when using interlace mode
146 mnMaxChunkSize = mnInterlaced == 0 ? std::numeric_limits< sal_uInt32 >::max() : 0x40000;
148 if ( pFilterData )
150 sal_Int32 i = 0;
151 for ( i = 0; i < pFilterData->getLength(); i++ )
153 if ( (*pFilterData)[ i ].Name.equalsAscii( "Compression" ) )
154 (*pFilterData)[ i ].Value >>= mnCompLevel;
155 else if ( (*pFilterData)[ i ].Name.equalsAscii( "Interlaced" ) )
156 (*pFilterData)[ i ].Value >>= mnInterlaced;
157 else if ( (*pFilterData)[ i ].Name.equalsAscii( "MaxChunkSize" ) )
159 sal_Int32 nVal = 0;
160 if ( (*pFilterData)[ i ].Value >>= nVal )
161 mnMaxChunkSize = (sal_uInt32)nVal;
165 mnBitsPerPixel = (BYTE)aBmp.GetBitCount();
167 if( rBmpEx.IsTransparent() )
169 if ( mnBitsPerPixel <= 8 && rBmpEx.IsAlpha() )
171 aBmp.Convert( BMP_CONVERSION_24BIT );
172 mnBitsPerPixel = 24;
175 if ( mnBitsPerPixel <= 8 ) // transparent palette
177 aBmp.Convert( BMP_CONVERSION_8BIT_TRANS );
178 aBmp.Replace( rBmpEx.GetMask(), BMP_COL_TRANS );
179 mnBitsPerPixel = 8;
180 mpAccess = aBmp.AcquireReadAccess();
181 if ( mpAccess )
183 if ( ImplWriteHeader() )
185 ImplWritepHYs( rBmpEx );
186 ImplWritePalette();
187 ImplWriteTransparent();
188 ImplWriteIDAT();
190 aBmp.ReleaseAccess( mpAccess );
192 else
193 mbStatus = FALSE;
195 else
197 mpAccess = aBmp.AcquireReadAccess(); // TRUE RGB with alphachannel
198 if( mpAccess )
200 if ( ( mbTrueAlpha = rBmpEx.IsAlpha() ) != FALSE )
202 AlphaMask aMask( rBmpEx.GetAlpha() );
203 mpMaskAccess = aMask.AcquireReadAccess();
204 if ( mpMaskAccess )
206 if ( ImplWriteHeader() )
208 ImplWritepHYs( rBmpEx );
209 ImplWriteIDAT();
211 aMask.ReleaseAccess( mpMaskAccess );
213 else
214 mbStatus = FALSE;
216 else
218 Bitmap aMask( rBmpEx.GetMask() );
219 mpMaskAccess = aMask.AcquireReadAccess();
220 if( mpMaskAccess )
222 if ( ImplWriteHeader() )
224 ImplWritepHYs( rBmpEx );
225 ImplWriteIDAT();
227 aMask.ReleaseAccess( mpMaskAccess );
229 else
230 mbStatus = FALSE;
232 aBmp.ReleaseAccess( mpAccess );
234 else
235 mbStatus = FALSE;
238 else
240 mpAccess = aBmp.AcquireReadAccess(); // palette + RGB without alphachannel
241 if( mpAccess )
243 if ( ImplWriteHeader() )
245 ImplWritepHYs( rBmpEx );
246 if( mpAccess->HasPalette() )
247 ImplWritePalette();
249 ImplWriteIDAT();
251 aBmp.ReleaseAccess( mpAccess );
253 else
254 mbStatus = FALSE;
256 if ( mbStatus )
258 ImplOpenChunk( PNGCHUNK_IEND ); // create an IEND chunk
259 ImplCloseChunk();
264 // ------------------------------------------------------------------------
266 PNGWriterImpl::~PNGWriterImpl()
268 delete mpZCodec;
271 // ------------------------------------------------------------------------
273 sal_Bool PNGWriterImpl::Write( SvStream& rOStm )
275 /* png signature is always an array of 8 bytes */
276 sal_uInt16 nOldMode = rOStm.GetNumberFormatInt();
277 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
278 rOStm << static_cast<sal_uInt32>(0x89504e47);
279 rOStm << static_cast<sal_uInt32>(0x0d0a1a0a);
281 std::vector< vcl::PNGWriter::ChunkData >::iterator aBeg( maChunkSeq.begin() );
282 std::vector< vcl::PNGWriter::ChunkData >::iterator aEnd( maChunkSeq.end() );
283 while( aBeg != aEnd )
285 sal_uInt32 nType = aBeg->nType;
286 #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
287 nType = SWAPLONG( nType );
288 #endif
289 sal_uInt32 nCRC = rtl_crc32( 0, &nType, 4 );
290 sal_uInt32 nDataSize = aBeg->aData.size();
291 if ( nDataSize )
292 nCRC = rtl_crc32( nCRC, &aBeg->aData[ 0 ], nDataSize );
293 rOStm << nDataSize
294 << aBeg->nType;
295 if ( nDataSize )
296 rOStm.Write( &aBeg->aData[ 0 ], nDataSize );
297 rOStm << nCRC;
298 aBeg++;
300 rOStm.SetNumberFormatInt( nOldMode );
301 return mbStatus;
304 // ------------------------------------------------------------------------
306 std::vector< vcl::PNGWriter::ChunkData >& PNGWriterImpl::GetChunks()
308 return maChunkSeq;
311 // ------------------------------------------------------------------------
313 BOOL PNGWriterImpl::ImplWriteHeader()
315 ImplOpenChunk(PNGCHUNK_IHDR);
316 ImplWriteChunk( sal_uInt32( mnWidth = mpAccess->Width() ) );
317 ImplWriteChunk( sal_uInt32( mnHeight = mpAccess->Height() ) );
319 if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus )
321 BYTE nBitDepth = mnBitsPerPixel;
322 if ( mnBitsPerPixel <= 8 )
323 mnFilterType = 0;
324 else
325 mnFilterType = 4;
327 BYTE nColorType = 2; // colortype:
328 // bit 0 -> palette is used
329 if ( mpAccess->HasPalette() ) // bit 1 -> color is used
330 nColorType |= 1; // bit 2 -> alpha channel is used
331 else
332 nBitDepth /= 3;
334 if ( mpMaskAccess )
335 nColorType |= 4;
337 ImplWriteChunk( nBitDepth );
338 ImplWriteChunk( nColorType ); // colortype
339 ImplWriteChunk((BYTE) 0 ); // compression type
340 ImplWriteChunk((BYTE) 0 ); // filter type - is not supported in this version
341 ImplWriteChunk((BYTE) mnInterlaced ); // interlace type
342 ImplCloseChunk();
344 else
345 mbStatus = FALSE;
346 return mbStatus;
349 // ------------------------------------------------------------------------
351 void PNGWriterImpl::ImplWritePalette()
353 const ULONG nCount = mpAccess->GetPaletteEntryCount();
354 BYTE* pTempBuf = new BYTE[ nCount*3 ];
355 BYTE* pTmp = pTempBuf;
357 ImplOpenChunk( PNGCHUNK_PLTE );
359 for ( USHORT i = 0; i < nCount; i++ )
361 const BitmapColor& rColor = mpAccess->GetPaletteColor( i );
362 *pTmp++ = rColor.GetRed();
363 *pTmp++ = rColor.GetGreen();
364 *pTmp++ = rColor.GetBlue();
366 ImplWriteChunk( pTempBuf, nCount*3 );
367 ImplCloseChunk();
368 delete[] pTempBuf;
371 // ------------------------------------------------------------------------
373 void PNGWriterImpl::ImplWriteTransparent ()
375 const ULONG nTransIndex = mpAccess->GetBestMatchingColor( BMP_COL_TRANS );
377 ImplOpenChunk( PNGCHUNK_tRNS );
379 for ( ULONG n = 0UL; n <= nTransIndex; n++ )
380 ImplWriteChunk( ( nTransIndex == n ) ? (BYTE) 0x0 : (BYTE) 0xff );
382 ImplCloseChunk();
385 // ------------------------------------------------------------------------
387 void PNGWriterImpl::ImplWritepHYs( const BitmapEx& rBmpEx )
389 if ( rBmpEx.GetPrefMapMode() == MAP_100TH_MM )
391 Size aPrefSize( rBmpEx.GetPrefSize() );
392 if ( aPrefSize.Width() && aPrefSize.Height() )
394 ImplOpenChunk( PNGCHUNK_pHYs );
395 sal_uInt8 nMapUnit = 1;
396 sal_uInt32 nPrefSizeX = (sal_uInt32)( (double)100000.0 / ( (double)aPrefSize.Width() / mnWidth ) + 0.5 );
397 sal_uInt32 nPrefSizeY = (sal_uInt32)( (double)100000.0 / ( (double)aPrefSize.Height() / mnHeight ) + 0.5 );
398 ImplWriteChunk( nPrefSizeX );
399 ImplWriteChunk( nPrefSizeY );
400 ImplWriteChunk( nMapUnit );
401 ImplCloseChunk();
406 // ------------------------------------------------------------------------
408 void PNGWriterImpl::ImplWriteIDAT ()
410 mnDeflateInSize = mnBitsPerPixel;
412 if( mpMaskAccess )
413 mnDeflateInSize += 8;
415 mnBBP = ( mnDeflateInSize + 7 ) >> 3;
417 mnDeflateInSize = mnBBP * mnWidth + 1;
419 mpDeflateInBuf = new BYTE[ mnDeflateInSize ];
421 if ( mnFilterType ) // using filter type 4 we need memory for the scanline 3 times
423 mpPreviousScan = new BYTE[ mnDeflateInSize ];
424 mpCurrentScan = new BYTE[ mnDeflateInSize ];
425 ImplClearFirstScanline();
427 mpZCodec->BeginCompression( ZCODEC_PNG_DEFAULT + mnCompLevel );
428 mpZCodec->SetCRC( mnCRC );
429 SvMemoryStream aOStm;
430 if ( mnInterlaced == 0 )
432 for ( ULONG nY = 0; nY < mnHeight; nY++ )
433 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter( nY ) );
435 else
437 // interlace mode
438 ULONG nY;
439 for ( nY = 0; nY < mnHeight; nY+=8 ) // pass 1
440 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 8 ) );
441 ImplClearFirstScanline();
443 for ( nY = 0; nY < mnHeight; nY+=8 ) // pass 2
444 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 4, 8 ) );
445 ImplClearFirstScanline();
447 if ( mnHeight >= 5 ) // pass 3
449 for ( nY = 4; nY < mnHeight; nY+=8 )
450 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 4 ) );
451 ImplClearFirstScanline();
454 for ( nY = 0; nY < mnHeight; nY+=4 ) // pass 4
455 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 2, 4 ) );
456 ImplClearFirstScanline();
458 if ( mnHeight >= 3 ) // pass 5
460 for ( nY = 2; nY < mnHeight; nY+=4 )
461 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 2 ) );
462 ImplClearFirstScanline();
465 for ( nY = 0; nY < mnHeight; nY+=2 ) // pass 6
466 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 1, 2 ) );
467 ImplClearFirstScanline();
469 if ( mnHeight >= 2 ) // pass 7
471 for ( nY = 1; nY < mnHeight; nY+=2 )
472 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 1 ) );
475 mpZCodec->EndCompression();
476 mnCRC = mpZCodec->GetCRC();
478 if ( mnFilterType ) // using filter type 4 we need memory for the scanline 3 times
480 delete[] mpCurrentScan;
481 delete[] mpPreviousScan;
483 delete[] mpDeflateInBuf;
485 sal_uInt32 nIDATSize = aOStm.Tell();
486 sal_uInt32 nBytes, nBytesToWrite = nIDATSize;
487 while( nBytesToWrite )
489 nBytes = nBytesToWrite <= mnMaxChunkSize ? nBytesToWrite : mnMaxChunkSize;
490 ImplOpenChunk( PNGCHUNK_IDAT );
491 ImplWriteChunk( (unsigned char*)aOStm.GetData() + ( nIDATSize - nBytesToWrite ), nBytes );
492 ImplCloseChunk();
493 nBytesToWrite -= nBytes;
497 // ---------------------------------------------------------------------------------------------------
498 // ImplGetFilter writes the complete Scanline (nY) - in interlace mode the parameter nXStart and nXAdd
499 // appends to the currently used pass
500 // the complete size of scanline will be returned - in interlace mode zero is possible!
502 ULONG PNGWriterImpl::ImplGetFilter ( ULONG nY, ULONG nXStart, ULONG nXAdd )
504 BYTE* pDest;
506 if ( mnFilterType )
507 pDest = mpCurrentScan;
508 else
509 pDest = mpDeflateInBuf;
511 if ( nXStart < mnWidth )
513 *pDest++ = mnFilterType; // in this version the filter type is either 0 or 4
515 if ( mpAccess->HasPalette() ) // alphachannel is not allowed by pictures including palette entries
517 switch ( mnBitsPerPixel )
519 case( 1 ):
521 ULONG nX, nXIndex;
522 for ( nX = nXStart, nXIndex = 0; nX < mnWidth; nX+=nXAdd, nXIndex++ )
524 ULONG nShift = ( nXIndex & 7 ) ^ 7;
525 if ( nShift == 7)
526 *pDest = (BYTE)(mpAccess->GetPixel( nY, nX ) << nShift);
527 else if ( nShift == 0 )
528 *pDest++ |= (BYTE) mpAccess->GetPixel( nY, nX ) << nShift;
529 else
530 *pDest |= (BYTE) mpAccess->GetPixel( nY, nX ) << nShift;
532 if ( ( nXIndex & 7 ) != 0 ) pDest++; // byte is not completely used, so the
533 } // bufferpointer is to correct
534 break;
536 case( 4 ):
538 ULONG nX, nXIndex;
539 for ( nX = nXStart, nXIndex = 0; nX < mnWidth; nX+= nXAdd, nXIndex++ )
541 if( nXIndex & 1 )
542 *pDest++ |= (BYTE) mpAccess->GetPixel( nY, nX );
543 else
544 *pDest = (BYTE) mpAccess->GetPixel( nY, nX ) << 4;
546 if ( nXIndex & 1 ) pDest++;
548 break;
550 case( 8 ):
552 for ( ULONG nX = nXStart; nX < mnWidth; nX+=nXAdd )
553 *pDest++ = mpAccess->GetPixel( nY, nX );
555 break;
557 default :
558 mbStatus = FALSE;
559 break;
562 else
564 if ( mpMaskAccess ) // mpMaskAccess != NULL -> alphachannel is to create
566 if ( mbTrueAlpha )
568 for ( ULONG nX = nXStart; nX < mnWidth; nX += nXAdd )
570 const BitmapColor& rColor = mpAccess->GetPixel( nY, nX );
571 *pDest++ = rColor.GetRed();
572 *pDest++ = rColor.GetGreen();
573 *pDest++ = rColor.GetBlue();
574 *pDest++ = 255 - mpMaskAccess->GetPixel( nY, nX );
577 else
579 const BitmapColor aTrans( mpMaskAccess->GetBestMatchingColor( Color( COL_WHITE ) ) );
581 for ( ULONG nX = nXStart; nX < mnWidth; nX+=nXAdd )
583 const BitmapColor& rColor = mpAccess->GetPixel( nY, nX );
584 *pDest++ = rColor.GetRed();
585 *pDest++ = rColor.GetGreen();
586 *pDest++ = rColor.GetBlue();
588 if( mpMaskAccess->GetPixel( nY, nX ) == aTrans )
589 *pDest++ = 0;
590 else
591 *pDest++ = 0xff;
595 else
597 for ( ULONG nX = nXStart; nX < mnWidth; nX+=nXAdd )
599 const BitmapColor& rColor = mpAccess->GetPixel( nY, nX );
600 *pDest++ = rColor.GetRed();
601 *pDest++ = rColor.GetGreen();
602 *pDest++ = rColor.GetBlue();
607 // filter type4 ( PAETH ) will be used only for 24bit graphics
608 if ( mnFilterType )
610 mnDeflateInSize = pDest - mpCurrentScan;
611 pDest = mpDeflateInBuf;
612 *pDest++ = 4; // filter type
614 ULONG na, nb, nc;
615 long np, npa, npb, npc;
617 BYTE* p1 = mpCurrentScan + 1; // Current Pixel
618 BYTE* p2 = p1 - mnBBP; // left pixel
619 BYTE* p3 = mpPreviousScan; // upper pixel
620 BYTE* p4 = p3 - mnBBP; // upperleft Pixel;
622 while ( pDest < mpDeflateInBuf + mnDeflateInSize )
624 nb = *p3++;
625 if ( p2 >= mpCurrentScan + 1 )
627 na = *p2;
628 nc = *p4;
630 else
631 na = nc = 0;
633 np = na + nb;
634 np -= nc;
635 npa = np - na;
636 npb = np - nb;
637 npc = np - nc;
638 if ( npa < 0 )
639 npa =-npa;
640 if ( npb < 0 )
641 npb =-npb;
642 if ( npc < 0 )
643 npc =-npc;
644 if ( ( npa <= npb ) && ( npa <= npc ) ) *pDest++ = *p1++ - (BYTE)na;
645 else if ( npb <= npc ) *pDest++ = *p1++ - (BYTE)nb;
646 else *pDest++ = *p1++ - (BYTE)nc;
647 p4++;
648 p2++;
650 for ( long i = 0; i < (long)( mnDeflateInSize - 1 ); i++ )
651 mpPreviousScan[ i ] = mpCurrentScan[ i + 1 ];
653 else
654 mnDeflateInSize = pDest - mpDeflateInBuf;
655 return ( mnDeflateInSize );
658 // ------------------------------------------------------------------------
660 void PNGWriterImpl::ImplClearFirstScanline()
662 if ( mnFilterType )
663 rtl_zeroMemory( mpPreviousScan, mnDeflateInSize );
666 // ------------------------------------------------------------------------
668 void PNGWriterImpl::ImplOpenChunk ( ULONG nChunkType )
670 maChunkSeq.resize( maChunkSeq.size() + 1 );
671 maChunkSeq.back().nType = nChunkType;
674 // ------------------------------------------------------------------------
676 void PNGWriterImpl::ImplWriteChunk ( BYTE nSource )
678 maChunkSeq.back().aData.push_back( nSource );
681 void PNGWriterImpl::ImplWriteChunk ( sal_uInt32 nSource )
683 vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
684 rChunkData.aData.push_back( (sal_uInt8)( nSource >> 24 ) );
685 rChunkData.aData.push_back( (sal_uInt8)( nSource >> 16 ) );
686 rChunkData.aData.push_back( (sal_uInt8)( nSource >> 8 ) );
687 rChunkData.aData.push_back( (sal_uInt8)( nSource ) );
690 void PNGWriterImpl::ImplWriteChunk ( unsigned char* pSource, sal_uInt32 nDatSize )
692 if ( nDatSize )
694 vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
695 sal_uInt32 nSize = rChunkData.aData.size();
696 rChunkData.aData.resize( nSize + nDatSize );
697 rtl_copyMemory( &rChunkData.aData[ nSize ], pSource, nDatSize );
701 // ------------------------------------------------------------------------
702 // nothing to do
703 void PNGWriterImpl::ImplCloseChunk ( void )
707 // -------------
708 // - PNGWriter -
709 // -------------
711 PNGWriter::PNGWriter( const BitmapEx& rBmpEx,
712 const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) :
713 mpImpl( new ::vcl::PNGWriterImpl( rBmpEx, pFilterData ) )
717 // ------------------------------------------------------------------------
719 PNGWriter::~PNGWriter()
721 delete mpImpl;
724 // ------------------------------------------------------------------------
726 sal_Bool PNGWriter::Write( SvStream& rIStm )
728 return mpImpl->Write( rIStm );
731 // ------------------------------------------------------------------------
733 std::vector< vcl::PNGWriter::ChunkData >& PNGWriter::GetChunks()
735 return mpImpl->GetChunks();
738 } // namespace vcl