xref: /trunk/main/vcl/source/gdi/bitmap3.cxx (revision 37ab0f2ded8d56c462c711095097172f45805977)
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 
27 #include <stdlib.h>
28 
29 #include <vcl/bmpacc.hxx>
30 #include <vcl/octree.hxx>
31 #include <vcl/bitmapex.hxx>
32 #include <vcl/bitmap.hxx>
33 
34 #include <impoct.hxx>
35 #include <impvect.hxx>
36 
37 // -----------
38 // - Defines -
39 // -----------
40 
41 #define RGB15( _def_cR, _def_cG, _def_cB )  (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
42 #define GAMMA( _def_cVal, _def_InvGamma )   ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
43 #define MAP( cVal0, cVal1, nFrac )  ((sal_uInt8)((((long)(cVal0)<<7L)+nFrac*((long)(cVal1)-(cVal0)))>>7L))
44 
45 #define CALC_ERRORS                                                             \
46                         nTemp   = p1T[nX++] >> 12;                              \
47                         nBErr = MinMax( nTemp, 0, 255 );                        \
48                         nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
49                         nTemp   = p1T[nX++] >> 12;                              \
50                         nGErr = MinMax( nTemp, 0, 255 );                        \
51                         nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
52                         nTemp   = p1T[nX] >> 12;                                \
53                         nRErr = MinMax( nTemp, 0, 255 );                        \
54                         nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
55 
56 #define CALC_TABLES3                                        \
57                         p2T[nX++] += FloydError3[nBErr];    \
58                         p2T[nX++] += FloydError3[nGErr];    \
59                         p2T[nX++] += FloydError3[nRErr];
60 
61 #define CALC_TABLES5                                        \
62                         p2T[nX++] += FloydError5[nBErr];    \
63                         p2T[nX++] += FloydError5[nGErr];    \
64                         p2T[nX++] += FloydError5[nRErr];
65 
66 #define CALC_TABLES7                                        \
67                         p1T[++nX] += FloydError7[nBErr];    \
68                         p2T[nX++] += FloydError1[nBErr];    \
69                         p1T[nX] += FloydError7[nGErr];      \
70                         p2T[nX++] += FloydError1[nGErr];    \
71                         p1T[nX] += FloydError7[nRErr];      \
72                         p2T[nX] += FloydError1[nRErr];
73 
74 // -----------
75 // - Statics -
76 // -----------
77 
78 sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
79 sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
80 sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
81 
82 // ------------------------------------------------------------------------
83 
84 sal_uLong nVCLDitherLut[ 256 ] =
85 {
86        0, 49152, 12288, 61440,  3072, 52224, 15360, 64512,   768, 49920, 13056,
87    62208,  3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
88    48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
89    57344,  4096, 53248, 11264, 60416,  7168, 56320,  8960, 58112,  4864, 54016,
90    12032, 61184,  7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
91    23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
92    14336, 63488,  1024, 50176, 13312, 62464,  2816, 51968, 15104, 64256,  1792,
93    50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
94    35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392,  6144,
95    55296,  9216, 58368,  5120, 54272, 11008, 60160,  6912, 56064,  9984, 59136,
96     5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
97    27392, 39680, 23296, 42752, 26368, 38656, 22272,   512, 49664, 12800, 61952,
98     3584, 52736, 15872, 65024,   256, 49408, 12544, 61696,  3328, 52480, 15616,
99    64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
100    45312, 28928, 36096, 19712, 48384, 32000,  8704, 57856,  4608, 53760, 11776,
101    60928,  7680, 56832,  8448, 57600,  4352, 53504, 11520, 60672,  7424, 56576,
102    41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
103    20736, 44288, 27904, 40192, 23808,  2560, 51712, 14848, 64000,  1536, 50688,
104    13824, 62976,  2304, 51456, 14592, 63744,  1280, 50432, 13568, 62720, 35328,
105    18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
106    34048, 17664, 46336, 29952, 10752, 59904,  6656, 55808,  9728, 58880,  5632,
107    54784, 10496, 59648,  6400, 55552,  9472, 58624,  5376, 54528, 43520, 27136,
108    39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
109    25856, 38144, 21760
110 };
111 
112 // ------------------------------------------------------------------------
113 
114 sal_uLong nVCLLut[ 256 ] =
115 {
116          0,  1286,  2572,  3858,  5144,  6430,  7716,  9002,
117      10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
118      20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
119      30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
120      41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
121      51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
122      61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
123      72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
124      82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
125      92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
126     102880,104166,105452,106738,108024,109310,110596,111882,
127     113168,114454,115740,117026,118312,119598,120884,122170,
128     123456,124742,126028,127314,128600,129886,131172,132458,
129     133744,135030,136316,137602,138888,140174,141460,142746,
130     144032,145318,146604,147890,149176,150462,151748,153034,
131     154320,155606,156892,158178,159464,160750,162036,163322,
132     164608,165894,167180,168466,169752,171038,172324,173610,
133     174896,176182,177468,178754,180040,181326,182612,183898,
134     185184,186470,187756,189042,190328,191614,192900,194186,
135     195472,196758,198044,199330,200616,201902,203188,204474,
136     205760,207046,208332,209618,210904,212190,213476,214762,
137     216048,217334,218620,219906,221192,222478,223764,225050,
138     226336,227622,228908,230194,231480,232766,234052,235338,
139     236624,237910,239196,240482,241768,243054,244340,245626,
140     246912,248198,249484,250770,252056,253342,254628,255914,
141     257200,258486,259772,261058,262344,263630,264916,266202,
142     267488,268774,270060,271346,272632,273918,275204,276490,
143     277776,279062,280348,281634,282920,284206,285492,286778,
144     288064,289350,290636,291922,293208,294494,295780,297066,
145     298352,299638,300924,302210,303496,304782,306068,307354,
146     308640,309926,311212,312498,313784,315070,316356,317642,
147     318928,320214,321500,322786,324072,325358,326644,327930
148 };
149 
150 // ------------------------------------------------------------------------
151 
152 long FloydMap[256] =
153 {
154     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
156     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
157     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
158     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
159     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
160     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
161     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
163     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
164     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
165     3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
166     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
167     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
168     4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
169     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
170 };
171 
172 // ------------------------------------------------------------------------
173 
174 long FloydError1[61] =
175 {
176     -7680, -7424, -7168, -6912, -6656, -6400, -6144,
177     -5888, -5632, -5376, -5120, -4864, -4608, -4352,
178     -4096, -3840, -3584, -3328, -3072, -2816, -2560,
179     -2304, -2048, -1792, -1536, -1280, -1024, -768,
180     -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
181     1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
182     3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
183     5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
184 };
185 
186 // ------------------------------------------------------------------------
187 
188 long FloydError3[61] =
189 {
190     -23040, -22272, -21504, -20736, -19968, -19200,
191     -18432, -17664, -16896, -16128, -15360, -14592,
192     -13824, -13056, -12288, -11520, -10752, -9984,
193     -9216, -8448, -7680, -6912, -6144, -5376, -4608,
194     -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
195     2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
196     8448, 9216, 9984, 10752, 11520, 12288, 13056,
197     13824, 14592, 15360, 16128, 16896, 17664, 18432,
198     19200, 19968, 20736, 21504, 22272, 23040
199 };
200 
201 // ------------------------------------------------------------------------
202 
203 long FloydError5[61] =
204 {
205     -38400, -37120, -35840, -34560, -33280, -32000,
206     -30720, -29440, -28160, -26880, -25600, -24320,
207     -23040, -21760, -20480, -19200, -17920, -16640,
208     -15360, -14080, -12800, -11520, -10240, -8960,
209     -7680, -6400, -5120, -3840, -2560, -1280,   0,
210     1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
211     11520, 12800, 14080, 15360, 16640, 17920, 19200,
212     20480, 21760, 23040, 24320, 25600, 26880, 28160,
213     29440, 30720, 32000, 33280, 34560, 35840, 37120,
214     38400
215 };
216 
217 // ------------------------------------------------------------------------
218 
219 long FloydError7[61] =
220 {
221     -53760, -51968, -50176, -48384, -46592, -44800,
222     -43008, -41216, -39424, -37632, -35840, -34048,
223     -32256, -30464, -28672, -26880, -25088, -23296,
224     -21504, -19712, -17920, -16128, -14336, -12544,
225     -10752, -8960, -7168, -5376, -3584, -1792,  0,
226     1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
227     16128, 17920, 19712, 21504, 23296, 25088, 26880,
228     28672, 30464, 32256, 34048, 35840, 37632, 39424,
229     41216, 43008, 44800, 46592, 48384, 50176, 51968,
230     53760
231 };
232 
233 // ------------------------------------------------------------------------
234 
235 long FloydIndexMap[6] =
236 {
237     -30,  21, 72, 123, 174, 225
238 };
239 
240 // --------------------------
241 // - ImplCreateDitherMatrix -
242 // --------------------------
243 
244 void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] )
245 {
246     double          fVal = 3.125;
247     const double    fVal16 = fVal / 16.;
248     long            i, j, k, l;
249     sal_uInt16          pMtx[ 16 ][ 16 ];
250     sal_uInt16          nMax = 0;
251     static sal_uInt8    pMagic[4][4] = { { 0, 14,  3, 13, },
252                                      {11,  5,  8,  6, },
253                                      {12,  2, 15,  1, },
254                                      {7,   9,  4, 10 } };
255 
256     // MagicSquare aufbauen
257     for ( i = 0; i < 4; i++ )
258        for ( j = 0; j < 4; j++ )
259            for ( k = 0; k < 4; k++ )
260                 for ( l = 0; l < 4; l++ )
261                     nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
262                     (sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
263 
264     // auf Intervall [0;254] skalieren
265     for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
266         for( j = 0; j < 16; j++ )
267             (*pDitherMatrix)[i][j] = (sal_uInt8) ( fVal * pMtx[i][j] );
268 }
269 
270 // ----------
271 // - Bitmap -
272 // ----------
273 
274 sal_Bool Bitmap::Convert( BmpConversion eConversion )
275 {
276     const sal_uInt16    nBitCount = GetBitCount();
277     sal_Bool            bRet = sal_False;
278 
279     switch( eConversion )
280     {
281         case( BMP_CONVERSION_1BIT_THRESHOLD ):
282             bRet = ImplMakeMono( 128 );
283         break;
284 
285         case( BMP_CONVERSION_1BIT_MATRIX ):
286             bRet = ImplMakeMonoDither();
287         break;
288 
289         case( BMP_CONVERSION_4BIT_GREYS ):
290             bRet = ImplMakeGreyscales( 16 );
291         break;
292 
293         case( BMP_CONVERSION_4BIT_COLORS ):
294         {
295             if( nBitCount < 4 )
296                 bRet = ImplConvertUp( 4, NULL );
297             else if( nBitCount > 4 )
298                 bRet = ImplConvertDown( 4, NULL );
299             else
300                 bRet = sal_True;
301         }
302         break;
303 
304         case( BMP_CONVERSION_4BIT_TRANS ):
305         {
306             Color aTrans( BMP_COL_TRANS );
307 
308             if( nBitCount < 4 )
309                 bRet = ImplConvertUp( 4, &aTrans );
310             else
311                 bRet = ImplConvertDown( 4, &aTrans );
312         }
313         break;
314 
315         case( BMP_CONVERSION_8BIT_GREYS ):
316             bRet = ImplMakeGreyscales( 256 );
317         break;
318 
319         case( BMP_CONVERSION_8BIT_COLORS ):
320         {
321             if( nBitCount < 8 )
322                 bRet = ImplConvertUp( 8 );
323             else if( nBitCount > 8 )
324                 bRet = ImplConvertDown( 8 );
325             else
326                 bRet = sal_True;
327         }
328         break;
329 
330         case( BMP_CONVERSION_8BIT_TRANS ):
331         {
332             Color aTrans( BMP_COL_TRANS );
333 
334             if( nBitCount < 8 )
335                 bRet = ImplConvertUp( 8, &aTrans );
336             else
337                 bRet = ImplConvertDown( 8, &aTrans );
338         }
339         break;
340 
341         case( BMP_CONVERSION_24BIT ):
342         {
343             if( nBitCount < 24 )
344                 bRet = ImplConvertUp( 24, sal_False );
345             else
346                 bRet = sal_True;
347         }
348         break;
349 
350         case( BMP_CONVERSION_GHOSTED ):
351             bRet = ImplConvertGhosted();
352         break;
353 
354         default:
355             DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
356         break;
357     }
358 
359     return bRet;
360 }
361 
362 // ------------------------------------------------------------------------
363 
364 sal_Bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold )
365 {
366     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
367     sal_Bool                bRet = sal_False;
368 
369     if( pReadAcc )
370     {
371         Bitmap              aNewBmp( GetSizePixel(), 1 );
372         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
373 
374         if( pWriteAcc )
375         {
376             const BitmapColor   aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
377             const BitmapColor   aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
378             const long          nWidth = pWriteAcc->Width();
379             const long          nHeight = pWriteAcc->Height();
380 
381             if( pReadAcc->HasPalette() )
382             {
383                 for( long nY = 0L; nY < nHeight; nY++ )
384                 {
385                     for( long nX = 0L; nX < nWidth; nX++ )
386                     {
387                         const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
388                         if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >=
389                             cThreshold )
390                         {
391                             pWriteAcc->SetPixel( nY, nX, aWhite );
392                         }
393                         else
394                             pWriteAcc->SetPixel( nY, nX, aBlack );
395                     }
396                 }
397             }
398             else
399             {
400                 for( long nY = 0L; nY < nHeight; nY++ )
401                 {
402                     for( long nX = 0L; nX < nWidth; nX++ )
403                     {
404                         if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
405                             cThreshold )
406                         {
407                             pWriteAcc->SetPixel( nY, nX, aWhite );
408                         }
409                         else
410                             pWriteAcc->SetPixel( nY, nX, aBlack );
411                     }
412                 }
413             }
414 
415             aNewBmp.ReleaseAccess( pWriteAcc );
416             bRet = sal_True;
417         }
418 
419         ReleaseAccess( pReadAcc );
420 
421         if( bRet )
422         {
423             const MapMode   aMap( maPrefMapMode );
424             const Size      aSize( maPrefSize );
425 
426             *this = aNewBmp;
427 
428             maPrefMapMode = aMap;
429             maPrefSize = aSize;
430         }
431     }
432 
433     return bRet;
434 }
435 
436 // ------------------------------------------------------------------------
437 
438 sal_Bool Bitmap::ImplMakeMonoDither()
439 {
440     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
441     sal_Bool                bRet = sal_False;
442 
443     if( pReadAcc )
444     {
445         Bitmap              aNewBmp( GetSizePixel(), 1 );
446         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
447 
448         if( pWriteAcc )
449         {
450             const BitmapColor   aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
451             const BitmapColor   aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
452             const long          nWidth = pWriteAcc->Width();
453             const long          nHeight = pWriteAcc->Height();
454             sal_uInt8               pDitherMatrix[ 16 ][ 16 ];
455 
456             ImplCreateDitherMatrix( &pDitherMatrix );
457 
458             if( pReadAcc->HasPalette() )
459             {
460                 for( long nY = 0L; nY < nHeight; nY++ )
461                 {
462                     for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
463                     {
464                         const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
465                         if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >
466                             pDitherMatrix[ nModY ][ nX % 16 ] )
467                         {
468                             pWriteAcc->SetPixel( nY, nX, aWhite );
469                         }
470                         else
471                             pWriteAcc->SetPixel( nY, nX, aBlack );
472                     }
473                 }
474             }
475             else
476             {
477                 for( long nY = 0L; nY < nHeight; nY++ )
478                 {
479                     for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
480                     {
481                         if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
482                             pDitherMatrix[ nModY ][ nX % 16 ]  )
483                         {
484                             pWriteAcc->SetPixel( nY, nX, aWhite );
485                         }
486                         else
487                             pWriteAcc->SetPixel( nY, nX, aBlack );
488                     }
489                 }
490             }
491 
492             aNewBmp.ReleaseAccess( pWriteAcc );
493             bRet = sal_True;
494         }
495 
496         ReleaseAccess( pReadAcc );
497 
498         if( bRet )
499         {
500             const MapMode   aMap( maPrefMapMode );
501             const Size      aSize( maPrefSize );
502 
503             *this = aNewBmp;
504 
505             maPrefMapMode = aMap;
506             maPrefSize = aSize;
507         }
508     }
509 
510     return bRet;
511 }
512 
513 // ------------------------------------------------------------------------
514 
515 sal_Bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
516 {
517     DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" );
518 
519     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
520     sal_Bool                bRet = sal_False;
521 
522     if( pReadAcc )
523     {
524         const BitmapPalette&    rPal = GetGreyPalette( nGreys );
525         sal_uLong                   nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
526         sal_Bool                    bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
527 
528         if( !bPalDiffers )
529             bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
530 
531         if( bPalDiffers )
532         {
533             Bitmap              aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
534             BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
535 
536             if( pWriteAcc )
537             {
538                 const long  nWidth = pWriteAcc->Width();
539                 const long  nHeight = pWriteAcc->Height();
540 
541                 if( pReadAcc->HasPalette() )
542                 {
543                     for( long nY = 0L; nY < nHeight; nY++ )
544                     {
545                         for( long nX = 0L; nX < nWidth; nX++ )
546                         {
547                             const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
548                             pWriteAcc->SetPixelIndex( nY, nX,
549                                 (pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
550                         }
551                     }
552                 }
553                 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
554                          pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
555                 {
556                     nShift += 8;
557 
558                     for( long nY = 0L; nY < nHeight; nY++ )
559                     {
560                         Scanline pReadScan = pReadAcc->GetScanline( nY );
561                         Scanline pWriteScan = pWriteAcc->GetScanline( nY );
562 
563                         for( long nX = 0L; nX < nWidth; nX++ )
564                         {
565                             const sal_uLong nB = *pReadScan++;
566                             const sal_uLong nG = *pReadScan++;
567                             const sal_uLong nR = *pReadScan++;
568 
569                             *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
570                         }
571                     }
572                 }
573                 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
574                          pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
575                 {
576                     nShift += 8;
577 
578                     for( long nY = 0L; nY < nHeight; nY++ )
579                     {
580                         Scanline pReadScan = pReadAcc->GetScanline( nY );
581                         Scanline pWriteScan = pWriteAcc->GetScanline( nY );
582 
583                         for( long nX = 0L; nX < nWidth; nX++ )
584                         {
585                             const sal_uLong nR = *pReadScan++;
586                             const sal_uLong nG = *pReadScan++;
587                             const sal_uLong nB = *pReadScan++;
588 
589                             *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
590                         }
591                     }
592                 }
593                 else
594                 {
595                     for( long nY = 0L; nY < nHeight; nY++ )
596                         for( long nX = 0L; nX < nWidth; nX++ )
597                             pWriteAcc->SetPixelIndex( nY, nX, (pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift );
598                 }
599 
600                 aNewBmp.ReleaseAccess( pWriteAcc );
601                 bRet = sal_True;
602             }
603 
604             ReleaseAccess( pReadAcc );
605 
606             if( bRet )
607             {
608                 const MapMode   aMap( maPrefMapMode );
609                 const Size      aSize( maPrefSize );
610 
611                 *this = aNewBmp;
612 
613                 maPrefMapMode = aMap;
614                 maPrefSize = aSize;
615             }
616         }
617         else
618         {
619             ReleaseAccess( pReadAcc );
620             bRet = sal_True;
621         }
622     }
623 
624     return bRet;
625 }
626 
627 // ------------------------------------------------------------------------
628 
629 sal_Bool Bitmap::ImplConvertUp( sal_uInt16 nBitCount, Color* pExtColor )
630 {
631     DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
632 
633     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
634     sal_Bool                bRet = sal_False;
635 
636     if( pReadAcc )
637     {
638         BitmapPalette       aPal;
639         Bitmap              aNewBmp( GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPal );
640         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
641 
642         if( pWriteAcc )
643         {
644             const long  nWidth = pWriteAcc->Width();
645             const long  nHeight = pWriteAcc->Height();
646 
647             if( pWriteAcc->HasPalette() )
648             {
649                 const sal_uInt16            nOldCount = 1 << GetBitCount();
650                 const BitmapPalette&    rOldPal = pReadAcc->GetPalette();
651 
652                 aPal.SetEntryCount( 1 << nBitCount );
653 
654                 for( sal_uInt16 i = 0; i < nOldCount; i++ )
655                     aPal[ i ] = rOldPal[ i ];
656 
657                 if( pExtColor )
658                     aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
659 
660                 pWriteAcc->SetPalette( aPal );
661 
662                 for( long nY = 0L; nY < nHeight; nY++ )
663                     for( long nX = 0L; nX < nWidth; nX++ )
664                         pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
665             }
666             else
667             {
668                 if( pReadAcc->HasPalette() )
669                 {
670                     for( long nY = 0L; nY < nHeight; nY++ )
671                         for( long nX = 0L; nX < nWidth; nX++ )
672                             pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
673                 }
674                 else
675                 {
676                     for( long nY = 0L; nY < nHeight; nY++ )
677                         for( long nX = 0L; nX < nWidth; nX++ )
678                             pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
679                 }
680             }
681 
682             aNewBmp.ReleaseAccess( pWriteAcc );
683             bRet = sal_True;
684         }
685 
686         ReleaseAccess( pReadAcc );
687 
688         if( bRet )
689         {
690             const MapMode   aMap( maPrefMapMode );
691             const Size      aSize( maPrefSize );
692 
693             *this = aNewBmp;
694 
695             maPrefMapMode = aMap;
696             maPrefSize = aSize;
697         }
698     }
699 
700     return bRet;
701 }
702 
703 // ------------------------------------------------------------------------
704 
705 sal_Bool Bitmap::ImplConvertDown( sal_uInt16 nBitCount, Color* pExtColor )
706 {
707     DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
708 
709     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
710     sal_Bool                bRet = sal_False;
711 
712     if( pReadAcc )
713     {
714         BitmapPalette       aPal;
715         Bitmap              aNewBmp( GetSizePixel(), nBitCount, &aPal );
716         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
717 
718         if( pWriteAcc )
719         {
720             const sal_uInt16    nCount = 1 << nBitCount;
721             const long      nWidth = pWriteAcc->Width();
722             const long      nWidth1 = nWidth - 1L;
723             const long      nHeight = pWriteAcc->Height();
724             Octree          aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
725             InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
726             BitmapColor     aColor;
727             ImpErrorQuad    aErrQuad;
728             ImpErrorQuad*   pErrQuad1 = new ImpErrorQuad[ nWidth ];
729             ImpErrorQuad*   pErrQuad2 = new ImpErrorQuad[ nWidth ];
730             ImpErrorQuad*   pQLine1 = pErrQuad1;
731             ImpErrorQuad*   pQLine2 = 0;
732             long            nX, nY;
733             long            nYTmp = 0L;
734             sal_uInt8           cIndex;
735             sal_Bool            bQ1 = sal_True;
736 
737             if( pExtColor )
738             {
739                 aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
740                 aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
741             }
742 
743             // set Black/White always, if we have enough space
744             if( aPal.GetEntryCount() < ( nCount - 1 ) )
745             {
746                 aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
747                 aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
748                 aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
749             }
750 
751             pWriteAcc->SetPalette( aPal );
752 
753             for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
754             {
755                 for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
756                 {
757                     if( pReadAcc->HasPalette() )
758                         pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) );
759                     else
760                         pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
761                 }
762             }
763 
764             for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
765             {
766                 // first pixel in the line
767                 cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
768                 pWriteAcc->SetPixelIndex( nY, 0, cIndex );
769 
770                 for( nX = 1L; nX < nWidth1; nX++ )
771                 {
772                     cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
773                     aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
774                     pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
775                     pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
776                     pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
777                     pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
778                     pWriteAcc->SetPixelIndex( nY, nX, cIndex );
779                 }
780 
781                 // letztes ZeilenPixel
782                 if( nX < nWidth )
783                 {
784                     cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
785                     pWriteAcc->SetPixelIndex( nY, nX, cIndex );
786                 }
787 
788                 // Zeilenpuffer neu fuellen/kopieren
789                 pQLine1 = pQLine2;
790                 pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
791 
792                 if( nYTmp < nHeight )
793                 {
794                     for( nX = 0L; nX < nWidth; nX++ )
795                     {
796                         if( pReadAcc->HasPalette() )
797                             pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) );
798                         else
799                             pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
800                     }
801                 }
802             }
803 
804             // Zeilenpuffer zerstoeren
805             delete[] pErrQuad1;
806             delete[] pErrQuad2;
807 
808             aNewBmp.ReleaseAccess( pWriteAcc );
809             bRet = sal_True;
810         }
811 
812         ReleaseAccess( pReadAcc );
813 
814         if( bRet )
815         {
816             const MapMode   aMap( maPrefMapMode );
817             const Size      aSize( maPrefSize );
818 
819             *this = aNewBmp;
820 
821             maPrefMapMode = aMap;
822             maPrefSize = aSize;
823         }
824     }
825 
826     return bRet;
827 }
828 
829 // ------------------------------------------------------------------------
830 
831 sal_Bool Bitmap::ImplConvertGhosted()
832 {
833     Bitmap              aNewBmp;
834     BitmapReadAccess*   pR = AcquireReadAccess();
835     sal_Bool                bRet = sal_False;
836 
837     if( pR )
838     {
839         if( pR->HasPalette() )
840         {
841             BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
842 
843             for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
844             {
845                 const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i );
846                 aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
847                                                      ( rOld.GetGreen() >> 1 ) | 0x80,
848                                                      ( rOld.GetBlue() >> 1 ) | 0x80 );
849             }
850 
851             aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
852             BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
853 
854             if( pW )
855             {
856                 pW->CopyBuffer( *pR );
857                 aNewBmp.ReleaseAccess( pW );
858                 bRet = sal_True;
859             }
860         }
861         else
862         {
863             aNewBmp = Bitmap( GetSizePixel(), 24 );
864 
865             BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
866 
867             if( pW )
868             {
869                 const long nWidth = pR->Width(), nHeight = pR->Height();
870 
871                 for( long nY = 0; nY < nHeight; nY++ )
872                 {
873                     for( long nX = 0; nX < nWidth; nX++ )
874                     {
875                         const BitmapColor aOld( pR->GetPixel( nY, nX ) );
876                         pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
877                                                            ( aOld.GetGreen() >> 1 ) | 0x80,
878                                                            ( aOld.GetBlue() >> 1 ) | 0x80 ) );
879 
880                     }
881                 }
882 
883                 aNewBmp.ReleaseAccess( pW );
884                 bRet = sal_True;
885             }
886         }
887 
888         ReleaseAccess( pR );
889     }
890 
891     if( bRet )
892     {
893         const MapMode   aMap( maPrefMapMode );
894         const Size      aSize( maPrefSize );
895 
896         *this = aNewBmp;
897 
898         maPrefMapMode = aMap;
899         maPrefSize = aSize;
900     }
901 
902     return bRet;
903 }
904 
905 // ------------------------------------------------------------------------
906 
907 sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
908 {
909 #ifdef DBG_UTIL
910     // #121233# allow to test the different scalers in debug build with source
911     // level debugger (change nNumber to desired action)
912     static sal_uInt16 nNumber(0);
913 
914     switch(nNumber)
915     {
916         case 0 : break;
917         case 1: nScaleFlag = BMP_SCALE_FAST; break;
918         case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break;
919         case 3: nScaleFlag = BMP_SCALE_SUPER; break;
920         case 4: nScaleFlag = BMP_SCALE_LANCZOS; break;
921         case 5: nScaleFlag = BMP_SCALE_BICUBIC; break;
922         case 6: nScaleFlag = BMP_SCALE_BILINEAR; break;
923         case 7: nScaleFlag = BMP_SCALE_BOX; break;
924         case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break;
925         case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break;
926     }
927 #endif // DBG_UTIL
928 
929     if(basegfx::fTools::equalZero(rScaleX) && basegfx::fTools::equalZero(rScaleY))
930     {
931         // no scale
932         return true;
933     }
934     else
935     {
936         if(BMP_SCALE_BESTQUALITY == nScaleFlag)
937         {
938             // Use LANCZOS when best quality is requested
939             nScaleFlag = BMP_SCALE_LANCZOS;
940         }
941         else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag)
942         {
943             // Use BMP_SCALE_SUPER when speed is requested, but not worst quality
944             nScaleFlag = BMP_SCALE_SUPER;
945         }
946 
947         switch(nScaleFlag)
948         {
949             default:
950             case BMP_SCALE_NONE :
951             {
952                 return false;
953                 break;
954             }
955             case BMP_SCALE_FAST :
956             {
957                 return ImplScaleFast( rScaleX, rScaleY );
958                 break;
959             }
960             case BMP_SCALE_INTERPOLATE :
961             {
962                 return ImplScaleInterpolate( rScaleX, rScaleY );
963                 break;
964             }
965             case BMP_SCALE_SUPER :
966             {
967                 if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
968                 {
969                     // fallback to ImplScaleFast
970                     return ImplScaleFast( rScaleX, rScaleY );
971                 }
972                 else
973                 {
974                     // #121233# use method from symphony
975                     return ImplScaleSuper( rScaleX, rScaleY );
976                 }
977                 break;
978             }
979             case BMP_SCALE_LANCZOS :
980             {
981                 const Lanczos3Kernel kernel;
982 
983                 return ImplScaleConvolution( rScaleX, rScaleY, kernel);
984                 break;
985             }
986             case BMP_SCALE_BICUBIC :
987             {
988                 const BicubicKernel kernel;
989 
990                 return ImplScaleConvolution( rScaleX, rScaleY, kernel );
991                 break;
992             }
993             case BMP_SCALE_BILINEAR :
994             {
995                 const BilinearKernel kernel;
996 
997                 return ImplScaleConvolution( rScaleX, rScaleY, kernel );
998                 break;
999             }
1000             case BMP_SCALE_BOX :
1001             {
1002                 const BoxKernel kernel;
1003 
1004                 return ImplScaleConvolution( rScaleX, rScaleY, kernel );
1005                 break;
1006             }
1007         }
1008     }
1009 
1010     // should not happen
1011     return false;
1012 }
1013 
1014 // ------------------------------------------------------------------------
1015 
1016 sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
1017 {
1018     const Size  aSize( GetSizePixel() );
1019     sal_Bool        bRet;
1020 
1021     if( aSize.Width() && aSize.Height() )
1022     {
1023         bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
1024                       (double) rNewSize.Height() / aSize.Height(),
1025                       nScaleFlag );
1026     }
1027     else
1028         bRet = sal_True;
1029 
1030     return bRet;
1031 }
1032 
1033 // ------------------------------------------------------------------------
1034 
1035 void Bitmap::ImplAdaptBitCount(Bitmap& rNew)
1036 {
1037     // aNew is the result of some operation; adapt it's BitCount to the original (this)
1038     if(GetBitCount() != rNew.GetBitCount())
1039     {
1040         switch(GetBitCount())
1041         {
1042             case 1:
1043             {
1044                 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
1045                 break;
1046             }
1047             case 4:
1048             {
1049                 if(HasGreyPalette())
1050                 {
1051                     rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
1052                 }
1053                 else
1054                 {
1055                     rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
1056                 }
1057                 break;
1058             }
1059             case 8:
1060             {
1061                 if(HasGreyPalette())
1062                 {
1063                     rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
1064                 }
1065                 else
1066                 {
1067                     rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
1068                 }
1069                 break;
1070             }
1071             case 24:
1072             {
1073                 rNew.Convert(BMP_CONVERSION_24BIT);
1074                 break;
1075             }
1076             default:
1077             {
1078                 OSL_ENSURE(false, "BitDepth adaption failed (!)");
1079                 break;
1080             }
1081         }
1082     }
1083 }
1084 
1085 // ------------------------------------------------------------------------
1086 
1087 sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
1088 {
1089     const Size  aSizePix( GetSizePixel() );
1090     const long  nNewWidth = FRound( aSizePix.Width() * rScaleX );
1091     const long  nNewHeight = FRound( aSizePix.Height() * rScaleY );
1092     sal_Bool        bRet = sal_False;
1093 
1094     if( nNewWidth && nNewHeight )
1095     {
1096         BitmapReadAccess*   pReadAcc = AcquireReadAccess();
1097         if ( !pReadAcc )
1098             return sal_False;
1099 
1100         Bitmap              aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
1101         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
1102 
1103         if( pWriteAcc )
1104         {
1105             const long  nScanlineSize = pWriteAcc->GetScanlineSize();
1106             const long  nNewWidth1 = nNewWidth - 1L;
1107             const long  nNewHeight1 = nNewHeight - 1L;
1108             const long  nWidth = pReadAcc->Width();
1109             const long  nHeight = pReadAcc->Height();
1110             long*       pLutX = new long[ nNewWidth ];
1111             long*       pLutY = new long[ nNewHeight ];
1112             long        nX, nY, nMapY, nActY = 0L;
1113 
1114             if( nNewWidth1 && nNewHeight1 )
1115             {
1116                 for( nX = 0L; nX < nNewWidth; nX++ )
1117                     pLutX[ nX ] = nX * nWidth / nNewWidth;
1118 
1119                 for( nY = 0L; nY < nNewHeight; nY++ )
1120                     pLutY[ nY ] = nY * nHeight / nNewHeight;
1121 
1122                 while( nActY < nNewHeight )
1123                 {
1124                     nMapY = pLutY[ nActY ];
1125 
1126                     for( nX = 0L; nX < nNewWidth; nX++ )
1127                         pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
1128 
1129                     while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
1130                     {
1131                         memcpy( pWriteAcc->GetScanline( nActY + 1L ),
1132                                  pWriteAcc->GetScanline( nActY ), nScanlineSize );
1133                         nActY++;
1134                     }
1135 
1136                     nActY++;
1137                 }
1138 
1139                 bRet = sal_True;
1140             }
1141 
1142             delete[] pLutX;
1143             delete[] pLutY;
1144         }
1145 
1146         ReleaseAccess( pReadAcc );
1147         aNewBmp.ReleaseAccess( pWriteAcc );
1148 
1149         if( bRet )
1150             ImplAssignWithSize( aNewBmp );
1151     }
1152 
1153     return bRet;
1154 }
1155 
1156 // ------------------------------------------------------------------------
1157 
1158 sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1159 {
1160     const Size  aSizePix( GetSizePixel() );
1161     const long  nNewWidth = FRound( aSizePix.Width() * rScaleX );
1162     const long  nNewHeight = FRound( aSizePix.Height() * rScaleY );
1163     sal_Bool        bRet = sal_False;
1164 
1165     if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1166     {
1167         BitmapColor         aCol0;
1168         BitmapColor         aCol1;
1169         BitmapReadAccess*   pReadAcc = AcquireReadAccess();
1170         long                nWidth = pReadAcc->Width();
1171         long                nHeight = pReadAcc->Height();
1172         Bitmap              aNewBmp( Size( nNewWidth, nHeight ), 24 );
1173         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
1174         long*               pLutInt;
1175         long*               pLutFrac;
1176         long                nX, nY;
1177         long                lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1178         double              fTemp;
1179         long                nTemp;
1180 
1181         if( pReadAcc && pWriteAcc )
1182         {
1183             const long      nNewWidth1 = nNewWidth - 1L;
1184             const long      nWidth1 = pReadAcc->Width() - 1L;
1185             const double    fRevScaleX = (double) nWidth1 / nNewWidth1;
1186 
1187             pLutInt = new long[ nNewWidth ];
1188             pLutFrac = new long[ nNewWidth ];
1189 
1190             for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1191             {
1192                 fTemp = nX * fRevScaleX;
1193                 pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1194                 fTemp -= pLutInt[ nX ];
1195                 pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1196             }
1197 
1198             if( pReadAcc->HasPalette() )
1199             {
1200                 for( nY = 0L; nY < nHeight; nY++ )
1201                 {
1202                     if( 1 == nWidth )
1203                     {
1204                         aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) );
1205 
1206                         for( nX = 0L; nX < nNewWidth; nX++ )
1207                             pWriteAcc->SetPixel( nY, nX, aCol0 );
1208                     }
1209                     else
1210                     {
1211                         for( nX = 0L; nX < nNewWidth; nX++ )
1212                         {
1213                             nTemp = pLutInt[ nX ];
1214 
1215                             aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) );
1216                             aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) );
1217 
1218                             nTemp = pLutFrac[ nX ];
1219 
1220                             lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1221                             lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1222                             lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1223 
1224                             aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1225                             aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1226                             aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1227 
1228                             pWriteAcc->SetPixel( nY, nX, aCol0 );
1229                         }
1230                     }
1231                 }
1232             }
1233             else
1234             {
1235                 for( nY = 0L; nY < nHeight; nY++ )
1236                 {
1237                     if( 1 == nWidth )
1238                     {
1239                         aCol0 = pReadAcc->GetPixel( nY, 0 );
1240 
1241                         for( nX = 0L; nX < nNewWidth; nX++ )
1242                             pWriteAcc->SetPixel( nY, nX, aCol0 );
1243                     }
1244                     else
1245                     {
1246                         for( nX = 0L; nX < nNewWidth; nX++ )
1247                         {
1248                             nTemp = pLutInt[ nX ];
1249 
1250                             aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1251                             aCol1 = pReadAcc->GetPixel( nY, nTemp );
1252 
1253                             nTemp = pLutFrac[ nX ];
1254 
1255                             lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1256                             lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1257                             lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1258 
1259                             aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1260                             aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1261                             aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1262 
1263                             pWriteAcc->SetPixel( nY, nX, aCol0 );
1264                         }
1265                     }
1266                 }
1267             }
1268 
1269             delete[] pLutInt;
1270             delete[] pLutFrac;
1271             bRet = sal_True;
1272         }
1273 
1274         ReleaseAccess( pReadAcc );
1275         aNewBmp.ReleaseAccess( pWriteAcc );
1276 
1277         if( bRet )
1278         {
1279             bRet = sal_False;
1280             ImplAdaptBitCount(aNewBmp);
1281             ImplAssignWithSize( aNewBmp );
1282             pReadAcc = AcquireReadAccess();
1283             aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1284             pWriteAcc = aNewBmp.AcquireWriteAccess();
1285 
1286             if( pReadAcc && pWriteAcc )
1287             {
1288                 const long      nNewHeight1 = nNewHeight - 1L;
1289                 const long      nHeight1 = pReadAcc->Height() - 1L;
1290                 const double    fRevScaleY = (double) nHeight1 / nNewHeight1;
1291 
1292                 pLutInt = new long[ nNewHeight ];
1293                 pLutFrac = new long[ nNewHeight ];
1294 
1295                 for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1296                 {
1297                     fTemp = nY * fRevScaleY;
1298                     pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1299                     fTemp -= pLutInt[ nY ];
1300                     pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1301                 }
1302 
1303                 if( pReadAcc->HasPalette() )
1304                 {
1305                     for( nX = 0L; nX < nNewWidth; nX++ )
1306                     {
1307                         if( 1 == nHeight )
1308                         {
1309                             aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nX ) );
1310 
1311                             for( nY = 0L; nY < nNewHeight; nY++ )
1312                                 pWriteAcc->SetPixel( nY, nX, aCol0 );
1313                         }
1314                         else
1315                         {
1316                             for( nY = 0L; nY < nNewHeight; nY++ )
1317                             {
1318                                 nTemp = pLutInt[ nY ];
1319 
1320                                 aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nTemp++, nX ) );
1321                                 aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nTemp, nX ) );
1322 
1323                                 nTemp = pLutFrac[ nY ];
1324 
1325                                 lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1326                                 lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1327                                 lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1328 
1329                                 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1330                                 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1331                                 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1332 
1333                                 pWriteAcc->SetPixel( nY, nX, aCol0 );
1334                             }
1335                         }
1336                     }
1337                 }
1338                 else
1339                 {
1340                     for( nX = 0L; nX < nNewWidth; nX++ )
1341                     {
1342                         if( 1 == nHeight )
1343                         {
1344                             aCol0 = pReadAcc->GetPixel( 0, nX );
1345 
1346                             for( nY = 0L; nY < nNewHeight; nY++ )
1347                                 pWriteAcc->SetPixel( nY, nX, aCol0 );
1348                         }
1349                         else
1350                         {
1351                             for( nY = 0L; nY < nNewHeight; nY++ )
1352                             {
1353                                 nTemp = pLutInt[ nY ];
1354 
1355                                 aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1356                                 aCol1 = pReadAcc->GetPixel( nTemp, nX );
1357 
1358                                 nTemp = pLutFrac[ nY ];
1359 
1360                                 lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1361                                 lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1362                                 lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1363 
1364                                 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1365                                 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1366                                 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1367 
1368                                 pWriteAcc->SetPixel( nY, nX, aCol0 );
1369                             }
1370                         }
1371                     }
1372                 }
1373 
1374                 delete[] pLutInt;
1375                 delete[] pLutFrac;
1376                 bRet = sal_True;
1377             }
1378 
1379             ReleaseAccess( pReadAcc );
1380             aNewBmp.ReleaseAccess( pWriteAcc );
1381 
1382             if( bRet )
1383             {
1384                 ImplAdaptBitCount(aNewBmp);
1385                 ImplAssignWithSize( aNewBmp );
1386             }
1387         }
1388     }
1389 
1390     if( !bRet )
1391         bRet = ImplScaleFast( rScaleX, rScaleY );
1392 
1393     return bRet;
1394 }
1395 
1396 // ------------------------------------------------------------------------
1397 // #121233# Added BMP_SCALE_SUPER from symphony code
1398 
1399 sal_Bool Bitmap::ImplScaleSuper(
1400     const double& rScaleX,
1401     const double& rScaleY )
1402 {
1403     const Size  aSizePix( GetSizePixel() );
1404     bool   bHMirr = ( rScaleX < 0 );
1405     bool   bVMirr = ( rScaleY < 0 );
1406     double scaleX = bHMirr ? -rScaleX : rScaleX;
1407     double scaleY = bVMirr ? -rScaleY : rScaleY;
1408     const long  nDstW = FRound( aSizePix.Width() * scaleX );
1409     const long  nDstH = FRound( aSizePix.Height() * scaleY );
1410     const double fScaleThresh = 0.6;
1411     bool bRet = false;
1412 
1413     if( ( nDstW > 1L ) && ( nDstH > 1L ) )
1414     {
1415         BitmapColor         aCol0, aCol1, aColRes;
1416         BitmapReadAccess*   pAcc = AcquireReadAccess();
1417         long                nW = pAcc->Width() ;
1418         long                nH = pAcc->Height() ;
1419         Bitmap              aOutBmp( Size( nDstW, nDstH ), 24 );
1420         BitmapWriteAccess*  pWAcc = aOutBmp.AcquireWriteAccess();
1421         long*               pMapIX = new long[ nDstW ];
1422         long*               pMapIY = new long[ nDstH ];
1423         long*               pMapFX = new long[ nDstW ];
1424         long*               pMapFY = new long[ nDstH ];
1425         long                nX, nY, nXDst, nYDst;;
1426         double              fTemp;
1427         long                nTemp , nTempX, nTempY, nTempFX, nTempFY;
1428         sal_uInt8           cR0, cG0, cB0, cR1, cG1, cB1;
1429         long                nStartX = 0 , nStartY = 0;
1430         long                nEndX = nDstW - 1L;
1431         long                nEndY = nDstH - 1L;
1432         long                nMax = 1 << 7L;
1433 
1434         if( pAcc && pWAcc )
1435         {
1436             const double    fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0;
1437             const double    fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0;
1438 
1439             // create horizontal mapping table
1440             for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ )
1441             {
1442                 fTemp = nX * fRevScaleX;
1443 
1444                 if( bHMirr )
1445                     fTemp = nTempX - fTemp;
1446 
1447                 pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
1448             }
1449 
1450             // create vertical mapping table
1451             for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ )
1452             {
1453                 fTemp = nY * fRevScaleY;
1454 
1455                 if( bVMirr )
1456                     fTemp = nTempY - fTemp;
1457 
1458                 pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
1459             }
1460 
1461             if( pAcc->HasPalette() )
1462             {
1463                 if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1464                 {
1465                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1466                     {
1467                         Scanline pLine0, pLine1;
1468 
1469                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1470                         {
1471                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1472                             pLine0 = pAcc->GetScanline( nTempY );
1473                             pLine1 = pAcc->GetScanline( ++nTempY );
1474 
1475                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1476                             {
1477                                 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1478 
1479                                 const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] );
1480                                 const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
1481                                 const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] );
1482                                 const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
1483 
1484                                 cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
1485                                 cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
1486                                 cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
1487 
1488                                 cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
1489                                 cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
1490                                 cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
1491 
1492                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1493                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1494                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1495                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1496                             }
1497                         }
1498                     }
1499                     else
1500                     {
1501                         Scanline    pTmpY;
1502                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1503                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1504                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1505 
1506                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1507                         {
1508                             nTop = bVMirr ? ( nY + 1 ) : nY;
1509                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
1510 
1511                             if( nY ==nEndY )
1512                             {
1513                                 nLineStart = pMapIY[ nY ];
1514                                 nLineRange = 0;
1515                             }
1516                             else
1517                             {
1518                                 nLineStart = pMapIY[ nTop ] ;
1519                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1520                             }
1521 
1522                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1523                             {
1524                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
1525                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
1526 
1527                                 if( nX == nEndX )
1528                                 {
1529                                     nRowStart = pMapIX[ nX ];
1530                                     nRowRange = 0;
1531                                 }
1532                                 else
1533                                 {
1534                                     nRowStart = pMapIX[ nLeft ];
1535                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1536                                 }
1537 
1538                                 nSumR = nSumG = nSumB = 0;
1539                                 nTotalWeightY = 0;
1540 
1541                                 for(int i = 0; i<= nLineRange; i++)
1542                                 {
1543                                     pTmpY = pAcc->GetScanline( nLineStart + i );
1544                                     nSumRowR = nSumRowG = nSumRowB = 0;
1545                                     nTotalWeightX = 0;
1546 
1547                                     for(int j = 0; j <= nRowRange; j++)
1548                                     {
1549                                         const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] );
1550 
1551                                         if(nX == nEndX )
1552                                         {
1553                                             nSumRowB += rCol.GetBlue() << 7L;
1554                                             nSumRowG += rCol.GetGreen() << 7L;
1555                                             nSumRowR += rCol.GetRed() << 7L;
1556                                             nTotalWeightX += 1 << 7L;
1557                                         }
1558                                         else if( j == 0 )
1559                                         {
1560                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
1561                                             nSumRowB += ( nWeightX *rCol.GetBlue()) ;
1562                                             nSumRowG += ( nWeightX *rCol.GetGreen()) ;
1563                                             nSumRowR += ( nWeightX *rCol.GetRed()) ;
1564                                             nTotalWeightX += nWeightX;
1565                                         }
1566                                         else if ( nRowRange == j )
1567                                         {
1568                                             nWeightX = pMapFX[ nRight ] ;
1569                                             nSumRowB += ( nWeightX *rCol.GetBlue() );
1570                                             nSumRowG += ( nWeightX *rCol.GetGreen() );
1571                                             nSumRowR += ( nWeightX *rCol.GetRed() );
1572                                             nTotalWeightX += nWeightX;
1573                                         }
1574                                         else
1575                                         {
1576                                             nSumRowB += rCol.GetBlue() << 7L;
1577                                             nSumRowG += rCol.GetGreen() << 7L;
1578                                             nSumRowR += rCol.GetRed() << 7L;
1579                                             nTotalWeightX += 1 << 7L;
1580                                         }
1581                                     }
1582 
1583                                     if( nY == nEndY )
1584                                         nWeightY = nMax;
1585                                     else if( i == 0 )
1586                                         nWeightY = nMax - pMapFY[ nTop ];
1587                                     else if( nLineRange == 1 )
1588                                         nWeightY = pMapFY[ nTop ];
1589                                     else if ( nLineRange == i )
1590                                         nWeightY = pMapFY[ nBottom ];
1591                                     else
1592                                         nWeightY = nMax;
1593 
1594                                     nWeightY = nWeightY ;
1595                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1596                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1597                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1598                                     nTotalWeightY += nWeightY;
1599                                 }
1600 
1601                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1602                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1603                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1604                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1605 
1606                             }
1607                         }
1608                     }
1609 }
1610                 else
1611                 {
1612                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1613                     {
1614                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1615                         {
1616                             nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ];
1617 
1618                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1619                             {
1620                                 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1621 
1622                                 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) );
1623                                 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) );
1624                                 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1625                                 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1626                                 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1627 
1628                                 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) );
1629                                 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) );
1630                                 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1631                                 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1632                                 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1633 
1634                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1635                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1636                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1637                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1638                             }
1639                         }
1640 
1641                     }
1642                     else
1643                     {
1644                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1645                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1646                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1647 
1648                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1649                         {
1650                             nTop = bVMirr ? ( nY + 1 ) : nY;
1651                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
1652 
1653                             if( nY ==nEndY )
1654                             {
1655                                 nLineStart = pMapIY[ nY ];
1656                                 nLineRange = 0;
1657                             }
1658                             else
1659                             {
1660                                 nLineStart = pMapIY[ nTop ] ;
1661                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1662                             }
1663 
1664                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1665                             {
1666                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
1667                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
1668 
1669                                 if( nX == nEndX )
1670                                 {
1671                                     nRowStart = pMapIX[ nX ];
1672                                     nRowRange = 0;
1673                                 }
1674                                 else
1675                                 {
1676                                     nRowStart = pMapIX[ nLeft ];
1677                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1678                                 }
1679 
1680                                 nSumR = nSumG = nSumB = 0;
1681                                 nTotalWeightY = 0;
1682 
1683                                 for(int i = 0; i<= nLineRange; i++)
1684                                 {
1685                                     nSumRowR = nSumRowG = nSumRowB = 0;
1686                                     nTotalWeightX = 0;
1687 
1688                                     for(int j = 0; j <= nRowRange; j++)
1689                                     {
1690                                         aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
1691 
1692                                         if(nX == nEndX )
1693                                         {
1694 
1695                                             nSumRowB += aCol0.GetBlue() << 7L;
1696                                             nSumRowG += aCol0.GetGreen() << 7L;
1697                                             nSumRowR += aCol0.GetRed() << 7L;
1698                                             nTotalWeightX += 1 << 7L;
1699                                         }
1700                                         else if( j == 0 )
1701                                         {
1702 
1703                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
1704                                             nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
1705                                             nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
1706                                             nSumRowR += ( nWeightX *aCol0.GetRed()) ;
1707                                             nTotalWeightX += nWeightX;
1708                                         }
1709                                         else if ( nRowRange == j )
1710                                         {
1711 
1712                                             nWeightX = pMapFX[ nRight ] ;
1713                                             nSumRowB += ( nWeightX *aCol0.GetBlue() );
1714                                             nSumRowG += ( nWeightX *aCol0.GetGreen() );
1715                                             nSumRowR += ( nWeightX *aCol0.GetRed() );
1716                                             nTotalWeightX += nWeightX;
1717                                         }
1718                                         else
1719                                         {
1720 
1721                                             nSumRowB += aCol0.GetBlue() << 7L;
1722                                             nSumRowG += aCol0.GetGreen() << 7L;
1723                                             nSumRowR += aCol0.GetRed() << 7L;
1724                                             nTotalWeightX += 1 << 7L;
1725                                         }
1726                                     }
1727 
1728                                     if( nY == nEndY )
1729                                         nWeightY = nMax;
1730                                     else if( i == 0 )
1731                                         nWeightY = nMax - pMapFY[ nTop ];
1732                                     else if( nLineRange == 1 )
1733                                         nWeightY = pMapFY[ nTop ];
1734                                     else if ( nLineRange == i )
1735                                         nWeightY = pMapFY[ nBottom ];
1736                                     else
1737                                         nWeightY = nMax;
1738 
1739                                     nWeightY = nWeightY ;
1740                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1741                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1742                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1743                                     nTotalWeightY += nWeightY;
1744                                 }
1745 
1746                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1747                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1748                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1749                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1750                             }
1751                         }
1752                     }
1753                 }
1754             }
1755             else
1756             {
1757                 if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
1758                 {
1759                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1760                     {
1761                         Scanline    pLine0, pLine1, pTmp0, pTmp1;
1762                         long        nOff;
1763 
1764                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1765                         {
1766                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1767                             pLine0 = pAcc->GetScanline( nTempY );
1768                             pLine1 = pAcc->GetScanline( ++nTempY );
1769 
1770                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1771                             {
1772                                 nOff = 3L * ( nTempX = pMapIX[ nX ] );
1773                                 nTempFX = pMapFX[ nX ];
1774 
1775                                 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1776                                 cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1777                                 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1778                                 cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
1779 
1780                                 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1781                                 cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1782                                 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1783                                 cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
1784 
1785                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1786                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1787                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1788                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1789                             }
1790                         }
1791                     }
1792                     else
1793                     {
1794                         Scanline    pTmpY, pTmpX;
1795                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1796                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1797                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1798 
1799                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1800                         {
1801                             nTop = bVMirr ? ( nY + 1 ) : nY;
1802                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
1803 
1804                             if( nY ==nEndY )
1805                             {
1806                                 nLineStart = pMapIY[ nY ];
1807                                 nLineRange = 0;
1808                             }
1809                             else
1810                             {
1811                                 nLineStart = pMapIY[ nTop ] ;
1812                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1813                             }
1814 
1815                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1816                             {
1817                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
1818                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
1819 
1820                                 if( nX == nEndX  )
1821                                 {
1822                                     nRowStart = pMapIX[ nX ];
1823                                     nRowRange = 0;
1824                                 }
1825                                 else
1826                                 {
1827                                     nRowStart = pMapIX[ nLeft ];
1828                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1829                                 }
1830 
1831                                 nSumR = nSumG = nSumB = 0;
1832                                 nTotalWeightY = 0;
1833 
1834                                 for(int i = 0; i<= nLineRange; i++)
1835                                 {
1836                                     pTmpY = pAcc->GetScanline( nLineStart + i );
1837                                     pTmpX = pTmpY + 3L * nRowStart;
1838                                     nSumRowR = nSumRowG = nSumRowB = 0;
1839                                     nTotalWeightX = 0;
1840 
1841                                     for(int j = 0; j <= nRowRange; j++)
1842                                     {
1843                                         if(nX == nEndX )
1844                                         {
1845                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1846                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1847                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1848                                             nTotalWeightX += 1 << 7L;
1849                                         }
1850                                         else if( j == 0 )
1851                                         {
1852                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
1853                                             nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
1854                                             nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
1855                                             nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
1856                                             nTotalWeightX += nWeightX;
1857                                         }
1858                                         else if ( nRowRange == j )
1859                                         {
1860                                             nWeightX = pMapFX[ nRight ] ;
1861                                             nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
1862                                             nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
1863                                             nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
1864                                             nTotalWeightX += nWeightX;
1865                                         }
1866                                         else
1867                                         {
1868                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1869                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1870                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1871                                             nTotalWeightX += 1 << 7L;
1872                                         }
1873                                     }
1874 
1875                                     if( nY == nEndY )
1876                                         nWeightY = nMax;
1877                                     else if( i == 0 )
1878                                         nWeightY = nMax - pMapFY[ nTop ];
1879                                     else if( nLineRange == 1 )
1880                                         nWeightY = pMapFY[ nTop ];
1881                                     else if ( nLineRange == i )
1882                                         nWeightY = pMapFY[ nBottom ];
1883                                     else
1884                                         nWeightY = nMax;
1885 
1886                                     nWeightY = nWeightY ;
1887                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1888                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1889                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1890                                     nTotalWeightY += nWeightY;
1891                                 }
1892 
1893                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1894                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1895                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1896                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1897 
1898                             }
1899                         }
1900                     }
1901                 }
1902                 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
1903                 {
1904                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1905                     {
1906                         Scanline    pLine0, pLine1, pTmp0, pTmp1;
1907                         long        nOff;
1908 
1909                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1910                         {
1911                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1912                             pLine0 = pAcc->GetScanline( nTempY );
1913                             pLine1 = pAcc->GetScanline( ++nTempY );
1914 
1915                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1916                             {
1917                                 nOff = 3L * ( nTempX = pMapIX[ nX ] );
1918                                 nTempFX = pMapFX[ nX ];
1919 
1920                                 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1921                                 cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1922                                 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1923                                 cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
1924 
1925                                 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1926                                 cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1927                                 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1928                                 cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
1929 
1930                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1931                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1932                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1933                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1934                             }
1935                         }
1936                     }
1937                     else
1938                     {
1939                         Scanline    pTmpY, pTmpX;
1940                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1941                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1942                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1943 
1944                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1945                         {
1946                             nTop = bVMirr ? ( nY + 1 ) : nY;
1947                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
1948 
1949                             if( nY ==nEndY )
1950                             {
1951                                 nLineStart = pMapIY[ nY ];
1952                                 nLineRange = 0;
1953                             }
1954                             else
1955                             {
1956                                 nLineStart = pMapIY[ nTop ] ;
1957                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1958                             }
1959 
1960                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1961                             {
1962                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
1963                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
1964 
1965                                 if( nX == nEndX )
1966                                 {
1967                                     nRowStart = pMapIX[ nX ];
1968                                     nRowRange = 0;
1969                                 }
1970                                 else
1971                                 {
1972                                     nRowStart = pMapIX[ nLeft ];
1973                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1974                                 }
1975 
1976                                 nSumR = nSumG = nSumB = 0;
1977                                 nTotalWeightY = 0;
1978 
1979                                 for(int i = 0; i<= nLineRange; i++)
1980                                 {
1981                                     pTmpY = pAcc->GetScanline( nLineStart + i );
1982                                     pTmpX = pTmpY + 3L * nRowStart;
1983                                     nSumRowR = nSumRowG = nSumRowB = 0;
1984                                     nTotalWeightX = 0;
1985 
1986                                     for(int j = 0; j <= nRowRange; j++)
1987                                     {
1988                                         if(nX == nEndX )
1989                                         {
1990                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1991                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1992                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1993                                             nTotalWeightX += 1 << 7L;
1994                                         }
1995                                         else if( j == 0 )
1996                                         {
1997                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
1998                                             nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
1999                                             nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
2000                                             nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
2001                                             nTotalWeightX += nWeightX;
2002                                         }
2003                                         else if ( nRowRange == j )
2004                                         {
2005                                             nWeightX = pMapFX[ nRight ] ;
2006                                             nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
2007                                             nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
2008                                             nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
2009                                             nTotalWeightX += nWeightX;
2010                                         }
2011                                         else
2012                                         {
2013                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
2014                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
2015                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
2016                                             nTotalWeightX += 1 << 7L;
2017                                         }
2018                                     }
2019 
2020                                     if( nY == nEndY )
2021                                         nWeightY = nMax;
2022                                     else if( i == 0 )
2023                                         nWeightY = nMax - pMapFY[ nTop ];
2024                                     else if( nLineRange == 1 )
2025                                         nWeightY = pMapFY[ nTop ];
2026                                     else if ( nLineRange == i )
2027                                         nWeightY = pMapFY[ nBottom ];
2028                                     else
2029                                         nWeightY = nMax;
2030 
2031                                     nWeightY = nWeightY ;
2032                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
2033                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
2034                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
2035                                     nTotalWeightY += nWeightY;
2036                                 }
2037 
2038                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
2039                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
2040                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
2041                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2042 
2043                             }
2044                         }
2045                     }
2046                 }
2047                 else
2048                 {
2049                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
2050                     {
2051                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
2052                         {
2053                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
2054 
2055                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
2056                             {
2057                                 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
2058 
2059                                 aCol0 = pAcc->GetPixel( nTempY, nTempX );
2060                                 aCol1 = pAcc->GetPixel( nTempY, ++nTempX );
2061                                 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
2062                                 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
2063                                 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
2064 
2065                                 aCol1 = pAcc->GetPixel( ++nTempY, nTempX );
2066                                 aCol0 = pAcc->GetPixel( nTempY--, --nTempX );
2067                                 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
2068                                 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
2069                                 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
2070 
2071                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
2072                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
2073                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
2074                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2075                             }
2076                         }
2077                     }
2078                     else
2079                     {
2080                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
2081                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
2082                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
2083 
2084                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
2085                         {
2086                             nTop = bVMirr ? ( nY + 1 ) : nY;
2087                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
2088 
2089                             if( nY ==nEndY )
2090                             {
2091                                 nLineStart = pMapIY[ nY ];
2092                                 nLineRange = 0;
2093                             }
2094                             else
2095                             {
2096                                 nLineStart = pMapIY[ nTop ] ;
2097                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
2098                             }
2099 
2100                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
2101                             {
2102                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
2103                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
2104 
2105                                 if( nX == nEndX )
2106                                 {
2107                                     nRowStart = pMapIX[ nX ];
2108                                     nRowRange = 0;
2109                                 }
2110                                 else
2111                                 {
2112                                     nRowStart = pMapIX[ nLeft ];
2113                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
2114                                 }
2115 
2116                                 nSumR = nSumG = nSumB = 0;
2117                                 nTotalWeightY = 0;
2118 
2119                                 for(int i = 0; i<= nLineRange; i++)
2120                                 {
2121                                     nSumRowR = nSumRowG = nSumRowB = 0;
2122                                     nTotalWeightX = 0;
2123 
2124                                     for(int j = 0; j <= nRowRange; j++)
2125                                     {
2126                                         aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j );
2127 
2128                                         if(nX == nEndX )
2129                                         {
2130 
2131                                             nSumRowB += aCol0.GetBlue() << 7L;
2132                                             nSumRowG += aCol0.GetGreen() << 7L;
2133                                             nSumRowR += aCol0.GetRed() << 7L;
2134                                             nTotalWeightX += 1 << 7L;
2135                                         }
2136                                         else if( j == 0 )
2137                                         {
2138 
2139                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
2140                                             nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
2141                                             nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
2142                                             nSumRowR += ( nWeightX *aCol0.GetRed()) ;
2143                                             nTotalWeightX += nWeightX;
2144                                         }
2145                                         else if ( nRowRange == j )
2146                                         {
2147 
2148                                             nWeightX = pMapFX[ nRight ] ;
2149                                             nSumRowB += ( nWeightX *aCol0.GetBlue() );
2150                                             nSumRowG += ( nWeightX *aCol0.GetGreen() );
2151                                             nSumRowR += ( nWeightX *aCol0.GetRed() );
2152                                             nTotalWeightX += nWeightX;
2153                                         }
2154                                         else
2155                                         {
2156                                             nSumRowB += aCol0.GetBlue() << 7L;
2157                                             nSumRowG += aCol0.GetGreen() << 7L;
2158                                             nSumRowR += aCol0.GetRed() << 7L;
2159                                             nTotalWeightX += 1 << 7L;
2160                                         }
2161                                     }
2162 
2163                                     if( nY == nEndY )
2164                                         nWeightY = nMax;
2165                                     else if( i == 0 )
2166                                         nWeightY = nMax - pMapFY[ nTop ];
2167                                     else if( nLineRange == 1 )
2168                                         nWeightY = pMapFY[ nTop ];
2169                                     else if ( nLineRange == i )
2170                                         nWeightY = pMapFY[ nBottom ];
2171                                     else
2172                                         nWeightY = nMax;
2173 
2174                                     nWeightY = nWeightY ;
2175                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
2176                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
2177                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
2178                                     nTotalWeightY += nWeightY;
2179                                 }
2180 
2181                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
2182                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
2183                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
2184                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2185 
2186                             }
2187                         }
2188                     }
2189                 }
2190             }
2191 
2192             bRet = true;
2193         }
2194 
2195         delete[] pMapIX;
2196         delete[] pMapIY;
2197         delete[] pMapFX;
2198         delete[] pMapFY;
2199 
2200         ReleaseAccess( pAcc );
2201         aOutBmp.ReleaseAccess( pWAcc );
2202 
2203         if( bRet )
2204         {
2205             ImplAdaptBitCount(aOutBmp);
2206             ImplAssignWithSize(aOutBmp);
2207         }
2208 
2209         if( !bRet )
2210             bRet = ImplScaleFast( scaleX, scaleY );
2211     }
2212 
2213     return bRet;
2214 }
2215 
2216 //-----------------------------------------------------------------------------------
2217 
2218 namespace
2219 {
2220     void ImplCalculateContributions(
2221         const sal_uInt32 aSourceSize,
2222         const sal_uInt32 aDestinationSize,
2223         sal_uInt32& aNumberOfContributions,
2224         double*& pWeights,
2225         sal_uInt32*& pPixels,
2226         sal_uInt32*& pCount,
2227         const Kernel& aKernel)
2228     {
2229         const double fSamplingRadius(aKernel.GetWidth());
2230         const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
2231         const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
2232         const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
2233 
2234         aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
2235         const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
2236         pWeights = new double[nAllocSize];
2237         pPixels = new sal_uInt32[nAllocSize];
2238         pCount = new sal_uInt32[aDestinationSize];
2239 
2240         for(sal_uInt32 i(0); i < aDestinationSize; i++)
2241         {
2242             const sal_uInt32 aIndex(i * aNumberOfContributions);
2243             const double aCenter(i / fScale);
2244             const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
2245             const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
2246             sal_uInt32 aCurrentCount(0);
2247 
2248             for(sal_Int32 j(aLeft); j <= aRight; j++)
2249             {
2250                 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
2251 
2252                 // Reduce calculations with ignoring weights of 0.0
2253                 if(fabs(aWeight) < 0.0001)
2254                 {
2255                     continue;
2256                 }
2257 
2258                 // Handling on edges
2259                 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
2260                 const sal_uInt32 nIndex(aIndex + aCurrentCount);
2261 
2262                 pWeights[nIndex] = aWeight;
2263                 pPixels[nIndex] = aPixelIndex;
2264 
2265                 aCurrentCount++;
2266             }
2267 
2268             pCount[i] = aCurrentCount;
2269         }
2270     }
2271 
2272     sal_Bool ImplScaleConvolutionHor(
2273         Bitmap& rSource,
2274         Bitmap& rTarget,
2275         const double& rScaleX,
2276         const Kernel& aKernel)
2277     {
2278         // Do horizontal filtering
2279         OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
2280         const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
2281         const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
2282 
2283         if(nWidth == nNewWidth)
2284         {
2285             return true;
2286         }
2287 
2288         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
2289 
2290         if(pReadAcc)
2291         {
2292             double* pWeights = 0;
2293             sal_uInt32* pPixels = 0;
2294             sal_uInt32* pCount = 0;
2295             sal_uInt32 aNumberOfContributions(0);
2296 
2297             const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
2298             ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
2299             rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
2300             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
2301             bool bResult(0 != pWriteAcc);
2302 
2303             if(bResult)
2304             {
2305                 for(sal_uInt32 y(0); y < nHeight; y++)
2306                 {
2307                     for(sal_uInt32 x(0); x < nNewWidth; x++)
2308                     {
2309                         const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
2310                         double aSum(0.0);
2311                         double aValueRed(0.0);
2312                         double aValueGreen(0.0);
2313                         double aValueBlue(0.0);
2314 
2315                         for(sal_uInt32 j(0); j < pCount[x]; j++)
2316                         {
2317                             const sal_uInt32 aIndex(aBaseIndex + j);
2318                             const double aWeight(pWeights[aIndex]);
2319                             BitmapColor aColor;
2320 
2321                             aSum += aWeight;
2322 
2323                             if(pReadAcc->HasPalette())
2324                             {
2325                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
2326                             }
2327                             else
2328                             {
2329                                 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
2330                             }
2331 
2332                             aValueRed += aWeight * aColor.GetRed();
2333                             aValueGreen += aWeight * aColor.GetGreen();
2334                             aValueBlue += aWeight * aColor.GetBlue();
2335                         }
2336 
2337                         const BitmapColor aResultColor(
2338                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
2339                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
2340                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
2341 
2342                         pWriteAcc->SetPixel(y, x, aResultColor);
2343                     }
2344                 }
2345 
2346                 rTarget.ReleaseAccess(pWriteAcc);
2347             }
2348 
2349             rSource.ReleaseAccess(pReadAcc);
2350             delete[] pWeights;
2351             delete[] pCount;
2352             delete[] pPixels;
2353 
2354             if(bResult)
2355             {
2356                 return true;
2357             }
2358         }
2359 
2360         return false;
2361     }
2362 
2363     bool ImplScaleConvolutionVer(
2364         Bitmap& rSource,
2365         Bitmap& rTarget,
2366         const double& rScaleY,
2367         const Kernel& aKernel)
2368     {
2369         // Do vertical filtering
2370         OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
2371         const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
2372         const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
2373 
2374         if(nHeight == nNewHeight)
2375         {
2376             return true;
2377         }
2378 
2379         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
2380 
2381         if(pReadAcc)
2382         {
2383             double* pWeights = 0;
2384             sal_uInt32* pPixels = 0;
2385             sal_uInt32* pCount = 0;
2386             sal_uInt32 aNumberOfContributions(0);
2387 
2388             const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
2389             ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
2390             rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
2391             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
2392             bool bResult(0 != pWriteAcc);
2393 
2394             if(pWriteAcc)
2395             {
2396                 for(sal_uInt32 x(0); x < nWidth; x++)
2397                 {
2398                     for(sal_uInt32 y(0); y < nNewHeight; y++)
2399                     {
2400                         const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
2401                         double aSum(0.0);
2402                         double aValueRed(0.0);
2403                         double aValueGreen(0.0);
2404                         double aValueBlue(0.0);
2405 
2406                         for(sal_uInt32 j(0); j < pCount[y]; j++)
2407                         {
2408                             const sal_uInt32 aIndex(aBaseIndex + j);
2409                             const double aWeight(pWeights[aIndex]);
2410                             BitmapColor aColor;
2411 
2412                             aSum += aWeight;
2413 
2414                             if(pReadAcc->HasPalette())
2415                             {
2416                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
2417                             }
2418                             else
2419                             {
2420                                 aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
2421                             }
2422 
2423                             aValueRed += aWeight * aColor.GetRed();
2424                             aValueGreen += aWeight * aColor.GetGreen();
2425                             aValueBlue += aWeight * aColor.GetBlue();
2426                         }
2427 
2428                         const BitmapColor aResultColor(
2429                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
2430                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
2431                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
2432 
2433                         if(pWriteAcc->HasPalette())
2434                         {
2435                             pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
2436                         }
2437                         else
2438                         {
2439                             pWriteAcc->SetPixel(y, x, aResultColor);
2440                         }
2441                     }
2442                 }
2443             }
2444 
2445             rTarget.ReleaseAccess(pWriteAcc);
2446             rSource.ReleaseAccess(pReadAcc);
2447 
2448             delete[] pWeights;
2449             delete[] pCount;
2450             delete[] pPixels;
2451 
2452             if(bResult)
2453             {
2454                 return true;
2455             }
2456         }
2457 
2458         return false;
2459     }
2460 }
2461 
2462 // #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and
2463 // BMP_SCALE_BOX derived from the original commit from Toma� Vajngerl (see
2464 // bugzilla task for deitails) Thanks!
2465 sal_Bool Bitmap::ImplScaleConvolution(
2466     const double& rScaleX,
2467     const double& rScaleY,
2468     const Kernel& aKernel)
2469 {
2470     const bool bMirrorHor(rScaleX < 0.0);
2471     const bool bMirrorVer(rScaleY < 0.0);
2472     const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
2473     const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
2474     const sal_uInt32 nWidth(GetSizePixel().Width());
2475     const sal_uInt32 nHeight(GetSizePixel().Height());
2476     const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
2477     const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
2478     const bool bScaleHor(nWidth != nNewWidth);
2479     const bool bScaleVer(nHeight != nNewHeight);
2480     const bool bMirror(bMirrorHor || bMirrorVer);
2481 
2482     if(!bMirror && !bScaleHor && !bScaleVer)
2483     {
2484         return true;
2485     }
2486 
2487     bool bResult(true);
2488     sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
2489     bool bMirrorAfter(false);
2490 
2491     if(bMirror)
2492     {
2493         if(bMirrorHor)
2494         {
2495             nMirrorFlags |= BMP_MIRROR_HORZ;
2496         }
2497 
2498         if(bMirrorVer)
2499         {
2500             nMirrorFlags |= BMP_MIRROR_VERT;
2501         }
2502 
2503         const sal_uInt32 nStartSize(nWidth * nHeight);
2504         const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
2505 
2506         bMirrorAfter = nStartSize > nEndSize;
2507 
2508         if(!bMirrorAfter)
2509         {
2510             bResult = Mirror(nMirrorFlags);
2511         }
2512     }
2513 
2514     Bitmap aResult;
2515 
2516     if(bResult)
2517     {
2518         const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
2519         const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
2520 
2521         if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
2522         {
2523             if(bScaleHor)
2524             {
2525                 bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel);
2526             }
2527 
2528             if(bResult && bScaleVer)
2529             {
2530                 bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel);
2531             }
2532         }
2533         else
2534         {
2535             if(bScaleVer)
2536             {
2537                 bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel);
2538             }
2539 
2540             if(bResult && bScaleHor)
2541             {
2542                 bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel);
2543             }
2544         }
2545     }
2546 
2547     if(bResult && bMirrorAfter)
2548     {
2549         bResult = aResult.Mirror(nMirrorFlags);
2550     }
2551 
2552     if(bResult)
2553     {
2554         ImplAdaptBitCount(aResult);
2555         *this = aResult;
2556     }
2557 
2558     return bResult;
2559 }
2560 
2561 // ------------------------------------------------------------------------
2562 
2563 sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
2564 {
2565     sal_Bool bRet = sal_False;
2566 
2567     const Size aSizePix( GetSizePixel() );
2568 
2569     if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
2570         bRet = sal_True;
2571     else if( nDitherFlags & BMP_DITHER_MATRIX )
2572         bRet = ImplDitherMatrix();
2573     else if( nDitherFlags & BMP_DITHER_FLOYD )
2574         bRet = ImplDitherFloyd();
2575     else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
2576         bRet = ImplDitherFloyd16();
2577 
2578     return bRet;
2579 }
2580 
2581 // ------------------------------------------------------------------------
2582 
2583 sal_Bool Bitmap::ImplDitherMatrix()
2584 {
2585     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
2586     Bitmap              aNewBmp( GetSizePixel(), 8 );
2587     BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
2588     sal_Bool                bRet = sal_False;
2589 
2590     if( pReadAcc && pWriteAcc )
2591     {
2592         const sal_uLong nWidth = pReadAcc->Width();
2593         const sal_uLong nHeight = pReadAcc->Height();
2594         BitmapColor aIndex( (sal_uInt8) 0 );
2595 
2596         if( pReadAcc->HasPalette() )
2597         {
2598             for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2599             {
2600                 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2601                 {
2602                     const BitmapColor   aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
2603                     const sal_uLong         nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2604                     const sal_uLong         nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2605                     const sal_uLong         nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2606                     const sal_uLong         nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2607 
2608                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2609                     pWriteAcc->SetPixel( nY, nX, aIndex );
2610                 }
2611             }
2612         }
2613         else
2614         {
2615             for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2616             {
2617                 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2618                 {
2619                     const BitmapColor   aCol( pReadAcc->GetPixel( nY, nX ) );
2620                     const sal_uLong         nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2621                     const sal_uLong         nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2622                     const sal_uLong         nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2623                     const sal_uLong         nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2624 
2625                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2626                     pWriteAcc->SetPixel( nY, nX, aIndex );
2627                 }
2628             }
2629         }
2630 
2631         bRet = sal_True;
2632     }
2633 
2634     ReleaseAccess( pReadAcc );
2635     aNewBmp.ReleaseAccess( pWriteAcc );
2636 
2637     if( bRet )
2638     {
2639         const MapMode   aMap( maPrefMapMode );
2640         const Size      aSize( maPrefSize );
2641 
2642         *this = aNewBmp;
2643 
2644         maPrefMapMode = aMap;
2645         maPrefSize = aSize;
2646     }
2647 
2648     return bRet;
2649 }
2650 
2651 // ------------------------------------------------------------------------
2652 
2653 sal_Bool Bitmap::ImplDitherFloyd()
2654 {
2655     const Size  aSize( GetSizePixel() );
2656     sal_Bool        bRet = sal_False;
2657 
2658     if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
2659     {
2660         BitmapReadAccess*   pReadAcc = AcquireReadAccess();
2661         Bitmap              aNewBmp( GetSizePixel(), 8 );
2662         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
2663 
2664         if( pReadAcc && pWriteAcc )
2665         {
2666             BitmapColor aColor;
2667             long        nWidth = pReadAcc->Width();
2668             long        nWidth1 = nWidth - 1L;
2669             long        nHeight = pReadAcc->Height();
2670             long        nX;
2671             long        nW = nWidth * 3L;
2672             long        nW2 = nW - 3L;
2673             long        nRErr, nGErr, nBErr;
2674             long        nRC, nGC, nBC;
2675             long        nTemp;
2676             long        nZ;
2677             long*       p1 = new long[ nW ];
2678             long*       p2 = new long[ nW ];
2679             long*       p1T = p1;
2680             long*       p2T = p2;
2681             long*       pTmp;
2682             sal_Bool        bPal = pReadAcc->HasPalette();
2683 
2684             pTmp = p2T;
2685 
2686             if( bPal )
2687             {
2688                 for( nZ = 0; nZ < nWidth; nZ++ )
2689                 {
2690                     aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) );
2691 
2692                     *pTmp++ = (long) aColor.GetBlue() << 12;
2693                     *pTmp++ = (long) aColor.GetGreen() << 12;
2694                     *pTmp++ = (long) aColor.GetRed() << 12;
2695                 }
2696             }
2697             else
2698             {
2699                 for( nZ = 0; nZ < nWidth; nZ++ )
2700                 {
2701                     aColor = pReadAcc->GetPixel( 0, nZ );
2702 
2703                     *pTmp++ = (long) aColor.GetBlue() << 12;
2704                     *pTmp++ = (long) aColor.GetGreen() << 12;
2705                     *pTmp++ = (long) aColor.GetRed() << 12;
2706                 }
2707             }
2708 
2709             for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
2710             {
2711                 pTmp = p1T;
2712                 p1T = p2T;
2713                 p2T = pTmp;
2714 
2715                 if( nY < nHeight )
2716                 {
2717                     if( bPal )
2718                     {
2719                         for( nZ = 0; nZ < nWidth; nZ++ )
2720                         {
2721                             aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) );
2722 
2723                             *pTmp++ = (long) aColor.GetBlue() << 12;
2724                             *pTmp++ = (long) aColor.GetGreen() << 12;
2725                             *pTmp++ = (long) aColor.GetRed() << 12;
2726                         }
2727                     }
2728                     else
2729                     {
2730                         for( nZ = 0; nZ < nWidth; nZ++ )
2731                         {
2732                             aColor = pReadAcc->GetPixel( nY, nZ );
2733 
2734                             *pTmp++ = (long) aColor.GetBlue() << 12;
2735                             *pTmp++ = (long) aColor.GetGreen() << 12;
2736                             *pTmp++ = (long) aColor.GetRed() << 12;
2737                         }
2738                     }
2739                 }
2740 
2741                 // erstes Pixel gesondert betrachten
2742                 nX = 0;
2743                 CALC_ERRORS;
2744                 CALC_TABLES7;
2745                 nX -= 5;
2746                 CALC_TABLES5;
2747                 pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2748 
2749                 // mittlere Pixel ueber Schleife
2750                 long nXAcc;
2751                 for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
2752                 {
2753                     CALC_ERRORS;
2754                     CALC_TABLES7;
2755                     nX -= 8;
2756                     CALC_TABLES3;
2757                     CALC_TABLES5;
2758                     pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2759                 }
2760 
2761                 // letztes Pixel gesondert betrachten
2762                 CALC_ERRORS;
2763                 nX -= 5;
2764                 CALC_TABLES3;
2765                 CALC_TABLES5;
2766                 pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2767             }
2768 
2769             delete[] p1;
2770             delete[] p2;
2771             bRet = sal_True;
2772         }
2773 
2774         ReleaseAccess( pReadAcc );
2775         aNewBmp.ReleaseAccess( pWriteAcc );
2776 
2777         if( bRet )
2778         {
2779             const MapMode   aMap( maPrefMapMode );
2780             const Size      aPrefSize( maPrefSize );
2781 
2782             *this = aNewBmp;
2783 
2784             maPrefMapMode = aMap;
2785             maPrefSize = aPrefSize;
2786         }
2787     }
2788 
2789     return bRet;
2790 }
2791 
2792 // ------------------------------------------------------------------------
2793 
2794 sal_Bool Bitmap::ImplDitherFloyd16()
2795 {
2796     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
2797     Bitmap              aNewBmp( GetSizePixel(), 24 );
2798     BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
2799     sal_Bool                bRet = sal_False;
2800 
2801     if( pReadAcc && pWriteAcc )
2802     {
2803         const long      nWidth = pWriteAcc->Width();
2804         const long      nWidth1 = nWidth - 1L;
2805         const long      nHeight = pWriteAcc->Height();
2806         BitmapColor     aColor;
2807         BitmapColor     aBestCol;
2808         ImpErrorQuad    aErrQuad;
2809         ImpErrorQuad*   pErrQuad1 = new ImpErrorQuad[ nWidth ];
2810         ImpErrorQuad*   pErrQuad2 = new ImpErrorQuad[ nWidth ];
2811         ImpErrorQuad*   pQLine1 = pErrQuad1;
2812         ImpErrorQuad*   pQLine2 = 0;
2813         long            nX, nY;
2814         long            nYTmp = 0L;
2815         sal_Bool            bQ1 = sal_True;
2816 
2817         for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
2818             for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
2819                 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2820 
2821         for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
2822         {
2823             // erstes ZeilenPixel
2824             aBestCol = pQLine1[ 0 ].ImplGetColor();
2825             aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2826             aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2827             aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2828             pWriteAcc->SetPixel( nY, 0, aBestCol );
2829 
2830             for( nX = 1L; nX < nWidth1; nX++ )
2831             {
2832                 aColor = pQLine1[ nX ].ImplGetColor();
2833                 aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
2834                 aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
2835                 aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
2836                 aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
2837                 pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
2838                 pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
2839                 pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
2840                 pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
2841                 pWriteAcc->SetPixel( nY, nX, aBestCol );
2842             }
2843 
2844             // letztes ZeilenPixel
2845             aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
2846             aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2847             aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2848             aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2849             pWriteAcc->SetPixel( nY, nX, aBestCol );
2850 
2851             // Zeilenpuffer neu fuellen/kopieren
2852             pQLine1 = pQLine2;
2853             pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
2854 
2855             if( nYTmp < nHeight )
2856                 for( nX = 0L; nX < nWidth; nX++ )
2857                     pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2858         }
2859 
2860         // Zeilenpuffer zerstoeren
2861         delete[] pErrQuad1;
2862         delete[] pErrQuad2;
2863         bRet = sal_True;
2864     }
2865 
2866     ReleaseAccess( pReadAcc );
2867     aNewBmp.ReleaseAccess( pWriteAcc );
2868 
2869     if( bRet )
2870     {
2871         const MapMode   aMap( maPrefMapMode );
2872         const Size      aSize( maPrefSize );
2873 
2874         *this = aNewBmp;
2875 
2876         maPrefMapMode = aMap;
2877         maPrefSize = aSize;
2878     }
2879 
2880     return bRet;
2881 }
2882 
2883 // ------------------------------------------------------------------------
2884 
2885 sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
2886 {
2887     sal_Bool bRet;
2888 
2889     if( GetColorCount() <= (sal_uLong) nColorCount )
2890         bRet = sal_True;
2891     else if( nColorCount )
2892     {
2893         if( BMP_REDUCE_SIMPLE == eReduce )
2894             bRet = ImplReduceSimple( nColorCount );
2895         else if( BMP_REDUCE_POPULAR == eReduce )
2896             bRet = ImplReducePopular( nColorCount );
2897         else
2898             bRet = ImplReduceMedian( nColorCount );
2899     }
2900     else
2901         bRet = sal_False;
2902 
2903     return bRet;
2904 }
2905 
2906 // ------------------------------------------------------------------------
2907 
2908 sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
2909 {
2910     Bitmap              aNewBmp;
2911     BitmapReadAccess*   pRAcc = AcquireReadAccess();
2912     const sal_uInt16        nColCount = Min( nColorCount, (sal_uInt16) 256 );
2913     sal_uInt16              nBitCount;
2914     sal_Bool                bRet = sal_False;
2915 
2916     if( nColCount <= 2 )
2917         nBitCount = 1;
2918     else if( nColCount <= 16 )
2919         nBitCount = 4;
2920     else
2921         nBitCount = 8;
2922 
2923     if( pRAcc )
2924     {
2925         Octree                  aOct( *pRAcc, nColCount );
2926         const BitmapPalette&    rPal = aOct.GetPalette();
2927         BitmapWriteAccess*      pWAcc;
2928 
2929         aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
2930         pWAcc = aNewBmp.AcquireWriteAccess();
2931 
2932         if( pWAcc )
2933         {
2934             const long nWidth = pRAcc->Width();
2935             const long nHeight = pRAcc->Height();
2936 
2937             if( pRAcc->HasPalette() )
2938             {
2939                 for( long nY = 0L; nY < nHeight; nY++ )
2940                     for( long nX =0L; nX < nWidth; nX++ )
2941                         pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) );
2942             }
2943             else
2944             {
2945                 for( long nY = 0L; nY < nHeight; nY++ )
2946                     for( long nX =0L; nX < nWidth; nX++ )
2947                         pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) );
2948             }
2949 
2950             aNewBmp.ReleaseAccess( pWAcc );
2951             bRet = sal_True;
2952         }
2953 
2954         ReleaseAccess( pRAcc );
2955     }
2956 
2957     if( bRet )
2958     {
2959         const MapMode   aMap( maPrefMapMode );
2960         const Size      aSize( maPrefSize );
2961 
2962         *this = aNewBmp;
2963         maPrefMapMode = aMap;
2964         maPrefSize = aSize;
2965     }
2966 
2967     return bRet;
2968 }
2969 
2970 // ------------------------------------------------------------------------
2971 
2972 struct PopularColorCount
2973 {
2974     sal_uInt32  mnIndex;
2975     sal_uInt32  mnCount;
2976 };
2977 
2978 // ------------------------------------------------------------------------
2979 
2980 extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
2981 {
2982     int nRet;
2983 
2984     if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
2985         nRet = 1;
2986     else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
2987         nRet = 0;
2988     else
2989         nRet = -1;
2990 
2991     return nRet;
2992 }
2993 
2994 // ------------------------------------------------------------------------
2995 
2996 sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
2997 {
2998     BitmapReadAccess*   pRAcc = AcquireReadAccess();
2999     sal_uInt16              nBitCount;
3000     sal_Bool                bRet = sal_False;
3001 
3002     if( nColCount > 256 )
3003         nColCount = 256;
3004 
3005     if( nColCount < 17 )
3006         nBitCount = 4;
3007     else
3008         nBitCount = 8;
3009 
3010     if( pRAcc )
3011     {
3012         const sal_uInt32    nValidBits = 4;
3013         const sal_uInt32    nRightShiftBits = 8 - nValidBits;
3014         const sal_uInt32    nLeftShiftBits1 = nValidBits;
3015         const sal_uInt32    nLeftShiftBits2 = nValidBits << 1;
3016         const sal_uInt32    nColorsPerComponent = 1 << nValidBits;
3017         const sal_uInt32    nColorOffset = 256 / nColorsPerComponent;
3018         const sal_uInt32    nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
3019         const long          nWidth = pRAcc->Width();
3020         const long          nHeight = pRAcc->Height();
3021         PopularColorCount*  pCountTable = new PopularColorCount[ nTotalColors ];
3022         long                nX, nY, nR, nG, nB, nIndex;
3023 
3024         rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
3025 
3026         for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3027         {
3028             for( nG = 0; nG < 256; nG += nColorOffset )
3029             {
3030                 for( nB = 0; nB < 256; nB += nColorOffset )
3031                 {
3032                     pCountTable[ nIndex ].mnIndex = nIndex;
3033                     nIndex++;
3034                 }
3035             }
3036         }
3037 
3038         if( pRAcc->HasPalette() )
3039         {
3040             for( nY = 0L; nY < nHeight; nY++ )
3041             {
3042                 for( nX = 0L; nX < nWidth; nX++ )
3043                 {
3044                     const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3045                     pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3046                                  ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3047                                  ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3048                 }
3049             }
3050         }
3051         else
3052         {
3053             for( nY = 0L; nY < nHeight; nY++ )
3054             {
3055                 for( nX = 0L; nX < nWidth; nX++ )
3056                 {
3057                     const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3058                     pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3059                                  ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3060                                  ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3061                 }
3062             }
3063         }
3064 
3065         BitmapPalette aNewPal( nColCount );
3066 
3067         qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
3068 
3069         for( sal_uInt16 n = 0; n < nColCount; n++ )
3070         {
3071             const PopularColorCount& rPop = pCountTable[ n ];
3072             aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
3073                                         (sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
3074                                         (sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
3075         }
3076 
3077         Bitmap              aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
3078         BitmapWriteAccess*  pWAcc = aNewBmp.AcquireWriteAccess();
3079 
3080         if( pWAcc )
3081         {
3082             BitmapColor aDstCol( (sal_uInt8) 0 );
3083             sal_uInt8*      pIndexMap = new sal_uInt8[ nTotalColors ];
3084 
3085             for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3086                 for( nG = 0; nG < 256; nG += nColorOffset )
3087                     for( nB = 0; nB < 256; nB += nColorOffset )
3088                         pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
3089 
3090             if( pRAcc->HasPalette() )
3091             {
3092                 for( nY = 0L; nY < nHeight; nY++ )
3093                 {
3094                     for( nX = 0L; nX < nWidth; nX++ )
3095                     {
3096                         const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3097                         aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3098                                                      ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3099                                                      ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
3100                         pWAcc->SetPixel( nY, nX, aDstCol );
3101                     }
3102                 }
3103             }
3104             else
3105             {
3106                 for( nY = 0L; nY < nHeight; nY++ )
3107                 {
3108                     for( nX = 0L; nX < nWidth; nX++ )
3109                     {
3110                         const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3111                         aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3112                                                      ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3113                                                      ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
3114                         pWAcc->SetPixel( nY, nX, aDstCol );
3115                     }
3116                 }
3117             }
3118 
3119             delete[] pIndexMap;
3120             aNewBmp.ReleaseAccess( pWAcc );
3121             bRet = sal_True;
3122         }
3123 
3124         delete[] pCountTable;
3125         ReleaseAccess( pRAcc );
3126 
3127         if( bRet )
3128         {
3129             const MapMode   aMap( maPrefMapMode );
3130             const Size      aSize( maPrefSize );
3131 
3132             *this = aNewBmp;
3133             maPrefMapMode = aMap;
3134             maPrefSize = aSize;
3135         }
3136     }
3137 
3138     return bRet;
3139 }
3140 
3141 // ------------------------------------------------------------------------
3142 
3143 sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
3144 {
3145     BitmapReadAccess*   pRAcc = AcquireReadAccess();
3146     sal_uInt16              nBitCount;
3147     sal_Bool                bRet = sal_False;
3148 
3149     if( nColCount < 17 )
3150         nBitCount = 4;
3151     else if( nColCount < 257 )
3152         nBitCount = 8;
3153     else
3154     {
3155         DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
3156         nBitCount = 8;
3157         nColCount = 256;
3158     }
3159 
3160     if( pRAcc )
3161     {
3162         Bitmap              aNewBmp( GetSizePixel(), nBitCount );
3163         BitmapWriteAccess*  pWAcc = aNewBmp.AcquireWriteAccess();
3164 
3165         if( pWAcc )
3166         {
3167             const sal_uLong nSize = 32768UL * sizeof( sal_uLong );
3168             sal_uLong*      pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
3169             const long  nWidth = pWAcc->Width();
3170             const long  nHeight = pWAcc->Height();
3171             long        nIndex = 0L;
3172 
3173             memset( (HPBYTE) pColBuf, 0, nSize );
3174 
3175             // create Buffer
3176             if( pRAcc->HasPalette() )
3177             {
3178                 for( long nY = 0L; nY < nHeight; nY++ )
3179                 {
3180                     for( long nX = 0L; nX < nWidth; nX++ )
3181                     {
3182                         const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3183                         pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
3184                     }
3185                 }
3186             }
3187             else
3188             {
3189                 for( long nY = 0L; nY < nHeight; nY++ )
3190                 {
3191                     for( long nX = 0L; nX < nWidth; nX++ )
3192                     {
3193                         const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3194                         pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
3195                     }
3196                 }
3197             }
3198 
3199             // create palette via median cut
3200             BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
3201             ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
3202                            nColCount, nWidth * nHeight, nIndex );
3203 
3204             // do mapping of colors to palette
3205             InverseColorMap aMap( aPal );
3206             pWAcc->SetPalette( aPal );
3207             for( long nY = 0L; nY < nHeight; nY++ )
3208                 for( long nX = 0L; nX < nWidth; nX++ )
3209                     pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) );
3210 
3211             rtl_freeMemory( pColBuf );
3212             aNewBmp.ReleaseAccess( pWAcc );
3213             bRet = sal_True;
3214         }
3215 
3216         ReleaseAccess( pRAcc );
3217 
3218         if( bRet )
3219         {
3220             const MapMode   aMap( maPrefMapMode );
3221             const Size      aSize( maPrefSize );
3222 
3223             *this = aNewBmp;
3224             maPrefMapMode = aMap;
3225             maPrefSize = aSize;
3226         }
3227     }
3228 
3229     return bRet;
3230 }
3231 
3232 // ------------------------------------------------------------------------
3233 
3234 void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
3235                             long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
3236                             long nColors, long nPixels, long& rIndex )
3237 {
3238     if( !nPixels )
3239         return;
3240 
3241     BitmapColor aCol;
3242     const long  nRLen = nR2 - nR1;
3243     const long  nGLen = nG2 - nG1;
3244     const long  nBLen = nB2 - nB1;
3245     long        nR, nG, nB;
3246     sal_uLong*      pBuf = pColBuf;
3247 
3248     if( !nRLen && !nGLen && !nBLen )
3249     {
3250         if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
3251         {
3252             aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
3253             aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
3254             aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
3255             rPal[ (sal_uInt16) rIndex++ ] = aCol;
3256         }
3257     }
3258     else
3259     {
3260         if( 1 == nColors || 1 == nPixels )
3261         {
3262             long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
3263 
3264             for( nR = nR1; nR <= nR2; nR++ )
3265             {
3266                 for( nG = nG1; nG <= nG2; nG++ )
3267                 {
3268                     for( nB = nB1; nB <= nB2; nB++ )
3269                     {
3270                         nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
3271 
3272                         if( nPixSum )
3273                         {
3274                             nRSum += nR * nPixSum;
3275                             nGSum += nG * nPixSum;
3276                             nBSum += nB * nPixSum;
3277                         }
3278                     }
3279                 }
3280             }
3281 
3282             aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
3283             aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
3284             aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
3285             rPal[ (sal_uInt16) rIndex++ ] = aCol;
3286         }
3287         else
3288         {
3289             const long  nTest = ( nPixels >> 1 );
3290             long        nPixOld = 0;
3291             long        nPixNew = 0;
3292 
3293             if( nBLen > nGLen && nBLen > nRLen )
3294             {
3295                 nB = nB1 - 1;
3296 
3297                 while( nPixNew < nTest )
3298                 {
3299                     nB++, nPixOld = nPixNew;
3300                     for( nR = nR1; nR <= nR2; nR++ )
3301                         for( nG = nG1; nG <= nG2; nG++ )
3302                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3303                 }
3304 
3305                 if( nB < nB2 )
3306                 {
3307                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
3308                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3309                 }
3310                 else
3311                 {
3312                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
3313                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3314                 }
3315             }
3316             else if( nGLen > nRLen )
3317             {
3318                 nG = nG1 - 1;
3319 
3320                 while( nPixNew < nTest )
3321                 {
3322                     nG++, nPixOld = nPixNew;
3323                     for( nR = nR1; nR <= nR2; nR++ )
3324                         for( nB = nB1; nB <= nB2; nB++ )
3325                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3326                 }
3327 
3328                 if( nG < nG2 )
3329                 {
3330                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3331                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3332                 }
3333                 else
3334                 {
3335                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3336                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3337                 }
3338             }
3339             else
3340             {
3341                 nR = nR1 - 1;
3342 
3343                 while( nPixNew < nTest )
3344                 {
3345                     nR++, nPixOld = nPixNew;
3346                     for( nG = nG1; nG <= nG2; nG++ )
3347                         for( nB = nB1; nB <= nB2; nB++ )
3348                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3349                 }
3350 
3351                 if( nR < nR2 )
3352                 {
3353                     ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3354                     ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3355                 }
3356                 else
3357                 {
3358                     ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3359                     ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3360                 }
3361             }
3362         }
3363     }
3364 }
3365 
3366 // ------------------------------------------------------------------------
3367 
3368 sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
3369 {
3370     return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
3371 }
3372 
3373 // ------------------------------------------------------------------------
3374 
3375 sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
3376 {
3377     return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
3378 }
3379 
3380 // ------------------------------------------------------------------------
3381 
3382 sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
3383                      short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
3384                      double fGamma, sal_Bool bInvert )
3385 {
3386     sal_Bool bRet = sal_False;
3387 
3388     // nothing to do => return quickly
3389     if( !nLuminancePercent && !nContrastPercent &&
3390         !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
3391         ( fGamma == 1.0 ) && !bInvert )
3392     {
3393         bRet = sal_True;
3394     }
3395     else
3396     {
3397         BitmapWriteAccess* pAcc = AcquireWriteAccess();
3398 
3399         if( pAcc )
3400         {
3401             BitmapColor     aCol;
3402             const long      nW = pAcc->Width();
3403             const long      nH = pAcc->Height();
3404             sal_uInt8*          cMapR = new sal_uInt8[ 256 ];
3405             sal_uInt8*          cMapG = new sal_uInt8[ 256 ];
3406             sal_uInt8*          cMapB = new sal_uInt8[ 256 ];
3407             long            nX, nY;
3408             double          fM, fROff, fGOff, fBOff, fOff;
3409 
3410             // calculate slope
3411             if( nContrastPercent >= 0 )
3412                 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
3413             else
3414                 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
3415 
3416             // total offset = luminance offset + contrast offset
3417             fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
3418 
3419             // channel offset = channel offset  + total offset
3420             fROff = nChannelRPercent * 2.55 + fOff;
3421             fGOff = nChannelGPercent * 2.55 + fOff;
3422             fBOff = nChannelBPercent * 2.55 + fOff;
3423 
3424             // calculate gamma value
3425             fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
3426             const sal_Bool bGamma = ( fGamma != 1.0 );
3427 
3428             // create mapping table
3429             for( nX = 0L; nX < 256L; nX++ )
3430             {
3431                 cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
3432                 cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
3433                 cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
3434 
3435                 if( bGamma )
3436                 {
3437                     cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
3438                     cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
3439                     cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
3440                 }
3441 
3442                 if( bInvert )
3443                 {
3444                     cMapR[ nX ] = ~cMapR[ nX ];
3445                     cMapG[ nX ] = ~cMapG[ nX ];
3446                     cMapB[ nX ] = ~cMapB[ nX ];
3447                 }
3448             }
3449 
3450             // do modifying
3451             if( pAcc->HasPalette() )
3452             {
3453                 BitmapColor aNewCol;
3454 
3455                 for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
3456                 {
3457                     const BitmapColor& rCol = pAcc->GetPaletteColor( i );
3458                     aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
3459                     aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
3460                     aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
3461                     pAcc->SetPaletteColor( i, aNewCol );
3462                 }
3463             }
3464             else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
3465             {
3466                 for( nY = 0L; nY < nH; nY++ )
3467                 {
3468                     Scanline pScan = pAcc->GetScanline( nY );
3469 
3470                     for( nX = 0L; nX < nW; nX++ )
3471                     {
3472                         *pScan = cMapB[ *pScan ]; pScan++;
3473                         *pScan = cMapG[ *pScan ]; pScan++;
3474                         *pScan = cMapR[ *pScan ]; pScan++;
3475                     }
3476                 }
3477             }
3478             else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
3479             {
3480                 for( nY = 0L; nY < nH; nY++ )
3481                 {
3482                     Scanline pScan = pAcc->GetScanline( nY );
3483 
3484                     for( nX = 0L; nX < nW; nX++ )
3485                     {
3486                         *pScan = cMapR[ *pScan ]; pScan++;
3487                         *pScan = cMapG[ *pScan ]; pScan++;
3488                         *pScan = cMapB[ *pScan ]; pScan++;
3489                     }
3490                 }
3491             }
3492             else
3493             {
3494                 for( nY = 0L; nY < nH; nY++ )
3495                 {
3496                     for( nX = 0L; nX < nW; nX++ )
3497                     {
3498                         aCol = pAcc->GetPixel( nY, nX );
3499                         aCol.SetRed( cMapR[ aCol.GetRed() ] );
3500                         aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
3501                         aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
3502                         pAcc->SetPixel( nY, nX, aCol );
3503                     }
3504                 }
3505             }
3506 
3507             delete[] cMapR;
3508             delete[] cMapG;
3509             delete[] cMapB;
3510             ReleaseAccess( pAcc );
3511             bRet = sal_True;
3512         }
3513     }
3514 
3515     return bRet;
3516 }
3517