xref: /AOO41X/main/vcl/source/gdi/salmisc.cxx (revision d3e0dd8eb215533c15e891ee35bd141abe9397ee)
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 
ImplIndexFromColor(const BitmapColor & rCol)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 
ImplPALToPAL(const BitmapBuffer & rSrcBuffer,BitmapBuffer & rDstBuffer,FncGetPixel pFncGetPixel,FncSetPixel pFncSetPixel,Scanline * pSrcScanMap,Scanline * pDstScanMap,long * pMapX,long * pMapY)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 
ImplPALToTC(const BitmapBuffer & rSrcBuffer,BitmapBuffer & rDstBuffer,FncGetPixel pFncGetPixel,FncSetPixel pFncSetPixel,Scanline * pSrcScanMap,Scanline * pDstScanMap,long * pMapX,long * pMapY)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 
ImplTCToTC(const BitmapBuffer & rSrcBuffer,BitmapBuffer & rDstBuffer,FncGetPixel pFncGetPixel,FncSetPixel pFncSetPixel,Scanline * pSrcScanMap,Scanline * pDstScanMap,long * pMapX,long * pMapY)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 
ImplTCToPAL(const BitmapBuffer & rSrcBuffer,BitmapBuffer & rDstBuffer,FncGetPixel pFncGetPixel,FncSetPixel pFncSetPixel,Scanline * pSrcScanMap,Scanline * pDstScanMap,long * pMapX,long * pMapY)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 
StretchAndConvert(const BitmapBuffer & rSrcBuffer,const SalTwoRect & rTwoRect,sal_uLong nDstBitmapFormat,const BitmapPalette * pDstPal,const ColorMask * pDstMask)291 BitmapBuffer* StretchAndConvert(
292     const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect,
293     sal_uLong nDstBitmapFormat, const BitmapPalette* pDstPal, const ColorMask* pDstMask )
294 {
295     FncGetPixel     pFncGetPixel;
296     FncSetPixel     pFncSetPixel;
297     BitmapBuffer*   pDstBuffer = new BitmapBuffer;
298     long            i;
299 
300     // set function for getting pixels
301     switch( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) )
302     {
303         IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL );
304         IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL );
305         IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL );
306         IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL );
307         IMPL_CASE_GET_FORMAT( _8BIT_PAL );
308         IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK );
309         IMPL_CASE_GET_FORMAT( _16BIT_TC_MSB_MASK );
310         IMPL_CASE_GET_FORMAT( _16BIT_TC_LSB_MASK );
311         IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR );
312         IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB );
313         IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK );
314         IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR );
315         IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB );
316         IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA );
317         IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA );
318         IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK );
319 
320         default:
321             // should never come here
322             // initialize pFncGetPixel to something valid that is
323             // least likely to crash
324             pFncGetPixel = BitmapReadAccess::GetPixelFor_1BIT_MSB_PAL;
325             DBG_ERROR( "unknown read format" );
326         break;
327     }
328 
329     // set function for setting pixels
330     const sal_uLong nDstScanlineFormat = BMP_SCANLINE_FORMAT( nDstBitmapFormat );
331     switch( nDstScanlineFormat )
332     {
333         IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL, 1 );
334         IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL, 1 );
335         IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL, 1 );
336         IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL, 4 );
337         IMPL_CASE_SET_FORMAT( _8BIT_PAL, 8 );
338         IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK, 8 );
339         IMPL_CASE_SET_FORMAT( _16BIT_TC_MSB_MASK, 16 );
340         IMPL_CASE_SET_FORMAT( _16BIT_TC_LSB_MASK, 16 );
341         IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR, 24 );
342         IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB, 24 );
343         IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK, 24 );
344         IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR, 32 );
345         IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB, 32 );
346         IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA, 32 );
347         IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA, 32 );
348         IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK, 32 );
349 
350         default:
351             // should never come here
352             // initialize pFncSetPixel to something valid that is
353             // least likely to crash
354             pFncSetPixel = BitmapReadAccess::SetPixelFor_1BIT_MSB_PAL;
355             pDstBuffer->mnBitCount = 1;
356             DBG_ERROR( "unknown write format" );
357         break;
358     }
359 
360     // fill destination buffer
361     pDstBuffer->mnFormat = nDstBitmapFormat;
362     pDstBuffer->mnWidth = rTwoRect.mnDestWidth;
363     pDstBuffer->mnHeight = rTwoRect.mnDestHeight;
364     pDstBuffer->mnScanlineSize = AlignedWidth4Bytes( pDstBuffer->mnBitCount * pDstBuffer->mnWidth );
365     try
366     {
367         pDstBuffer->mpBits = new sal_uInt8[ pDstBuffer->mnScanlineSize * pDstBuffer->mnHeight ];
368     }
369     catch( const std::bad_alloc& )
370     {
371         // memory exception, clean up
372         pDstBuffer->mpBits = NULL;
373         delete pDstBuffer;
374         return NULL;
375     }
376 
377     // do we need a destination palette or color mask?
378     if( ( nDstScanlineFormat == BMP_FORMAT_1BIT_MSB_PAL ) ||
379         ( nDstScanlineFormat == BMP_FORMAT_1BIT_LSB_PAL ) ||
380         ( nDstScanlineFormat == BMP_FORMAT_4BIT_MSN_PAL ) ||
381         ( nDstScanlineFormat == BMP_FORMAT_4BIT_LSN_PAL ) ||
382         ( nDstScanlineFormat == BMP_FORMAT_8BIT_PAL ) )
383     {
384         DBG_ASSERT( pDstPal, "destination buffer requires palette" );
385         pDstBuffer->maPalette = *pDstPal;
386     }
387     else if( ( nDstScanlineFormat == BMP_FORMAT_8BIT_TC_MASK ) ||
388              ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_MSB_MASK ) ||
389              ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_LSB_MASK ) ||
390              ( nDstScanlineFormat == BMP_FORMAT_24BIT_TC_MASK ) ||
391              ( nDstScanlineFormat == BMP_FORMAT_32BIT_TC_MASK ) )
392     {
393         DBG_ASSERT( pDstMask, "destination buffer requires color mask" );
394         pDstBuffer->maColorMask = *pDstMask;
395     }
396 
397     // short circuit the most important conversions
398     bool bFastConvert = ImplFastBitmapConversion( *pDstBuffer, rSrcBuffer, rTwoRect );
399     if( bFastConvert )
400         return pDstBuffer;
401 
402     const long      nSrcX = rTwoRect.mnSrcX, nSrcY = rTwoRect.mnSrcY;
403     const long      nSrcDX = rTwoRect.mnSrcWidth, nSrcDY = rTwoRect.mnSrcHeight;
404     const long      nDstDX = rTwoRect.mnDestWidth, nDstDY = rTwoRect.mnDestHeight;
405     Scanline*       pSrcScan = NULL;
406     Scanline*       pDstScan = NULL;
407     long*           pMapX = NULL;
408     long*           pMapY = NULL;
409     long            nTmp, nOffset;
410 
411     try
412     {
413         pSrcScan = new Scanline[ rSrcBuffer.mnHeight ];
414         pDstScan = new Scanline[ nDstDY ];
415         pMapX = new long[ nDstDX ];
416         pMapY = new long[ nDstDY ];
417     }
418     catch( const std::bad_alloc& )
419     {
420         // memory exception, clean up
421         // remark: the buffer ptr causing the exception
422         // is still NULL here
423         delete[] pSrcScan;
424         delete[] pDstScan;
425         delete[] pMapX;
426         delete[] pMapY;
427         delete pDstBuffer;
428         return NULL;
429     }
430 
431     // horizontal mapping table
432     if( (nDstDX != nSrcDX) && (nDstDX != 0) )
433     {
434         const double fFactorX = (double)nSrcDX / nDstDX;
435 
436         for( i = 0L; i < nDstDX; i++ )
437             pMapX[ i ] = nSrcX + static_cast<int>( i * fFactorX );
438     }
439     else
440     {
441         for( i = 0L, nTmp = nSrcX; i < nDstDX; i++ )
442             pMapX[ i ] = nTmp++;
443     }
444 
445     // vertical mapping table
446     if( (nDstDY != nSrcDY) && (nDstDY != 0) )
447     {
448         const double fFactorY = (double)nSrcDY / nDstDY;
449 
450         for( i = 0L; i < nDstDY; i++ )
451             pMapY[ i ] = nSrcY + static_cast<int>( i * fFactorY );
452     }
453     else
454     {
455         for( i = 0L, nTmp = nSrcY; i < nDstDY; i++ )
456             pMapY[ i ] = nTmp++;
457     }
458 
459     // source scanline buffer
460     Scanline pTmpScan;
461     if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer.mnFormat ) == BMP_FORMAT_TOP_DOWN )
462         pTmpScan = rSrcBuffer.mpBits, nOffset = rSrcBuffer.mnScanlineSize;
463     else
464     {
465         pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
466         nOffset = -rSrcBuffer.mnScanlineSize;
467     }
468 
469     for( i = 0L; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset )
470         pSrcScan[ i ] = pTmpScan;
471 
472     // destination scanline buffer
473     if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
474         pTmpScan = pDstBuffer->mpBits, nOffset = pDstBuffer->mnScanlineSize;
475     else
476     {
477         pTmpScan = pDstBuffer->mpBits + ( nDstDY - 1 ) * pDstBuffer->mnScanlineSize;
478         nOffset = -pDstBuffer->mnScanlineSize;
479     }
480 
481     for( i = 0L; i < nDstDY; i++, pTmpScan += nOffset )
482         pDstScan[ i ] = pTmpScan;
483 
484     // do buffer scaling and conversion
485     if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 )
486     {
487         ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
488                       pSrcScan, pDstScan, pMapX, pMapY );
489     }
490     else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 )
491     {
492         ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
493                      pSrcScan, pDstScan, pMapX, pMapY );
494     }
495     else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 )
496     {
497         ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
498                     pSrcScan, pDstScan, pMapX, pMapY );
499     }
500     else
501     {
502         ImplTCToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
503                      pSrcScan, pDstScan, pMapX, pMapY );
504     }
505 
506     // cleanup
507     delete[] pSrcScan;
508     delete[] pDstScan;
509     delete[] pMapX;
510     delete[] pMapY;
511 
512     return pDstBuffer;
513 }
514