xref: /AOO41X/main/vcl/source/gdi/pngwrite.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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