xref: /aoo42x/main/vcl/source/gdi/bitmap3.cxx (revision 37ab0f2d)
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