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