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