xref: /aoo41x/main/vcl/source/gdi/salmisc.cxx (revision 9f62ea84)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include <rtl/memory.h>
27 #include <vcl/bmpacc.hxx>
28 #include <vcl/salbtype.hxx>
29 #include <bmpfast.hxx>
30 
31 // -----------
32 // - Defines -
33 // -----------
34 
35 #define IMPL_CASE_GET_FORMAT( Format )							\
36 case( BMP_FORMAT##Format ):									\
37 	pFncGetPixel = BitmapReadAccess::GetPixelFor##Format;		\
38 break
39 
40 // -----------------------------------------------------------------------------
41 
42 #define IMPL_CASE_SET_FORMAT( Format, BitCount )				\
43 case( BMP_FORMAT##Format ):									\
44 {																\
45 	pFncSetPixel = BitmapReadAccess::SetPixelFor##Format;		\
46 	pDstBuffer->mnBitCount = BitCount;							\
47 }																\
48 break
49 
50 // -----------------------------------------------------------------------------
51 
52 #define DOUBLE_SCANLINES()														\
53 while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) )				\
54 {																				\
55 	memcpy( pDstScanMap[ nActY + 1L ], pDstScan, rDstBuffer.mnScanlineSize );	\
56 	nActY++;																	\
57 }
58 
59 // -----------
60 // - Inlines -
61 // -----------
62 
63 #define TC_TO_PAL_COLORS	4096
64 
65 static long ImplIndexFromColor( const BitmapColor& rCol )
66 {
67 #if TC_TO_PAL_COLORS == 4096
68 
69 	return( ( ( (long) rCol.GetBlue() >> 4L) << 8L ) |
70 			( ( (long) rCol.GetGreen() >> 4L ) << 4L ) |
71 			( (long) rCol.GetRed() >> 4L ) );
72 
73 #elif TC_TO_PAL_COLORS == 32768
74 
75 	return( ( ( (long) rCol.GetBlue() >> 3L) << 10L ) |
76 			( ( (long) rCol.GetGreen() >> 3L ) << 5L ) |
77 			( (long) rCol.GetRed() >> 3L ) );
78 
79 #endif
80 }
81 
82 
83 #define COLOR_TO_INDEX( _def_rCol )
84 
85 // ------------------------
86 // - conversion functions -
87 // ------------------------
88 
89 static void	ImplPALToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
90 						  FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
91 						  Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
92 {
93 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
94 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
95 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
96 	BitmapPalette		aColMap( rSrcBuffer.maPalette.GetEntryCount() );
97 	BitmapColor*		pColMapBuf = aColMap.ImplGetColorBuffer();
98 	BitmapColor			aIndex( 0 );
99 
100 	for( sal_uInt16 i = 0, nSrcCount = aColMap.GetEntryCount(), nDstCount = rDstBuffer.maPalette.GetEntryCount(); i < nSrcCount; i++ )
101 	{
102 	    if( ( i < nDstCount ) && ( rSrcBuffer.maPalette[ i ] == rDstBuffer.maPalette[ i ] ) )
103 		    aIndex.SetIndex( sal::static_int_cast<sal_uInt8>(i) );
104 		else
105 			aIndex.SetIndex( sal::static_int_cast<sal_uInt8>(rDstBuffer.maPalette.GetBestIndex( rSrcBuffer.maPalette[ i ] )) );
106 
107 		pColMapBuf[ i ] = aIndex;
108 	}
109 
110 	for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
111 	{
112 		Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
113 
114 		for( long nX = 0L; nX < nWidth; nX++ )
115 			pFncSetPixel( pDstScan, nX, pColMapBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
116 
117 		DOUBLE_SCANLINES();
118 	}
119 }
120 
121 // -----------------------------------------------------------------------------
122 
123 static void	ImplPALToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
124 						 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
125 						 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
126 {
127 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
128 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
129 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
130 	const BitmapColor*	pColBuf = rSrcBuffer.maPalette.ImplGetColorBuffer();
131 
132 	if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_1BIT_MSB_PAL )
133 	{
134 		const BitmapColor	aCol0( pColBuf[ 0 ] );
135 		const BitmapColor	aCol1( pColBuf[ 1 ] );
136 		long				nMapX;
137 
138 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
139 		{
140 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
141 
142 			for( long nX = 0L; nX < nWidth; )
143 			{
144 				nMapX = pMapX[ nX ];
145 				pFncSetPixel( pDstScan, nX++,
146 							  pSrcScan[ nMapX >> 3 ] & ( 1 << ( 7 - ( nMapX & 7 ) ) ) ? aCol1 : aCol0,
147 							  rDstMask );
148 			}
149 
150 			DOUBLE_SCANLINES();
151 		}
152 	}
153 	else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_4BIT_MSN_PAL )
154 	{
155 		long nMapX;
156 
157 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
158 		{
159 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
160 
161 			for( long nX = 0L; nX < nWidth; )
162 			{
163 				nMapX = pMapX[ nX ];
164 				pFncSetPixel( pDstScan, nX++,
165 							  pColBuf[ ( pSrcScan[ nMapX >> 1 ] >> ( nMapX & 1 ? 0 : 4 ) ) & 0x0f ],
166 							  rDstMask );
167 			}
168 
169 			DOUBLE_SCANLINES();
170 		}
171 	}
172 	else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_8BIT_PAL )
173 	{
174 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
175 		{
176 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
177 
178 			for( long nX = 0L; nX < nWidth; nX++ )
179 				pFncSetPixel( pDstScan, nX, pColBuf[ pSrcScan[ pMapX[ nX ] ] ], rDstMask );
180 
181 			DOUBLE_SCANLINES();
182 		}
183 	}
184 	else
185 	{
186 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
187 		{
188 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
189 
190 			for( long nX = 0L; nX < nWidth; nX++ )
191 				pFncSetPixel( pDstScan, nX, pColBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
192 
193 			DOUBLE_SCANLINES();
194 		}
195 	}
196 }
197 
198 // -----------------------------------------------------------------------------
199 
200 static void	ImplTCToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
201 						FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
202 						Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
203 {
204 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
205 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
206 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
207 
208 	if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_24BIT_TC_BGR )
209 	{
210 		BitmapColor aCol;
211 		sal_uInt8*		pPixel;
212 
213 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
214 		{
215 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
216 
217 			for( long nX = 0L; nX < nWidth; nX++ )
218 			{
219 				aCol.SetBlue( *( pPixel = ( pSrcScan + pMapX[ nX ] * 3 ) )++ );
220 				aCol.SetGreen( *pPixel++ );
221 				aCol.SetRed( *pPixel );
222 				pFncSetPixel( pDstScan, nX, aCol, rDstMask );
223 			}
224 
225 			DOUBLE_SCANLINES()
226 		}
227 	}
228 	else
229 	{
230 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
231 		{
232 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
233 
234 			for( long nX = 0L; nX < nWidth; nX++ )
235 				pFncSetPixel( pDstScan, nX, pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ), rDstMask );
236 
237 			DOUBLE_SCANLINES();
238 		}
239 	}
240 }
241 
242 // -----------------------------------------------------------------------------
243 
244 static void	ImplTCToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
245 						 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
246 						 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
247 {
248 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
249 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
250 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
251 	BitmapPalette		aColMap( rSrcBuffer.maPalette.GetEntryCount() );
252 	sal_uInt8*				pColToPalMap = new sal_uInt8[ TC_TO_PAL_COLORS ];
253 	BitmapColor			aIndex( 0 );
254 
255 	for( long nR = 0; nR < 16; nR++ )
256 	{
257 		for( long nG = 0; nG < 16; nG++ )
258 		{
259 			for( long nB = 0; nB < 16; nB++ )
260 			{
261 				BitmapColor aCol( sal::static_int_cast<sal_uInt8>(nR << 4),
262                                   sal::static_int_cast<sal_uInt8>(nG << 4),
263                                   sal::static_int_cast<sal_uInt8>(nB << 4) );
264 				pColToPalMap[ ImplIndexFromColor( aCol ) ] = (sal_uInt8) rDstBuffer.maPalette.GetBestIndex( aCol );
265 			}
266 		}
267 	}
268 
269 	for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
270 	{
271 		Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
272 
273 		for( long nX = 0L; nX < nWidth; nX++ )
274 		{
275 			aIndex.SetIndex( pColToPalMap[ ImplIndexFromColor( pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ) ) ] );
276 			pFncSetPixel( pDstScan, nX, aIndex, rDstMask );
277 		}
278 
279 		DOUBLE_SCANLINES();
280 	}
281 
282 	delete[] pColToPalMap;
283 }
284 
285 // -----------------------------------------------------------------------------
286 
287 // ---------------------
288 // - StretchAndConvert -
289 // ---------------------
290 
291 BitmapBuffer* StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect,
292 								 sal_uLong nDstBitmapFormat, BitmapPalette* pDstPal, ColorMask* pDstMask )
293 {
294     FncGetPixel		pFncGetPixel;
295     FncSetPixel		pFncSetPixel;
296 	BitmapBuffer*	pDstBuffer = new BitmapBuffer;
297     long            i;
298 
299 	// set function for getting pixels
300 	switch( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) )
301 	{
302 		IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL );
303 		IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL );
304 		IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL );
305 		IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL );
306 		IMPL_CASE_GET_FORMAT( _8BIT_PAL );
307 		IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK );
308 		IMPL_CASE_GET_FORMAT( _16BIT_TC_MSB_MASK );
309 		IMPL_CASE_GET_FORMAT( _16BIT_TC_LSB_MASK );
310 		IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR );
311 		IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB );
312 		IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK );
313 		IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR );
314 		IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB );
315 		IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA );
316 		IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA );
317 		IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK );
318 
319 		default:
320             // should never come here
321             // initialize pFncGetPixel to something valid that is
322             // least likely to crash
323             pFncGetPixel = BitmapReadAccess::GetPixelFor_1BIT_MSB_PAL;
324 			DBG_ERROR( "unknown read format" );
325 		break;
326 	}
327 
328 	// set function for setting pixels
329     const sal_uLong nDstScanlineFormat = BMP_SCANLINE_FORMAT( nDstBitmapFormat );
330 	switch( nDstScanlineFormat )
331 	{
332 		IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL, 1 );
333 		IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL, 1 );
334 		IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL, 1 );
335 		IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL, 4 );
336 		IMPL_CASE_SET_FORMAT( _8BIT_PAL, 8 );
337 		IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK, 8 );
338 		IMPL_CASE_SET_FORMAT( _16BIT_TC_MSB_MASK, 16 );
339 		IMPL_CASE_SET_FORMAT( _16BIT_TC_LSB_MASK, 16 );
340 		IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR, 24 );
341 		IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB, 24 );
342 		IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK, 24 );
343 		IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR, 32 );
344 		IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB, 32 );
345 		IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA, 32 );
346 		IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA, 32 );
347 		IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK, 32 );
348 
349 		default:
350             // should never come here
351             // initialize pFncSetPixel to something valid that is
352             // least likely to crash
353             pFncSetPixel = BitmapReadAccess::SetPixelFor_1BIT_MSB_PAL;
354             pDstBuffer->mnBitCount = 1;
355 			DBG_ERROR( "unknown write format" );
356 		break;
357 	}
358 
359 	// fill destination buffer
360 	pDstBuffer->mnFormat = nDstBitmapFormat;
361 	pDstBuffer->mnWidth = rTwoRect.mnDestWidth;
362 	pDstBuffer->mnHeight = rTwoRect.mnDestHeight;
363 	pDstBuffer->mnScanlineSize = AlignedWidth4Bytes( pDstBuffer->mnBitCount * pDstBuffer->mnWidth );
364     try
365     {
366         pDstBuffer->mpBits = new sal_uInt8[ pDstBuffer->mnScanlineSize * pDstBuffer->mnHeight ];
367     }
368     catch( const std::bad_alloc& )
369     {
370         // memory exception, clean up
371         pDstBuffer->mpBits = NULL;
372         delete pDstBuffer;
373         return NULL;
374     }
375 
376 	// do we need a destination palette or color mask?
377 	if( ( nDstScanlineFormat == BMP_FORMAT_1BIT_MSB_PAL ) ||
378 		( nDstScanlineFormat == BMP_FORMAT_1BIT_LSB_PAL ) ||
379 		( nDstScanlineFormat == BMP_FORMAT_4BIT_MSN_PAL ) ||
380 		( nDstScanlineFormat == BMP_FORMAT_4BIT_LSN_PAL ) ||
381 		( nDstScanlineFormat == BMP_FORMAT_8BIT_PAL ) )
382 	{
383 		DBG_ASSERT( pDstPal, "destination buffer requires palette" );
384 		pDstBuffer->maPalette = *pDstPal;
385 	}
386 	else if( ( nDstScanlineFormat == BMP_FORMAT_8BIT_TC_MASK ) ||
387 			 ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_MSB_MASK ) ||
388 			 ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_LSB_MASK ) ||
389 			 ( nDstScanlineFormat == BMP_FORMAT_24BIT_TC_MASK ) ||
390 			 ( nDstScanlineFormat == BMP_FORMAT_32BIT_TC_MASK ) )
391 	{
392 		DBG_ASSERT( pDstMask, "destination buffer requires color mask" );
393 		pDstBuffer->maColorMask = *pDstMask;
394 	}
395 
396     // short circuit the most important conversions
397     bool bFastConvert = ImplFastBitmapConversion( *pDstBuffer, rSrcBuffer, rTwoRect );
398     if( bFastConvert )
399         return pDstBuffer;
400 
401     const long      nSrcX = rTwoRect.mnSrcX, nSrcY = rTwoRect.mnSrcY;
402     const long      nSrcDX = rTwoRect.mnSrcWidth, nSrcDY = rTwoRect.mnSrcHeight;
403     const long      nDstDX = rTwoRect.mnDestWidth, nDstDY = rTwoRect.mnDestHeight;
404     Scanline*       pSrcScan = NULL;
405     Scanline*       pDstScan = NULL;
406     long*           pMapX = NULL;
407     long*           pMapY = NULL;
408     long            nTmp, nOffset;
409 
410     try
411     {
412         pSrcScan = new Scanline[ rSrcBuffer.mnHeight ];
413         pDstScan = new Scanline[ nDstDY ];
414         pMapX = new long[ nDstDX ];
415         pMapY = new long[ nDstDY ];
416     }
417     catch( const std::bad_alloc& )
418     {
419         // memory exception, clean up
420         // remark: the buffer ptr causing the exception
421         // is still NULL here
422         delete[] pSrcScan;
423         delete[] pDstScan;
424         delete[] pMapX;
425         delete[] pMapY;
426         delete pDstBuffer;
427         return NULL;
428     }
429 
430     // horizontal mapping table
431 	if( nDstDX != nSrcDX )
432 	{
433 		const double fFactorX = ( nDstDX > 1 ) ? (double) ( nSrcDX - 1 ) / ( nDstDX - 1 ) : 0.0;
434 
435 		for( i = 0L; i < nDstDX; i++ )
436 			pMapX[ i ] = nSrcX + FRound( i * fFactorX );
437 	}
438 	else
439 	{
440 		for( i = 0L, nTmp = nSrcX; i < nDstDX; i++ )
441 			pMapX[ i ] = nTmp++;
442 	}
443 
444 	// vertical mapping table
445 	if( nDstDY != nSrcDY )
446 	{
447 		const double fFactorY = ( nDstDY > 1 ) ? (double) ( nSrcDY - 1 ) / ( nDstDY - 1 ) : 0.0;
448 
449 		for( i = 0L; i < nDstDY; i++ )
450 			pMapY[ i ] = nSrcY + FRound( i * fFactorY );
451 	}
452 	else
453 	{
454 		for( i = 0L, nTmp = nSrcY; i < nDstDY; i++ )
455 			pMapY[ i ] = nTmp++;
456 	}
457 
458 	// source scanline buffer
459     Scanline pTmpScan;
460 	if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer.mnFormat ) == BMP_FORMAT_TOP_DOWN )
461 		pTmpScan = rSrcBuffer.mpBits, nOffset = rSrcBuffer.mnScanlineSize;
462 	else
463 	{
464 		pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
465 		nOffset = -rSrcBuffer.mnScanlineSize;
466 	}
467 
468 	for( i = 0L; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset )
469 		pSrcScan[ i ] = pTmpScan;
470 
471 	// destination scanline buffer
472 	if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
473 		pTmpScan = pDstBuffer->mpBits, nOffset = pDstBuffer->mnScanlineSize;
474 	else
475 	{
476 		pTmpScan = pDstBuffer->mpBits + ( nDstDY - 1 ) * pDstBuffer->mnScanlineSize;
477 		nOffset = -pDstBuffer->mnScanlineSize;
478 	}
479 
480 	for( i = 0L; i < nDstDY; i++, pTmpScan += nOffset )
481 		pDstScan[ i ] = pTmpScan;
482 
483 	// do buffer scaling and conversion
484 	if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 )
485 	{
486 		ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
487 					  pSrcScan, pDstScan, pMapX, pMapY );
488 	}
489 	else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 )
490 	{
491 		ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
492 					 pSrcScan, pDstScan, pMapX, pMapY );
493 	}
494 	else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 )
495 	{
496 		ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
497 					pSrcScan, pDstScan, pMapX, pMapY );
498 	}
499 	else
500 	{
501 		ImplTCToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
502 					 pSrcScan, pDstScan, pMapX, pMapY );
503 	}
504 
505 	// cleanup
506 	delete[] pSrcScan;
507 	delete[] pDstScan;
508 	delete[] pMapX;
509 	delete[] pMapY;
510 
511 	return pDstBuffer;
512 }
513