xref: /AOO41X/main/vcl/source/gdi/bitmap3.cxx (revision a09c9fefca8b782e151b15310c4d12b98b503233)
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_uInt32 nScaleFlag )
908 {
909     if(basegfx::fTools::equalZero(rScaleX) || basegfx::fTools::equalZero(rScaleY))
910     {
911         // no scale
912         return true;
913     }
914 
915     if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
916     {
917         // no scale
918         return true;
919     }
920 
921 #ifdef DBG_UTIL
922     // #121233# allow to test the different scalers in debug build with source
923     // level debugger (change nNumber to desired action)
924     static sal_uInt16 nNumber(0);
925     const sal_uInt16 nStartCount(GetBitCount());
926 
927     switch(nNumber)
928     {
929         case 0 : break;
930         case 1: nScaleFlag = BMP_SCALE_FAST; break;
931         case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break;
932         case 3: nScaleFlag = BMP_SCALE_SUPER; break;
933         case 4: nScaleFlag = BMP_SCALE_LANCZOS; break;
934         case 5: nScaleFlag = BMP_SCALE_BICUBIC; break;
935         case 6: nScaleFlag = BMP_SCALE_BILINEAR; break;
936         case 7: nScaleFlag = BMP_SCALE_BOX; break;
937         case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break;
938         case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break;
939     }
940 #endif // DBG_UTIL
941 
942     bool bRetval(false);
943 
944     if(BMP_SCALE_BESTQUALITY == nScaleFlag)
945     {
946         // Use LANCZOS when best quality is requested
947         nScaleFlag = BMP_SCALE_LANCZOS;
948     }
949     else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag)
950     {
951         // Use BMP_SCALE_SUPER when speed is requested, but not worst quality
952         nScaleFlag = BMP_SCALE_SUPER;
953     }
954 
955     switch(nScaleFlag)
956     {
957         default:
958         case BMP_SCALE_NONE :
959         {
960             bRetval = false;
961             break;
962         }
963         case BMP_SCALE_FAST :
964         {
965             bRetval = ImplScaleFast( rScaleX, rScaleY );
966             break;
967         }
968         case BMP_SCALE_INTERPOLATE :
969         {
970             bRetval = ImplScaleInterpolate( rScaleX, rScaleY );
971             break;
972         }
973         case BMP_SCALE_SUPER :
974         {
975             if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
976             {
977                 // fallback to ImplScaleFast
978                 bRetval = ImplScaleFast( rScaleX, rScaleY );
979             }
980             else
981             {
982                 // #121233# use method from symphony
983                 bRetval = ImplScaleSuper( rScaleX, rScaleY );
984             }
985             break;
986         }
987         case BMP_SCALE_LANCZOS :
988         {
989             const Lanczos3Kernel kernel;
990 
991             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel);
992             break;
993         }
994         case BMP_SCALE_BICUBIC :
995         {
996             const BicubicKernel kernel;
997 
998             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
999             break;
1000         }
1001         case BMP_SCALE_BILINEAR :
1002         {
1003             const BilinearKernel kernel;
1004 
1005             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
1006             break;
1007         }
1008         case BMP_SCALE_BOX :
1009         {
1010             const BoxKernel kernel;
1011 
1012             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
1013             break;
1014         }
1015     }
1016 
1017 #ifdef DBG_UTIL
1018     if(bRetval && nStartCount != GetBitCount())
1019     {
1020         OSL_ENSURE(false, "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
1021     }
1022 #endif
1023 
1024     return bRetval;
1025 }
1026 
1027 // ------------------------------------------------------------------------
1028 
1029 sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
1030 {
1031 	const Size	aSize( GetSizePixel() );
1032 	sal_Bool		bRet;
1033 
1034 	if( aSize.Width() && aSize.Height() )
1035 	{
1036 		bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
1037 					  (double) rNewSize.Height() / aSize.Height(),
1038 					  nScaleFlag );
1039 	}
1040 	else
1041 		bRet = sal_True;
1042 
1043 	return bRet;
1044 }
1045 
1046 // ------------------------------------------------------------------------
1047 
1048 void Bitmap::AdaptBitCount(Bitmap& rNew) const
1049 {
1050     ImplAdaptBitCount(rNew);
1051 }
1052 
1053 // ------------------------------------------------------------------------
1054 
1055 void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const
1056 {
1057     // aNew is the result of some operation; adapt it's BitCount to the original (this)
1058     if(GetBitCount() != rNew.GetBitCount())
1059     {
1060         switch(GetBitCount())
1061         {
1062             case 1:
1063             {
1064                 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
1065                 break;
1066             }
1067             case 4:
1068             {
1069                 if(HasGreyPalette())
1070                 {
1071                     rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
1072                 }
1073                 else
1074                 {
1075                     rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
1076                 }
1077                 break;
1078             }
1079             case 8:
1080             {
1081                 if(HasGreyPalette())
1082                 {
1083                     rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
1084                 }
1085                 else
1086                 {
1087                     rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
1088                 }
1089                 break;
1090             }
1091             case 24:
1092             {
1093                 rNew.Convert(BMP_CONVERSION_24BIT);
1094                 break;
1095             }
1096             default:
1097             {
1098                 OSL_ENSURE(false, "BitDepth adaption failed (!)");
1099                 break;
1100             }
1101         }
1102     }
1103 }
1104 
1105 // ------------------------------------------------------------------------
1106 
1107 sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
1108 {
1109 	const Size	aSizePix( GetSizePixel() );
1110 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
1111 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
1112 	sal_Bool		bRet = sal_False;
1113 
1114 	if( nNewWidth && nNewHeight )
1115 	{
1116 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1117         if ( !pReadAcc )
1118             return sal_False;
1119 
1120 		Bitmap				aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
1121 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1122 
1123 		if( pWriteAcc )
1124 		{
1125 			const long	nScanlineSize = pWriteAcc->GetScanlineSize();
1126 			const long	nNewWidth1 = nNewWidth - 1L;
1127 			const long	nNewHeight1 = nNewHeight - 1L;
1128 			const long	nWidth = pReadAcc->Width();
1129 			const long	nHeight = pReadAcc->Height();
1130 			long*		pLutX = new long[ nNewWidth ];
1131 			long*		pLutY = new long[ nNewHeight ];
1132 			long		nX, nY, nMapY, nActY = 0L;
1133 
1134 			if( nNewWidth1 && nNewHeight1 )
1135 			{
1136 				for( nX = 0L; nX < nNewWidth; nX++ )
1137 					pLutX[ nX ] = nX * nWidth / nNewWidth;
1138 
1139 				for( nY = 0L; nY < nNewHeight; nY++ )
1140 					pLutY[ nY ] = nY * nHeight / nNewHeight;
1141 
1142 				while( nActY < nNewHeight )
1143 				{
1144 					nMapY = pLutY[ nActY ];
1145 
1146 					for( nX = 0L; nX < nNewWidth; nX++ )
1147 						pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
1148 
1149 					while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
1150 					{
1151 						memcpy( pWriteAcc->GetScanline( nActY + 1L ),
1152 								 pWriteAcc->GetScanline( nActY ), nScanlineSize );
1153 						nActY++;
1154 					}
1155 
1156 					nActY++;
1157 				}
1158 
1159 				bRet = sal_True;
1160 			}
1161 
1162 			delete[] pLutX;
1163 			delete[] pLutY;
1164 		}
1165 
1166 		ReleaseAccess( pReadAcc );
1167 		aNewBmp.ReleaseAccess( pWriteAcc );
1168 
1169 		if( bRet )
1170 			ImplAssignWithSize( aNewBmp );
1171 	}
1172 
1173 	return bRet;
1174 }
1175 
1176 // ------------------------------------------------------------------------
1177 
1178 sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1179 {
1180 	const Size	aSizePix( GetSizePixel() );
1181 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
1182 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
1183 	sal_Bool		bRet = sal_False;
1184 
1185 	if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1186 	{
1187 		BitmapColor 		aCol0;
1188 		BitmapColor 		aCol1;
1189 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1190 		long				nWidth = pReadAcc->Width();
1191 		long				nHeight = pReadAcc->Height();
1192 		Bitmap				aNewBmp( Size( nNewWidth, nHeight ), 24 );
1193 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1194 		long*				pLutInt;
1195 		long*				pLutFrac;
1196 		long				nX, nY;
1197 		long				lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1198 		double				fTemp;
1199 		long				nTemp;
1200 
1201 		if( pReadAcc && pWriteAcc )
1202 		{
1203 			const long		nNewWidth1 = nNewWidth - 1L;
1204 			const long		nWidth1 = pReadAcc->Width() - 1L;
1205 			const double	fRevScaleX = (double) nWidth1 / nNewWidth1;
1206 
1207 			pLutInt = new long[ nNewWidth ];
1208 			pLutFrac = new long[ nNewWidth ];
1209 
1210 			for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1211 			{
1212 				fTemp = nX * fRevScaleX;
1213 				pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1214 				fTemp -= pLutInt[ nX ];
1215 				pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1216 			}
1217 
1218 			for( nY = 0L; nY < nHeight; nY++ )
1219 			{
1220 				if( 1 == nWidth )
1221 				{
1222 			        if( pReadAcc->HasPalette() )
1223 			        {
1224     					aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) );
1225                     }
1226                     else
1227                     {
1228     					aCol0 = pReadAcc->GetPixel( nY, 0 );
1229                     }
1230 
1231 					for( nX = 0L; nX < nNewWidth; nX++ )
1232                     {
1233 						pWriteAcc->SetPixel( nY, nX, aCol0 );
1234                     }
1235 				}
1236 				else
1237 				{
1238 					for( nX = 0L; nX < nNewWidth; nX++ )
1239 					{
1240 						nTemp = pLutInt[ nX ];
1241 
1242 			            if( pReadAcc->HasPalette() )
1243 			            {
1244 							aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) );
1245 							aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) );
1246                         }
1247                         else
1248                         {
1249 							aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1250 							aCol1 = pReadAcc->GetPixel( nY, nTemp );
1251                         }
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 			delete[] pLutInt;
1269 			delete[] pLutFrac;
1270 			bRet = sal_True;
1271 		}
1272 
1273 		ReleaseAccess( pReadAcc );
1274 		aNewBmp.ReleaseAccess( pWriteAcc );
1275 
1276 		if( bRet )
1277 		{
1278 			bRet = sal_False;
1279             const Bitmap aOriginal(*this);
1280             *this = aNewBmp;
1281 			aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1282 			pReadAcc = AcquireReadAccess();
1283 			pWriteAcc = aNewBmp.AcquireWriteAccess();
1284 
1285 			if( pReadAcc && pWriteAcc )
1286 			{
1287 				const long		nNewHeight1 = nNewHeight - 1L;
1288 				const long		nHeight1 = pReadAcc->Height() - 1L;
1289 				const double	fRevScaleY = (double) nHeight1 / nNewHeight1;
1290 
1291 				pLutInt = new long[ nNewHeight ];
1292 				pLutFrac = new long[ nNewHeight ];
1293 
1294 				for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1295 				{
1296 					fTemp = nY * fRevScaleY;
1297 					pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1298 					fTemp -= pLutInt[ nY ];
1299 					pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1300 				}
1301 
1302                 // after 1st step, bitmap *is* 24bit format (see above)
1303 				OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)");
1304 
1305 				for( nX = 0L; nX < nNewWidth; nX++ )
1306 				{
1307 					if( 1 == nHeight )
1308 					{
1309 						aCol0 = pReadAcc->GetPixel( 0, nX );
1310 
1311 						for( nY = 0L; nY < nNewHeight; nY++ )
1312                         {
1313 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1314                         }
1315 					}
1316 					else
1317 					{
1318 						for( nY = 0L; nY < nNewHeight; nY++ )
1319 						{
1320 							nTemp = pLutInt[ nY ];
1321 
1322 							aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1323 							aCol1 = pReadAcc->GetPixel( nTemp, nX );
1324 
1325 							nTemp = pLutFrac[ nY ];
1326 
1327 							lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1328 							lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1329 							lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1330 
1331 							aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1332 							aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1333 							aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1334 
1335 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1336 						}
1337 					}
1338 				}
1339 
1340 				delete[] pLutInt;
1341 				delete[] pLutFrac;
1342 				bRet = sal_True;
1343 			}
1344 
1345 			ReleaseAccess( pReadAcc );
1346 			aNewBmp.ReleaseAccess( pWriteAcc );
1347 
1348 			if( bRet )
1349             {
1350                 aOriginal.ImplAdaptBitCount(aNewBmp);
1351 				*this = aNewBmp;
1352             }
1353 		}
1354 	}
1355 
1356 	if( !bRet )
1357     {
1358 		bRet = ImplScaleFast( rScaleX, rScaleY );
1359     }
1360 
1361 	return bRet;
1362 }
1363 
1364 // ------------------------------------------------------------------------
1365 // #121233# Added BMP_SCALE_SUPER from symphony code
1366 
1367 sal_Bool Bitmap::ImplScaleSuper(
1368     const double& rScaleX,
1369     const double& rScaleY )
1370 {
1371 	const Size	aSizePix( GetSizePixel() );
1372 	bool   bHMirr = ( rScaleX < 0 );
1373     bool   bVMirr = ( rScaleY < 0 );
1374     double scaleX = bHMirr ? -rScaleX : rScaleX;
1375     double scaleY = bVMirr ? -rScaleY : rScaleY;
1376 	const long	nDstW = FRound( aSizePix.Width() * scaleX );
1377 	const long	nDstH = FRound( aSizePix.Height() * scaleY );
1378 	const double fScaleThresh = 0.6;
1379 	bool bRet = false;
1380 
1381 	if( ( nDstW > 1L ) && ( nDstH > 1L ) )
1382 	{
1383 		BitmapColor			aCol0, aCol1, aColRes;
1384 		BitmapReadAccess*	pAcc = AcquireReadAccess();
1385 		long				nW = pAcc->Width() ;
1386 		long				nH = pAcc->Height() ;
1387 		Bitmap				aOutBmp( Size( nDstW, nDstH ), 24 );
1388 		BitmapWriteAccess*	pWAcc = aOutBmp.AcquireWriteAccess();
1389 		long*			    pMapIX = new long[ nDstW ];
1390 		long*			    pMapIY = new long[ nDstH ];
1391 		long*			    pMapFX = new long[ nDstW ];
1392 		long*			    pMapFY = new long[ nDstH ];
1393 		long				nX, nY, nXDst, nYDst;;
1394 		double				fTemp;
1395 		long				nTemp , nTempX, nTempY, nTempFX, nTempFY;
1396 		sal_uInt8           cR0, cG0, cB0, cR1, cG1, cB1;
1397 		long                nStartX = 0 , nStartY = 0;
1398 		long                nEndX = nDstW - 1L;
1399 		long                nEndY = nDstH - 1L;
1400 		long		        nMax = 1 << 7L;
1401 
1402 		if( pAcc && pWAcc )
1403 		{
1404             const double	fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0;
1405             const double	fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0;
1406 
1407             // create horizontal mapping table
1408             for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ )
1409             {
1410                 fTemp = nX * fRevScaleX;
1411 
1412                 if( bHMirr )
1413                     fTemp = nTempX - fTemp;
1414 
1415                 pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
1416             }
1417 
1418             // create vertical mapping table
1419             for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ )
1420             {
1421                 fTemp = nY * fRevScaleY;
1422 
1423                 if( bVMirr )
1424                     fTemp = nTempY - fTemp;
1425 
1426                 pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
1427             }
1428 
1429 			if( pAcc->HasPalette() )
1430 			{
1431 				if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1432 				{
1433 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1434 					{
1435 						Scanline pLine0, pLine1;
1436 
1437 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1438 						{
1439 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1440 							pLine0 = pAcc->GetScanline( nTempY );
1441 							pLine1 = pAcc->GetScanline( ++nTempY );
1442 
1443 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1444 							{
1445 								nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1446 
1447 								const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] );
1448 								const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
1449 								const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] );
1450 								const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
1451 
1452 								cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
1453 								cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
1454 								cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
1455 
1456 								cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
1457 								cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
1458 								cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
1459 
1460 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1461 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1462 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1463 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1464 							}
1465 						}
1466 					}
1467 					else
1468 					{
1469 						Scanline	pTmpY;
1470 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1471 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1472 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1473 
1474 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1475 						{
1476 							nTop = bVMirr ? ( nY + 1 ) : nY;
1477 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
1478 
1479 							if( nY ==nEndY )
1480                             {
1481 								nLineStart = pMapIY[ nY ];
1482 								nLineRange = 0;
1483 							}
1484 							else
1485 							{
1486 								nLineStart = pMapIY[ nTop ] ;
1487 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1488 							}
1489 
1490 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1491 							{
1492 								nLeft = bHMirr ? ( nX + 1 ) : nX;
1493 								nRight = bHMirr ? nX : ( nX + 1 ) ;
1494 
1495 								if( nX == nEndX )
1496                                 {
1497 									nRowStart = pMapIX[ nX ];
1498 									nRowRange = 0;
1499 								}
1500 								else
1501 								{
1502 									nRowStart = pMapIX[ nLeft ];
1503 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1504 								}
1505 
1506 								nSumR = nSumG = nSumB = 0;
1507 								nTotalWeightY = 0;
1508 
1509 								for(int i = 0; i<= nLineRange; i++)
1510 								{
1511 									pTmpY = pAcc->GetScanline( nLineStart + i );
1512 									nSumRowR = nSumRowG = nSumRowB = 0;
1513 									nTotalWeightX = 0;
1514 
1515 									for(int j = 0; j <= nRowRange; j++)
1516 									{
1517 										const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] );
1518 
1519 										if(nX == nEndX )
1520                                         {
1521 											nSumRowB += rCol.GetBlue() << 7L;
1522 											nSumRowG += rCol.GetGreen() << 7L;
1523 											nSumRowR += rCol.GetRed() << 7L;
1524 											nTotalWeightX += 1 << 7L;
1525 										}
1526 										else if( j == 0 )
1527                                         {
1528 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
1529 											nSumRowB += ( nWeightX *rCol.GetBlue()) ;
1530 											nSumRowG += ( nWeightX *rCol.GetGreen()) ;
1531 											nSumRowR += ( nWeightX *rCol.GetRed()) ;
1532 											nTotalWeightX += nWeightX;
1533 										}
1534 										else if ( nRowRange == j )
1535                                         {
1536 											nWeightX = pMapFX[ nRight ] ;
1537 											nSumRowB += ( nWeightX *rCol.GetBlue() );
1538 											nSumRowG += ( nWeightX *rCol.GetGreen() );
1539 											nSumRowR += ( nWeightX *rCol.GetRed() );
1540 											nTotalWeightX += nWeightX;
1541 										}
1542 										else
1543                                         {
1544 											nSumRowB += rCol.GetBlue() << 7L;
1545 											nSumRowG += rCol.GetGreen() << 7L;
1546 											nSumRowR += rCol.GetRed() << 7L;
1547 											nTotalWeightX += 1 << 7L;
1548 										}
1549 									}
1550 
1551 									if( nY == nEndY )
1552 										nWeightY = nMax;
1553 									else if( i == 0 )
1554 										nWeightY = nMax - pMapFY[ nTop ];
1555 									else if( nLineRange == 1 )
1556 										nWeightY = pMapFY[ nTop ];
1557 									else if ( nLineRange == i )
1558 										nWeightY = pMapFY[ nBottom ];
1559 									else
1560 										nWeightY = nMax;
1561 
1562 									nWeightY = nWeightY ;
1563 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1564 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1565 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1566 									nTotalWeightY += nWeightY;
1567 								}
1568 
1569 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1570 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1571 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1572 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1573 
1574 							}
1575     					}
1576 					}
1577 }
1578 				else
1579 				{
1580 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1581 					{
1582 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1583 						{
1584 							nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ];
1585 
1586 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1587 							{
1588 								nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1589 
1590 								aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) );
1591 								aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) );
1592 								cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1593 								cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1594 								cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1595 
1596 								aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) );
1597 								aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) );
1598 								cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1599 								cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1600 								cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1601 
1602 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1603 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1604 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1605 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1606 							}
1607 						}
1608 
1609 					}
1610 					else
1611 					{
1612 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1613 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1614 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1615 
1616 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1617 						{
1618 							nTop = bVMirr ? ( nY + 1 ) : nY;
1619 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
1620 
1621 							if( nY ==nEndY )
1622                             {
1623 								nLineStart = pMapIY[ nY ];
1624 								nLineRange = 0;
1625 							}
1626 							else
1627 							{
1628 								nLineStart = pMapIY[ nTop ] ;
1629 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1630 							}
1631 
1632 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1633 							{
1634 								nLeft = bHMirr ? ( nX + 1 ) : nX;
1635 								nRight = bHMirr ? nX : ( nX + 1 ) ;
1636 
1637 								if( nX == nEndX )
1638                                 {
1639 									nRowStart = pMapIX[ nX ];
1640 									nRowRange = 0;
1641 								}
1642 								else
1643 								{
1644 									nRowStart = pMapIX[ nLeft ];
1645 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1646 								}
1647 
1648 								nSumR = nSumG = nSumB = 0;
1649 								nTotalWeightY = 0;
1650 
1651 								for(int i = 0; i<= nLineRange; i++)
1652 								{
1653 									nSumRowR = nSumRowG = nSumRowB = 0;
1654 									nTotalWeightX = 0;
1655 
1656 									for(int j = 0; j <= nRowRange; j++)
1657 									{
1658 										aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
1659 
1660                                         if(nX == nEndX )
1661                                         {
1662 
1663 											nSumRowB += aCol0.GetBlue() << 7L;
1664 											nSumRowG += aCol0.GetGreen() << 7L;
1665 											nSumRowR += aCol0.GetRed() << 7L;
1666 											nTotalWeightX += 1 << 7L;
1667 										}
1668 										else if( j == 0 )
1669                                         {
1670 
1671 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
1672 											nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
1673 											nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
1674 											nSumRowR += ( nWeightX *aCol0.GetRed()) ;
1675 											nTotalWeightX += nWeightX;
1676 										}
1677 										else if ( nRowRange == j )
1678                                         {
1679 
1680 											nWeightX = pMapFX[ nRight ] ;
1681 											nSumRowB += ( nWeightX *aCol0.GetBlue() );
1682 											nSumRowG += ( nWeightX *aCol0.GetGreen() );
1683 											nSumRowR += ( nWeightX *aCol0.GetRed() );
1684 											nTotalWeightX += nWeightX;
1685 										}
1686 										else
1687                                         {
1688 
1689 											nSumRowB += aCol0.GetBlue() << 7L;
1690 											nSumRowG += aCol0.GetGreen() << 7L;
1691 											nSumRowR += aCol0.GetRed() << 7L;
1692 											nTotalWeightX += 1 << 7L;
1693 										}
1694 									}
1695 
1696 									if( nY == nEndY )
1697 										nWeightY = nMax;
1698 									else if( i == 0 )
1699 										nWeightY = nMax - pMapFY[ nTop ];
1700 									else if( nLineRange == 1 )
1701 										nWeightY = pMapFY[ nTop ];
1702 									else if ( nLineRange == i )
1703 										nWeightY = pMapFY[ nBottom ];
1704 									else
1705 										nWeightY = nMax;
1706 
1707 									nWeightY = nWeightY ;
1708 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1709 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1710 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1711 									nTotalWeightY += nWeightY;
1712 								}
1713 
1714 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1715 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1716 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1717 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1718 							}
1719                         }
1720 					}
1721 				}
1722 			}
1723 			else
1724 			{
1725 				if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
1726 				{
1727 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1728 					{
1729 						Scanline	pLine0, pLine1, pTmp0, pTmp1;
1730 						long		nOff;
1731 
1732 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1733 						{
1734 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1735 							pLine0 = pAcc->GetScanline( nTempY );
1736 							pLine1 = pAcc->GetScanline( ++nTempY );
1737 
1738                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1739 							{
1740 								nOff = 3L * ( nTempX = pMapIX[ nX ] );
1741 								nTempFX = pMapFX[ nX ];
1742 
1743 								pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1744 								cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1745 								cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1746 								cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
1747 
1748 								pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1749 								cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1750 								cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1751 								cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
1752 
1753 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1754 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1755 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1756 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1757 							}
1758 						}
1759 					}
1760 					else
1761 					{
1762 						Scanline	pTmpY, pTmpX;
1763 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1764 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1765 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1766 
1767 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1768 						{
1769 							nTop = bVMirr ? ( nY + 1 ) : nY;
1770 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
1771 
1772 							if( nY ==nEndY )
1773                             {
1774 								nLineStart = pMapIY[ nY ];
1775 								nLineRange = 0;
1776 							}
1777 							else
1778 							{
1779 								nLineStart = pMapIY[ nTop ] ;
1780 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1781 							}
1782 
1783 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1784 							{
1785 								nLeft = bHMirr ? ( nX + 1 ) : nX;
1786 								nRight = bHMirr ? nX : ( nX + 1 ) ;
1787 
1788 								if( nX == nEndX  )
1789                                 {
1790 									nRowStart = pMapIX[ nX ];
1791 									nRowRange = 0;
1792 								}
1793 								else
1794 								{
1795 									nRowStart = pMapIX[ nLeft ];
1796 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1797 								}
1798 
1799 								nSumR = nSumG = nSumB = 0;
1800 								nTotalWeightY = 0;
1801 
1802 								for(int i = 0; i<= nLineRange; i++)
1803 								{
1804 									pTmpY = pAcc->GetScanline( nLineStart + i );
1805 									pTmpX = pTmpY + 3L * nRowStart;
1806 									nSumRowR = nSumRowG = nSumRowB = 0;
1807 									nTotalWeightX = 0;
1808 
1809 									for(int j = 0; j <= nRowRange; j++)
1810 									{
1811 										if(nX == nEndX )
1812                                         {
1813 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1814 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1815 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1816 											nTotalWeightX += 1 << 7L;
1817 										}
1818 										else if( j == 0 )
1819                                         {
1820 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
1821 											nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
1822 											nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
1823 											nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
1824 											nTotalWeightX += nWeightX;
1825 										}
1826 										else if ( nRowRange == j )
1827                                         {
1828 											nWeightX = pMapFX[ nRight ] ;
1829 											nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
1830 											nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
1831 											nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
1832 											nTotalWeightX += nWeightX;
1833 										}
1834 										else
1835 										{
1836 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1837 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1838 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1839 											nTotalWeightX += 1 << 7L;
1840 										}
1841 									}
1842 
1843 									if( nY == nEndY )
1844 										nWeightY = nMax;
1845 									else if( i == 0 )
1846 										nWeightY = nMax - pMapFY[ nTop ];
1847 									else if( nLineRange == 1 )
1848 										nWeightY = pMapFY[ nTop ];
1849 									else if ( nLineRange == i )
1850 										nWeightY = pMapFY[ nBottom ];
1851 									else
1852 										nWeightY = nMax;
1853 
1854 									nWeightY = nWeightY ;
1855 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1856 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1857 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1858 									nTotalWeightY += nWeightY;
1859 								}
1860 
1861 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1862 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1863 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1864 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1865 
1866 							}
1867                         }
1868 					}
1869 				}
1870 				else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
1871 				{
1872 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1873 					{
1874 						Scanline	pLine0, pLine1, pTmp0, pTmp1;
1875 						long		nOff;
1876 
1877 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1878 						{
1879 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1880 							pLine0 = pAcc->GetScanline( nTempY );
1881 							pLine1 = pAcc->GetScanline( ++nTempY );
1882 
1883 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1884 							{
1885 								nOff = 3L * ( nTempX = pMapIX[ nX ] );
1886 								nTempFX = pMapFX[ nX ];
1887 
1888 								pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1889 								cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1890 								cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1891 								cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
1892 
1893 								pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1894 								cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1895 								cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1896 								cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
1897 
1898 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1899 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1900 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1901 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1902 							}
1903 						}
1904 					}
1905 					else
1906 					{
1907 						Scanline	pTmpY, pTmpX;
1908 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1909 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1910 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1911 
1912 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1913 						{
1914 							nTop = bVMirr ? ( nY + 1 ) : nY;
1915 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
1916 
1917 							if( nY ==nEndY )
1918                             {
1919 								nLineStart = pMapIY[ nY ];
1920 								nLineRange = 0;
1921 							}
1922 							else
1923 							{
1924 								nLineStart = pMapIY[ nTop ] ;
1925 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1926 							}
1927 
1928 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1929 							{
1930 								nLeft = bHMirr ? ( nX + 1 ) : nX;
1931 								nRight = bHMirr ? nX : ( nX + 1 ) ;
1932 
1933 								if( nX == nEndX )
1934                                 {
1935 									nRowStart = pMapIX[ nX ];
1936 									nRowRange = 0;
1937 								}
1938 								else
1939 								{
1940 									nRowStart = pMapIX[ nLeft ];
1941 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1942 								}
1943 
1944 								nSumR = nSumG = nSumB = 0;
1945 								nTotalWeightY = 0;
1946 
1947 								for(int i = 0; i<= nLineRange; i++)
1948 								{
1949 									pTmpY = pAcc->GetScanline( nLineStart + i );
1950 									pTmpX = pTmpY + 3L * nRowStart;
1951 									nSumRowR = nSumRowG = nSumRowB = 0;
1952 									nTotalWeightX = 0;
1953 
1954 									for(int j = 0; j <= nRowRange; j++)
1955 									{
1956 										if(nX == nEndX )
1957                                         {
1958 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1959 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1960 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1961 											nTotalWeightX += 1 << 7L;
1962 										}
1963 										else if( j == 0 )
1964                                         {
1965 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
1966 											nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
1967 											nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
1968 											nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
1969 											nTotalWeightX += nWeightX;
1970 										}
1971 										else if ( nRowRange == j )
1972                                         {
1973 											nWeightX = pMapFX[ nRight ] ;
1974 											nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
1975 											nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
1976 											nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
1977 											nTotalWeightX += nWeightX;
1978 										}
1979 										else
1980                                         {
1981 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1982 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1983 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1984 											nTotalWeightX += 1 << 7L;
1985 										}
1986 									}
1987 
1988 									if( nY == nEndY )
1989 										nWeightY = nMax;
1990 									else if( i == 0 )
1991 										nWeightY = nMax - pMapFY[ nTop ];
1992 									else if( nLineRange == 1 )
1993 										nWeightY = pMapFY[ nTop ];
1994 									else if ( nLineRange == i )
1995 										nWeightY = pMapFY[ nBottom ];
1996 									else
1997 										nWeightY = nMax;
1998 
1999 									nWeightY = nWeightY ;
2000 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
2001 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
2002 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
2003 									nTotalWeightY += nWeightY;
2004 								}
2005 
2006 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
2007 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
2008 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
2009 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2010 
2011 							}
2012                         }
2013 					}
2014 				}
2015 				else
2016 				{
2017 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
2018 					{
2019 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
2020 						{
2021 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
2022 
2023 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
2024 							{
2025 								nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
2026 
2027 								aCol0 = pAcc->GetPixel( nTempY, nTempX );
2028 								aCol1 = pAcc->GetPixel( nTempY, ++nTempX );
2029 								cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
2030 								cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
2031 								cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
2032 
2033 								aCol1 = pAcc->GetPixel( ++nTempY, nTempX );
2034 								aCol0 = pAcc->GetPixel( nTempY--, --nTempX );
2035 								cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
2036 								cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
2037 								cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
2038 
2039 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
2040 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
2041 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
2042 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2043 							}
2044 						}
2045 					}
2046 					else
2047 					{
2048 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
2049 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
2050 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
2051 
2052 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
2053 						{
2054 							nTop = bVMirr ? ( nY + 1 ) : nY;
2055 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
2056 
2057 							if( nY ==nEndY )
2058                             {
2059 								nLineStart = pMapIY[ nY ];
2060 								nLineRange = 0;
2061 							}
2062 							else
2063 							{
2064 								nLineStart = pMapIY[ nTop ] ;
2065 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
2066 							}
2067 
2068 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
2069 							{
2070 								nLeft = bHMirr ? ( nX + 1 ) : nX;
2071 								nRight = bHMirr ? nX : ( nX + 1 ) ;
2072 
2073 								if( nX == nEndX )
2074                                 {
2075 									nRowStart = pMapIX[ nX ];
2076 									nRowRange = 0;
2077 								}
2078 								else
2079 								{
2080 									nRowStart = pMapIX[ nLeft ];
2081 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
2082 								}
2083 
2084 								nSumR = nSumG = nSumB = 0;
2085 								nTotalWeightY = 0;
2086 
2087 								for(int i = 0; i<= nLineRange; i++)
2088 								{
2089 									nSumRowR = nSumRowG = nSumRowB = 0;
2090 									nTotalWeightX = 0;
2091 
2092 									for(int j = 0; j <= nRowRange; j++)
2093 									{
2094 										aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j );
2095 
2096                                         if(nX == nEndX )
2097                                         {
2098 
2099 											nSumRowB += aCol0.GetBlue() << 7L;
2100 											nSumRowG += aCol0.GetGreen() << 7L;
2101 											nSumRowR += aCol0.GetRed() << 7L;
2102 											nTotalWeightX += 1 << 7L;
2103 										}
2104 										else if( j == 0 )
2105                                         {
2106 
2107 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
2108 											nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
2109 											nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
2110 											nSumRowR += ( nWeightX *aCol0.GetRed()) ;
2111 											nTotalWeightX += nWeightX;
2112 										}
2113 										else if ( nRowRange == j )
2114                                         {
2115 
2116 											nWeightX = pMapFX[ nRight ] ;
2117 											nSumRowB += ( nWeightX *aCol0.GetBlue() );
2118 											nSumRowG += ( nWeightX *aCol0.GetGreen() );
2119 											nSumRowR += ( nWeightX *aCol0.GetRed() );
2120 											nTotalWeightX += nWeightX;
2121 										}
2122 										else
2123                                         {
2124 											nSumRowB += aCol0.GetBlue() << 7L;
2125 											nSumRowG += aCol0.GetGreen() << 7L;
2126 											nSumRowR += aCol0.GetRed() << 7L;
2127 											nTotalWeightX += 1 << 7L;
2128 										}
2129 									}
2130 
2131 									if( nY == nEndY )
2132 										nWeightY = nMax;
2133 									else if( i == 0 )
2134 										nWeightY = nMax - pMapFY[ nTop ];
2135 									else if( nLineRange == 1 )
2136 										nWeightY = pMapFY[ nTop ];
2137 									else if ( nLineRange == i )
2138 										nWeightY = pMapFY[ nBottom ];
2139 									else
2140 										nWeightY = nMax;
2141 
2142 									nWeightY = nWeightY ;
2143 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
2144 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
2145 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
2146 									nTotalWeightY += nWeightY;
2147 								}
2148 
2149 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
2150 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
2151 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
2152 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2153 
2154 							}
2155                         }
2156 					}
2157 				}
2158             }
2159 
2160             bRet = true;
2161 		}
2162 
2163 		delete[] pMapIX;
2164 		delete[] pMapIY;
2165 		delete[] pMapFX;
2166 		delete[] pMapFY;
2167 
2168 		ReleaseAccess( pAcc );
2169 		aOutBmp.ReleaseAccess( pWAcc );
2170 
2171 		if( bRet )
2172         {
2173             ImplAdaptBitCount(aOutBmp);
2174 			ImplAssignWithSize(aOutBmp);
2175         }
2176 
2177 		if( !bRet )
2178 			bRet = ImplScaleFast( scaleX, scaleY );
2179 	}
2180 
2181 	return bRet;
2182 }
2183 
2184 //-----------------------------------------------------------------------------------
2185 
2186 namespace
2187 {
2188     void ImplCalculateContributions(
2189         const sal_uInt32 aSourceSize,
2190         const sal_uInt32 aDestinationSize,
2191         sal_uInt32& aNumberOfContributions,
2192         double*& pWeights,
2193         sal_uInt32*& pPixels,
2194         sal_uInt32*& pCount,
2195         const Kernel& aKernel)
2196     {
2197         const double fSamplingRadius(aKernel.GetWidth());
2198         const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
2199         const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
2200         const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
2201 
2202         aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
2203         const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
2204         pWeights = new double[nAllocSize];
2205         pPixels = new sal_uInt32[nAllocSize];
2206         pCount = new sal_uInt32[aDestinationSize];
2207 
2208         for(sal_uInt32 i(0); i < aDestinationSize; i++)
2209         {
2210             const sal_uInt32 aIndex(i * aNumberOfContributions);
2211             const double aCenter(i / fScale);
2212             const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
2213             const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
2214             sal_uInt32 aCurrentCount(0);
2215 
2216             for(sal_Int32 j(aLeft); j <= aRight; j++)
2217             {
2218                 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
2219 
2220                 // Reduce calculations with ignoring weights of 0.0
2221                 if(fabs(aWeight) < 0.0001)
2222                 {
2223                     continue;
2224                 }
2225 
2226                 // Handling on edges
2227                 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
2228                 const sal_uInt32 nIndex(aIndex + aCurrentCount);
2229 
2230                 pWeights[nIndex] = aWeight;
2231                 pPixels[nIndex] = aPixelIndex;
2232 
2233                 aCurrentCount++;
2234             }
2235 
2236             pCount[i] = aCurrentCount;
2237         }
2238     }
2239 
2240     sal_Bool ImplScaleConvolutionHor(
2241         Bitmap& rSource,
2242         Bitmap& rTarget,
2243         const double& rScaleX,
2244         const Kernel& aKernel)
2245     {
2246         // Do horizontal filtering
2247         OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
2248         const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
2249         const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
2250 
2251         if(nWidth == nNewWidth)
2252         {
2253             return true;
2254         }
2255 
2256         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
2257 
2258         if(pReadAcc)
2259         {
2260             double* pWeights = 0;
2261             sal_uInt32* pPixels = 0;
2262             sal_uInt32* pCount = 0;
2263             sal_uInt32 aNumberOfContributions(0);
2264 
2265             const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
2266             ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
2267             rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
2268             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
2269             bool bResult(0 != pWriteAcc);
2270 
2271             if(bResult)
2272             {
2273                 for(sal_uInt32 y(0); y < nHeight; y++)
2274                 {
2275                     for(sal_uInt32 x(0); x < nNewWidth; x++)
2276                     {
2277                         const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
2278                         double aSum(0.0);
2279                         double aValueRed(0.0);
2280                         double aValueGreen(0.0);
2281                         double aValueBlue(0.0);
2282 
2283                         for(sal_uInt32 j(0); j < pCount[x]; j++)
2284                         {
2285                             const sal_uInt32 aIndex(aBaseIndex + j);
2286                             const double aWeight(pWeights[aIndex]);
2287                             BitmapColor aColor;
2288 
2289                             aSum += aWeight;
2290 
2291                             if(pReadAcc->HasPalette())
2292                             {
2293                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
2294                             }
2295                             else
2296                             {
2297                                 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
2298                             }
2299 
2300                             aValueRed += aWeight * aColor.GetRed();
2301                             aValueGreen += aWeight * aColor.GetGreen();
2302                             aValueBlue += aWeight * aColor.GetBlue();
2303                         }
2304 
2305                         const BitmapColor aResultColor(
2306                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
2307                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
2308                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
2309 
2310                         pWriteAcc->SetPixel(y, x, aResultColor);
2311                     }
2312                 }
2313 
2314                 rTarget.ReleaseAccess(pWriteAcc);
2315             }
2316 
2317             rSource.ReleaseAccess(pReadAcc);
2318             delete[] pWeights;
2319             delete[] pCount;
2320             delete[] pPixels;
2321 
2322             if(bResult)
2323             {
2324                 return true;
2325             }
2326         }
2327 
2328         return false;
2329     }
2330 
2331     bool ImplScaleConvolutionVer(
2332         Bitmap& rSource,
2333         Bitmap& rTarget,
2334         const double& rScaleY,
2335         const Kernel& aKernel)
2336     {
2337         // Do vertical filtering
2338         OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
2339         const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
2340         const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
2341 
2342         if(nHeight == nNewHeight)
2343         {
2344             return true;
2345         }
2346 
2347         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
2348 
2349         if(pReadAcc)
2350         {
2351             double* pWeights = 0;
2352             sal_uInt32* pPixels = 0;
2353             sal_uInt32* pCount = 0;
2354             sal_uInt32 aNumberOfContributions(0);
2355 
2356             const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
2357             ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
2358             rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
2359             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
2360             bool bResult(0 != pWriteAcc);
2361 
2362             if(pWriteAcc)
2363             {
2364                 for(sal_uInt32 x(0); x < nWidth; x++)
2365                 {
2366                     for(sal_uInt32 y(0); y < nNewHeight; y++)
2367                     {
2368                         const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
2369                         double aSum(0.0);
2370                         double aValueRed(0.0);
2371                         double aValueGreen(0.0);
2372                         double aValueBlue(0.0);
2373 
2374                         for(sal_uInt32 j(0); j < pCount[y]; j++)
2375                         {
2376                             const sal_uInt32 aIndex(aBaseIndex + j);
2377                             const double aWeight(pWeights[aIndex]);
2378                             BitmapColor aColor;
2379 
2380                             aSum += aWeight;
2381 
2382                             if(pReadAcc->HasPalette())
2383                             {
2384                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
2385                             }
2386                             else
2387                             {
2388                                 aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
2389                             }
2390 
2391                             aValueRed += aWeight * aColor.GetRed();
2392                             aValueGreen += aWeight * aColor.GetGreen();
2393                             aValueBlue += aWeight * aColor.GetBlue();
2394                         }
2395 
2396                         const BitmapColor aResultColor(
2397                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
2398                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
2399                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
2400 
2401                         if(pWriteAcc->HasPalette())
2402                         {
2403                             pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
2404                         }
2405                         else
2406                         {
2407                             pWriteAcc->SetPixel(y, x, aResultColor);
2408                         }
2409                     }
2410                 }
2411             }
2412 
2413             rTarget.ReleaseAccess(pWriteAcc);
2414             rSource.ReleaseAccess(pReadAcc);
2415 
2416             delete[] pWeights;
2417             delete[] pCount;
2418             delete[] pPixels;
2419 
2420             if(bResult)
2421             {
2422                 return true;
2423             }
2424         }
2425 
2426         return false;
2427     }
2428 }
2429 
2430 // #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and
2431 // BMP_SCALE_BOX derived from the original commit from Toma� Vajngerl (see
2432 // bugzilla task for deitails) Thanks!
2433 sal_Bool Bitmap::ImplScaleConvolution(
2434     const double& rScaleX,
2435     const double& rScaleY,
2436     const Kernel& aKernel)
2437 {
2438     const bool bMirrorHor(rScaleX < 0.0);
2439     const bool bMirrorVer(rScaleY < 0.0);
2440     const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
2441     const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
2442     const sal_uInt32 nWidth(GetSizePixel().Width());
2443     const sal_uInt32 nHeight(GetSizePixel().Height());
2444     const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
2445     const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
2446     const bool bScaleHor(nWidth != nNewWidth);
2447     const bool bScaleVer(nHeight != nNewHeight);
2448     const bool bMirror(bMirrorHor || bMirrorVer);
2449 
2450     if(!bMirror && !bScaleHor && !bScaleVer)
2451     {
2452         return true;
2453     }
2454 
2455     bool bResult(true);
2456     sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
2457     bool bMirrorAfter(false);
2458 
2459     if(bMirror)
2460     {
2461         if(bMirrorHor)
2462         {
2463             nMirrorFlags |= BMP_MIRROR_HORZ;
2464         }
2465 
2466         if(bMirrorVer)
2467         {
2468             nMirrorFlags |= BMP_MIRROR_VERT;
2469         }
2470 
2471         const sal_uInt32 nStartSize(nWidth * nHeight);
2472         const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
2473 
2474         bMirrorAfter = nStartSize > nEndSize;
2475 
2476         if(!bMirrorAfter)
2477         {
2478             bResult = Mirror(nMirrorFlags);
2479         }
2480     }
2481 
2482     Bitmap aResult;
2483 
2484     if(bResult)
2485     {
2486         const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
2487         const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
2488         Bitmap aSource(*this);
2489 
2490         if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
2491         {
2492             if(bScaleHor)
2493             {
2494                 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
2495             }
2496 
2497             if(bResult && bScaleVer)
2498             {
2499                 if(bScaleHor)
2500                 {
2501                     // copy partial result, independent of color depth
2502                     aSource = aResult;
2503                 }
2504 
2505                 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
2506             }
2507         }
2508         else
2509         {
2510             if(bScaleVer)
2511             {
2512                 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
2513             }
2514 
2515             if(bResult && bScaleHor)
2516             {
2517                 if(bScaleVer)
2518                 {
2519                     // copy partial result, independent of color depth
2520                     aSource = aResult;
2521                 }
2522 
2523                 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
2524             }
2525         }
2526     }
2527 
2528     if(bResult && bMirrorAfter)
2529     {
2530         bResult = aResult.Mirror(nMirrorFlags);
2531     }
2532 
2533     if(bResult)
2534     {
2535         ImplAdaptBitCount(aResult);
2536         *this = aResult;
2537     }
2538 
2539     return bResult;
2540 }
2541 
2542 // ------------------------------------------------------------------------
2543 
2544 sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
2545 {
2546 	sal_Bool bRet = sal_False;
2547 
2548 	const Size aSizePix( GetSizePixel() );
2549 
2550 	if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
2551 		bRet = sal_True;
2552 	else if( nDitherFlags & BMP_DITHER_MATRIX )
2553 		bRet = ImplDitherMatrix();
2554 	else if( nDitherFlags & BMP_DITHER_FLOYD )
2555 		bRet = ImplDitherFloyd();
2556 	else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
2557 		bRet = ImplDitherFloyd16();
2558 
2559 	return bRet;
2560 }
2561 
2562 // ------------------------------------------------------------------------
2563 
2564 sal_Bool Bitmap::ImplDitherMatrix()
2565 {
2566 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
2567 	Bitmap				aNewBmp( GetSizePixel(), 8 );
2568 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
2569 	sal_Bool				bRet = sal_False;
2570 
2571 	if( pReadAcc && pWriteAcc )
2572 	{
2573 		const sal_uLong	nWidth = pReadAcc->Width();
2574 		const sal_uLong	nHeight = pReadAcc->Height();
2575 		BitmapColor	aIndex( (sal_uInt8) 0 );
2576 
2577 		if( pReadAcc->HasPalette() )
2578 		{
2579 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2580 			{
2581 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2582 				{
2583 					const BitmapColor	aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
2584 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2585 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2586 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2587 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2588 
2589 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2590 					pWriteAcc->SetPixel( nY, nX, aIndex );
2591 				}
2592 			}
2593 		}
2594 		else
2595 		{
2596 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2597 			{
2598 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2599 				{
2600 					const BitmapColor	aCol( pReadAcc->GetPixel( nY, nX ) );
2601 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2602 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2603 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2604 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2605 
2606 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2607 					pWriteAcc->SetPixel( nY, nX, aIndex );
2608 				}
2609 			}
2610 		}
2611 
2612 		bRet = sal_True;
2613 	}
2614 
2615 	ReleaseAccess( pReadAcc );
2616 	aNewBmp.ReleaseAccess( pWriteAcc );
2617 
2618 	if( bRet )
2619 	{
2620 		const MapMode	aMap( maPrefMapMode );
2621 		const Size		aSize( maPrefSize );
2622 
2623 		*this = aNewBmp;
2624 
2625 		maPrefMapMode = aMap;
2626 		maPrefSize = aSize;
2627 	}
2628 
2629 	return bRet;
2630 }
2631 
2632 // ------------------------------------------------------------------------
2633 
2634 sal_Bool Bitmap::ImplDitherFloyd()
2635 {
2636 	const Size	aSize( GetSizePixel() );
2637 	sal_Bool		bRet = sal_False;
2638 
2639 	if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
2640 	{
2641 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
2642 		Bitmap				aNewBmp( GetSizePixel(), 8 );
2643 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
2644 
2645 		if( pReadAcc && pWriteAcc )
2646 		{
2647 			BitmapColor	aColor;
2648 			long		nWidth = pReadAcc->Width();
2649 			long		nWidth1 = nWidth - 1L;
2650 			long		nHeight = pReadAcc->Height();
2651 			long		nX;
2652 			long		nW = nWidth * 3L;
2653 			long		nW2 = nW - 3L;
2654 			long		nRErr, nGErr, nBErr;
2655 			long		nRC, nGC, nBC;
2656 			long		nTemp;
2657 			long		nZ;
2658 			long*		p1 = new long[ nW ];
2659 			long*		p2 = new long[ nW ];
2660 			long*		p1T = p1;
2661 			long*		p2T = p2;
2662 			long*		pTmp;
2663 			sal_Bool		bPal = pReadAcc->HasPalette();
2664 
2665 			pTmp = p2T;
2666 
2667 			if( bPal )
2668 			{
2669 				for( nZ = 0; nZ < nWidth; nZ++ )
2670 				{
2671 					aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) );
2672 
2673 					*pTmp++ = (long) aColor.GetBlue() << 12;
2674 					*pTmp++ = (long) aColor.GetGreen() << 12;
2675 					*pTmp++ = (long) aColor.GetRed() << 12;
2676 				}
2677 			}
2678 			else
2679 			{
2680 				for( nZ = 0; nZ < nWidth; nZ++ )
2681 				{
2682 					aColor = pReadAcc->GetPixel( 0, nZ );
2683 
2684 					*pTmp++ = (long) aColor.GetBlue() << 12;
2685 					*pTmp++ = (long) aColor.GetGreen() << 12;
2686 					*pTmp++ = (long) aColor.GetRed() << 12;
2687 				}
2688 			}
2689 
2690 			for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
2691 			{
2692 				pTmp = p1T;
2693 				p1T = p2T;
2694 				p2T = pTmp;
2695 
2696 				if( nY < nHeight )
2697 				{
2698 					if( bPal )
2699 					{
2700 						for( nZ = 0; nZ < nWidth; nZ++ )
2701 						{
2702 							aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) );
2703 
2704 							*pTmp++ = (long) aColor.GetBlue() << 12;
2705 							*pTmp++ = (long) aColor.GetGreen() << 12;
2706 							*pTmp++ = (long) aColor.GetRed() << 12;
2707 						}
2708 					}
2709 					else
2710 					{
2711 						for( nZ = 0; nZ < nWidth; nZ++ )
2712 						{
2713 							aColor = pReadAcc->GetPixel( nY, nZ );
2714 
2715 							*pTmp++ = (long) aColor.GetBlue() << 12;
2716 							*pTmp++ = (long) aColor.GetGreen() << 12;
2717 							*pTmp++ = (long) aColor.GetRed() << 12;
2718 						}
2719 					}
2720 				}
2721 
2722 				// erstes Pixel gesondert betrachten
2723 				nX = 0;
2724 				CALC_ERRORS;
2725 				CALC_TABLES7;
2726 				nX -= 5;
2727 				CALC_TABLES5;
2728 				pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2729 
2730 				// mittlere Pixel ueber Schleife
2731 				long nXAcc;
2732 				for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
2733 				{
2734 					CALC_ERRORS;
2735 					CALC_TABLES7;
2736 					nX -= 8;
2737 					CALC_TABLES3;
2738 					CALC_TABLES5;
2739 					pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2740 				}
2741 
2742 				// letztes Pixel gesondert betrachten
2743 				CALC_ERRORS;
2744 				nX -= 5;
2745 				CALC_TABLES3;
2746 				CALC_TABLES5;
2747 				pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2748 			}
2749 
2750 			delete[] p1;
2751 			delete[] p2;
2752 			bRet = sal_True;
2753 		}
2754 
2755 		ReleaseAccess( pReadAcc );
2756 		aNewBmp.ReleaseAccess( pWriteAcc );
2757 
2758 		if( bRet )
2759 		{
2760 			const MapMode	aMap( maPrefMapMode );
2761 			const Size		aPrefSize( maPrefSize );
2762 
2763 			*this = aNewBmp;
2764 
2765 			maPrefMapMode = aMap;
2766 			maPrefSize = aPrefSize;
2767 		}
2768 	}
2769 
2770 	return bRet;
2771 }
2772 
2773 // ------------------------------------------------------------------------
2774 
2775 sal_Bool Bitmap::ImplDitherFloyd16()
2776 {
2777 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
2778 	Bitmap				aNewBmp( GetSizePixel(), 24 );
2779 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
2780 	sal_Bool				bRet = sal_False;
2781 
2782 	if( pReadAcc && pWriteAcc )
2783 	{
2784 		const long		nWidth = pWriteAcc->Width();
2785 		const long		nWidth1 = nWidth - 1L;
2786 		const long		nHeight = pWriteAcc->Height();
2787 		BitmapColor 	aColor;
2788 		BitmapColor		aBestCol;
2789 		ImpErrorQuad	aErrQuad;
2790 		ImpErrorQuad*	pErrQuad1 = new ImpErrorQuad[ nWidth ];
2791 		ImpErrorQuad*	pErrQuad2 = new ImpErrorQuad[ nWidth ];
2792 		ImpErrorQuad*	pQLine1 = pErrQuad1;
2793 		ImpErrorQuad*	pQLine2 = 0;
2794 		long			nX, nY;
2795 		long			nYTmp = 0L;
2796 		sal_Bool			bQ1 = sal_True;
2797 
2798 		for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
2799 			for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
2800 				pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2801 
2802 		for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
2803 		{
2804 			// erstes ZeilenPixel
2805 			aBestCol = pQLine1[ 0 ].ImplGetColor();
2806 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2807 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2808 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2809 			pWriteAcc->SetPixel( nY, 0, aBestCol );
2810 
2811 			for( nX = 1L; nX < nWidth1; nX++ )
2812 			{
2813 				aColor = pQLine1[ nX ].ImplGetColor();
2814 				aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
2815 				aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
2816 				aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
2817 				aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
2818 				pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
2819 				pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
2820 				pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
2821 				pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
2822 				pWriteAcc->SetPixel( nY, nX, aBestCol );
2823 			}
2824 
2825 			// letztes ZeilenPixel
2826 			aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
2827 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2828 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2829 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2830 			pWriteAcc->SetPixel( nY, nX, aBestCol );
2831 
2832 			// Zeilenpuffer neu fuellen/kopieren
2833 			pQLine1 = pQLine2;
2834 			pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
2835 
2836 			if( nYTmp < nHeight )
2837 				for( nX = 0L; nX < nWidth; nX++ )
2838 					pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2839 		}
2840 
2841 		// Zeilenpuffer zerstoeren
2842 		delete[] pErrQuad1;
2843 		delete[] pErrQuad2;
2844 		bRet = sal_True;
2845 	}
2846 
2847 	ReleaseAccess( pReadAcc );
2848 	aNewBmp.ReleaseAccess( pWriteAcc );
2849 
2850 	if( bRet )
2851 	{
2852 		const MapMode	aMap( maPrefMapMode );
2853 		const Size		aSize( maPrefSize );
2854 
2855 		*this = aNewBmp;
2856 
2857 		maPrefMapMode = aMap;
2858 		maPrefSize = aSize;
2859 	}
2860 
2861 	return bRet;
2862 }
2863 
2864 // ------------------------------------------------------------------------
2865 
2866 sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
2867 {
2868 	sal_Bool bRet;
2869 
2870 	if( GetColorCount() <= (sal_uLong) nColorCount )
2871 		bRet = sal_True;
2872 	else if( nColorCount )
2873 	{
2874 		if( BMP_REDUCE_SIMPLE == eReduce )
2875 			bRet = ImplReduceSimple( nColorCount );
2876 		else if( BMP_REDUCE_POPULAR == eReduce )
2877 			bRet = ImplReducePopular( nColorCount );
2878 		else
2879 			bRet = ImplReduceMedian( nColorCount );
2880 	}
2881 	else
2882 		bRet = sal_False;
2883 
2884 	return bRet;
2885 }
2886 
2887 // ------------------------------------------------------------------------
2888 
2889 sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
2890 {
2891 	Bitmap				aNewBmp;
2892 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
2893 	const sal_uInt16		nColCount = Min( nColorCount, (sal_uInt16) 256 );
2894 	sal_uInt16				nBitCount;
2895 	sal_Bool				bRet = sal_False;
2896 
2897 	if( nColCount <= 2 )
2898 		nBitCount = 1;
2899 	else if( nColCount <= 16 )
2900 		nBitCount = 4;
2901 	else
2902 		nBitCount = 8;
2903 
2904 	if( pRAcc )
2905 	{
2906 		Octree					aOct( *pRAcc, nColCount );
2907 		const BitmapPalette&	rPal = aOct.GetPalette();
2908 		BitmapWriteAccess*		pWAcc;
2909 
2910 		aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
2911 		pWAcc = aNewBmp.AcquireWriteAccess();
2912 
2913 		if( pWAcc )
2914 		{
2915 			const long nWidth = pRAcc->Width();
2916 			const long nHeight = pRAcc->Height();
2917 
2918 			if( pRAcc->HasPalette() )
2919 			{
2920 				for( long nY = 0L; nY < nHeight; nY++ )
2921 					for( long nX =0L; nX < nWidth; nX++ )
2922 						pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) );
2923 			}
2924 			else
2925 			{
2926 				for( long nY = 0L; nY < nHeight; nY++ )
2927 					for( long nX =0L; nX < nWidth; nX++ )
2928 						pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) );
2929 			}
2930 
2931 			aNewBmp.ReleaseAccess( pWAcc );
2932 			bRet = sal_True;
2933 		}
2934 
2935 		ReleaseAccess( pRAcc );
2936 	}
2937 
2938 	if( bRet )
2939 	{
2940 		const MapMode	aMap( maPrefMapMode );
2941 		const Size		aSize( maPrefSize );
2942 
2943 		*this = aNewBmp;
2944 		maPrefMapMode = aMap;
2945 		maPrefSize = aSize;
2946 	}
2947 
2948 	return bRet;
2949 }
2950 
2951 // ------------------------------------------------------------------------
2952 
2953 struct PopularColorCount
2954 {
2955 	sal_uInt32	mnIndex;
2956 	sal_uInt32	mnCount;
2957 };
2958 
2959 // ------------------------------------------------------------------------
2960 
2961 extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
2962 {
2963 	int nRet;
2964 
2965 	if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
2966 		nRet = 1;
2967 	else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
2968 		nRet = 0;
2969 	else
2970 		nRet = -1;
2971 
2972 	return nRet;
2973 }
2974 
2975 // ------------------------------------------------------------------------
2976 
2977 sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
2978 {
2979 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
2980 	sal_uInt16				nBitCount;
2981 	sal_Bool				bRet = sal_False;
2982 
2983 	if( nColCount > 256 )
2984 		nColCount = 256;
2985 
2986 	if( nColCount < 17 )
2987 		nBitCount = 4;
2988 	else
2989 		nBitCount = 8;
2990 
2991 	if( pRAcc )
2992 	{
2993 		const sal_uInt32	nValidBits = 4;
2994 		const sal_uInt32	nRightShiftBits = 8 - nValidBits;
2995 		const sal_uInt32	nLeftShiftBits1 = nValidBits;
2996 		const sal_uInt32	nLeftShiftBits2 = nValidBits << 1;
2997 		const sal_uInt32	nColorsPerComponent = 1 << nValidBits;
2998 		const sal_uInt32	nColorOffset = 256 / nColorsPerComponent;
2999 		const sal_uInt32	nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
3000 		const long			nWidth = pRAcc->Width();
3001 		const long			nHeight = pRAcc->Height();
3002 		PopularColorCount*	pCountTable = new PopularColorCount[ nTotalColors ];
3003 		long				nX, nY, nR, nG, nB, nIndex;
3004 
3005 		rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
3006 
3007 		for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3008         {
3009 			for( nG = 0; nG < 256; nG += nColorOffset )
3010             {
3011 				for( nB = 0; nB < 256; nB += nColorOffset )
3012                 {
3013 					pCountTable[ nIndex ].mnIndex = nIndex;
3014                     nIndex++;
3015                 }
3016             }
3017         }
3018 
3019 		if( pRAcc->HasPalette() )
3020 		{
3021 			for( nY = 0L; nY < nHeight; nY++ )
3022 			{
3023 				for( nX = 0L; nX < nWidth; nX++ )
3024 				{
3025 					const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3026 					pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3027 								 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3028 								 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3029 				}
3030 			}
3031 		}
3032 		else
3033 		{
3034 			for( nY = 0L; nY < nHeight; nY++ )
3035 			{
3036 				for( nX = 0L; nX < nWidth; nX++ )
3037 				{
3038 					const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3039 					pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3040 								 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3041 								 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3042 				}
3043 			}
3044 		}
3045 
3046 		BitmapPalette aNewPal( nColCount );
3047 
3048 		qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
3049 
3050 		for( sal_uInt16 n = 0; n < nColCount; n++ )
3051 		{
3052 			const PopularColorCount& rPop = pCountTable[ n ];
3053 			aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
3054 										(sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
3055 										(sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
3056 		}
3057 
3058 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
3059 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
3060 
3061 		if( pWAcc )
3062 		{
3063 			BitmapColor	aDstCol( (sal_uInt8) 0 );
3064 			sal_uInt8*		pIndexMap = new sal_uInt8[ nTotalColors ];
3065 
3066 			for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3067 				for( nG = 0; nG < 256; nG += nColorOffset )
3068 					for( nB = 0; nB < 256; nB += nColorOffset )
3069 						pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
3070 
3071 			if( pRAcc->HasPalette() )
3072 			{
3073 				for( nY = 0L; nY < nHeight; nY++ )
3074 				{
3075 					for( nX = 0L; nX < nWidth; nX++ )
3076 					{
3077 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3078 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3079 													 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3080 													 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
3081 						pWAcc->SetPixel( nY, nX, aDstCol );
3082 					}
3083 				}
3084 			}
3085 			else
3086 			{
3087 				for( nY = 0L; nY < nHeight; nY++ )
3088 				{
3089 					for( nX = 0L; nX < nWidth; nX++ )
3090 					{
3091 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3092 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3093 													 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3094 													 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
3095 						pWAcc->SetPixel( nY, nX, aDstCol );
3096 					}
3097 				}
3098 			}
3099 
3100 			delete[] pIndexMap;
3101 			aNewBmp.ReleaseAccess( pWAcc );
3102 			bRet = sal_True;
3103 		}
3104 
3105 		delete[] pCountTable;
3106 		ReleaseAccess( pRAcc );
3107 
3108 		if( bRet )
3109 		{
3110 			const MapMode	aMap( maPrefMapMode );
3111 			const Size		aSize( maPrefSize );
3112 
3113 			*this = aNewBmp;
3114 			maPrefMapMode = aMap;
3115 			maPrefSize = aSize;
3116 		}
3117 	}
3118 
3119 	return bRet;
3120 }
3121 
3122 // ------------------------------------------------------------------------
3123 
3124 sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
3125 {
3126 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
3127 	sal_uInt16				nBitCount;
3128 	sal_Bool				bRet = sal_False;
3129 
3130 	if( nColCount < 17 )
3131 		nBitCount = 4;
3132 	else if( nColCount < 257 )
3133 		nBitCount = 8;
3134 	else
3135 	{
3136 		DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
3137 		nBitCount = 8;
3138 		nColCount = 256;
3139 	}
3140 
3141 	if( pRAcc )
3142 	{
3143 		Bitmap				aNewBmp( GetSizePixel(), nBitCount );
3144 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
3145 
3146 		if( pWAcc )
3147 		{
3148 			const sal_uLong	nSize = 32768UL * sizeof( sal_uLong );
3149 			sal_uLong*		pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
3150 			const long	nWidth = pWAcc->Width();
3151 			const long	nHeight = pWAcc->Height();
3152 			long		nIndex = 0L;
3153 
3154 			memset( (HPBYTE) pColBuf, 0, nSize );
3155 
3156 			// create Buffer
3157 			if( pRAcc->HasPalette() )
3158 			{
3159 				for( long nY = 0L; nY < nHeight; nY++ )
3160 				{
3161 					for( long nX = 0L; nX < nWidth; nX++ )
3162 					{
3163 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3164 						pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
3165 					}
3166 				}
3167 			}
3168 			else
3169 			{
3170 				for( long nY = 0L; nY < nHeight; nY++ )
3171 				{
3172 					for( long nX = 0L; nX < nWidth; nX++ )
3173 					{
3174 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3175 						pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
3176 					}
3177 				}
3178 			}
3179 
3180 			// create palette via median cut
3181 			BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
3182 			ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
3183 						   nColCount, nWidth * nHeight, nIndex );
3184 
3185 			// do mapping of colors to palette
3186 			InverseColorMap aMap( aPal );
3187 			pWAcc->SetPalette( aPal );
3188 			for( long nY = 0L; nY < nHeight; nY++ )
3189 				for( long nX = 0L; nX < nWidth; nX++ )
3190 					pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) );
3191 
3192 			rtl_freeMemory( pColBuf );
3193 			aNewBmp.ReleaseAccess( pWAcc );
3194 			bRet = sal_True;
3195 		}
3196 
3197 		ReleaseAccess( pRAcc );
3198 
3199 		if( bRet )
3200 		{
3201 			const MapMode	aMap( maPrefMapMode );
3202 			const Size		aSize( maPrefSize );
3203 
3204 			*this = aNewBmp;
3205 			maPrefMapMode = aMap;
3206 			maPrefSize = aSize;
3207 		}
3208 	}
3209 
3210 	return bRet;
3211 }
3212 
3213 // ------------------------------------------------------------------------
3214 
3215 void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
3216 							long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
3217 							long nColors, long nPixels, long& rIndex )
3218 {
3219 	if( !nPixels )
3220 		return;
3221 
3222 	BitmapColor	aCol;
3223 	const long	nRLen = nR2 - nR1;
3224 	const long	nGLen = nG2 - nG1;
3225 	const long	nBLen = nB2 - nB1;
3226 	long 		nR, nG, nB;
3227 	sal_uLong*		pBuf = pColBuf;
3228 
3229 	if( !nRLen && !nGLen && !nBLen )
3230 	{
3231 		if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
3232 		{
3233 			aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
3234 			aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
3235 			aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
3236 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
3237 		}
3238 	}
3239 	else
3240 	{
3241 		if( 1 == nColors || 1 == nPixels )
3242 		{
3243 			long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
3244 
3245 			for( nR = nR1; nR <= nR2; nR++ )
3246 			{
3247 				for( nG = nG1; nG <= nG2; nG++ )
3248 				{
3249 					for( nB = nB1; nB <= nB2; nB++ )
3250 					{
3251 						nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
3252 
3253 						if( nPixSum )
3254 						{
3255 							nRSum += nR * nPixSum;
3256 							nGSum += nG * nPixSum;
3257 							nBSum += nB * nPixSum;
3258 						}
3259 					}
3260 				}
3261 			}
3262 
3263 			aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
3264 			aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
3265 			aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
3266 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
3267 		}
3268 		else
3269 		{
3270 			const long	nTest = ( nPixels >> 1 );
3271 			long		nPixOld = 0;
3272 			long		nPixNew = 0;
3273 
3274 			if( nBLen > nGLen && nBLen > nRLen )
3275 			{
3276 				nB = nB1 - 1;
3277 
3278 				while( nPixNew < nTest )
3279 				{
3280 					nB++, nPixOld = nPixNew;
3281 					for( nR = nR1; nR <= nR2; nR++ )
3282 						for( nG = nG1; nG <= nG2; nG++ )
3283 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3284 				}
3285 
3286 				if( nB < nB2 )
3287 				{
3288 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
3289 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3290 				}
3291 				else
3292 				{
3293 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
3294 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3295 				}
3296 			}
3297 			else if( nGLen > nRLen )
3298 			{
3299 				nG = nG1 - 1;
3300 
3301 				while( nPixNew < nTest )
3302 				{
3303 					nG++, nPixOld = nPixNew;
3304 					for( nR = nR1; nR <= nR2; nR++ )
3305 						for( nB = nB1; nB <= nB2; nB++ )
3306 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3307 				}
3308 
3309 				if( nG < nG2 )
3310 				{
3311 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3312 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3313 				}
3314 				else
3315 				{
3316 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3317 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3318 				}
3319 			}
3320 			else
3321 			{
3322 				nR = nR1 - 1;
3323 
3324 				while( nPixNew < nTest )
3325 				{
3326 					nR++, nPixOld = nPixNew;
3327 					for( nG = nG1; nG <= nG2; nG++ )
3328 						for( nB = nB1; nB <= nB2; nB++ )
3329 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3330 				}
3331 
3332 				if( nR < nR2 )
3333 				{
3334 					ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3335 					ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3336 				}
3337 				else
3338 				{
3339 					ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3340 					ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3341 				}
3342 			}
3343 		}
3344 	}
3345 }
3346 
3347 // ------------------------------------------------------------------------
3348 
3349 sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
3350 {
3351 	return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
3352 }
3353 
3354 // ------------------------------------------------------------------------
3355 
3356 sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
3357 {
3358 	return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
3359 }
3360 
3361 // ------------------------------------------------------------------------
3362 
3363 sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
3364 					 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
3365 					 double fGamma, sal_Bool bInvert )
3366 {
3367 	sal_Bool bRet = sal_False;
3368 
3369 	// nothing to do => return quickly
3370 	if( !nLuminancePercent && !nContrastPercent &&
3371 		!nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
3372 		( fGamma == 1.0 ) && !bInvert )
3373 	{
3374 		bRet = sal_True;
3375 	}
3376 	else
3377 	{
3378 		BitmapWriteAccess* pAcc = AcquireWriteAccess();
3379 
3380 		if( pAcc )
3381 		{
3382 			BitmapColor		aCol;
3383 			const long		nW = pAcc->Width();
3384 			const long		nH = pAcc->Height();
3385 			sal_uInt8*			cMapR = new sal_uInt8[ 256 ];
3386 			sal_uInt8*			cMapG = new sal_uInt8[ 256 ];
3387 			sal_uInt8*			cMapB = new sal_uInt8[ 256 ];
3388 			long			nX, nY;
3389 			double			fM, fROff, fGOff, fBOff, fOff;
3390 
3391 			// calculate slope
3392 			if( nContrastPercent >= 0 )
3393 				fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
3394 			else
3395 				fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
3396 
3397 			// total offset = luminance offset + contrast offset
3398 			fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
3399 
3400 			// channel offset = channel offset  + total offset
3401 			fROff = nChannelRPercent * 2.55 + fOff;
3402 			fGOff = nChannelGPercent * 2.55 + fOff;
3403 			fBOff = nChannelBPercent * 2.55 + fOff;
3404 
3405 			// calculate gamma value
3406 			fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
3407 			const sal_Bool bGamma = ( fGamma != 1.0 );
3408 
3409 			// create mapping table
3410 			for( nX = 0L; nX < 256L; nX++ )
3411 			{
3412 				cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
3413 				cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
3414 				cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
3415 
3416 				if( bGamma )
3417 				{
3418 					cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
3419 					cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
3420 					cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
3421 				}
3422 
3423 				if( bInvert )
3424 				{
3425 					cMapR[ nX ] = ~cMapR[ nX ];
3426 					cMapG[ nX ] = ~cMapG[ nX ];
3427 					cMapB[ nX ] = ~cMapB[ nX ];
3428 				}
3429 			}
3430 
3431 			// do modifying
3432 			if( pAcc->HasPalette() )
3433 			{
3434 				BitmapColor aNewCol;
3435 
3436 				for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
3437 				{
3438 					const BitmapColor& rCol = pAcc->GetPaletteColor( i );
3439 					aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
3440 					aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
3441 					aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
3442 					pAcc->SetPaletteColor( i, aNewCol );
3443 				}
3444 			}
3445 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
3446 			{
3447 				for( nY = 0L; nY < nH; nY++ )
3448 				{
3449 					Scanline pScan = pAcc->GetScanline( nY );
3450 
3451 					for( nX = 0L; nX < nW; nX++ )
3452 					{
3453 						*pScan = cMapB[ *pScan ]; pScan++;
3454 						*pScan = cMapG[ *pScan ]; pScan++;
3455 						*pScan = cMapR[ *pScan ]; pScan++;
3456 					}
3457 				}
3458 			}
3459 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
3460 			{
3461 				for( nY = 0L; nY < nH; nY++ )
3462 				{
3463 					Scanline pScan = pAcc->GetScanline( nY );
3464 
3465 					for( nX = 0L; nX < nW; nX++ )
3466 					{
3467 						*pScan = cMapR[ *pScan ]; pScan++;
3468 						*pScan = cMapG[ *pScan ]; pScan++;
3469 						*pScan = cMapB[ *pScan ]; pScan++;
3470 					}
3471 				}
3472 			}
3473 			else
3474 			{
3475 				for( nY = 0L; nY < nH; nY++ )
3476 				{
3477 					for( nX = 0L; nX < nW; nX++ )
3478 					{
3479 						aCol = pAcc->GetPixel( nY, nX );
3480 						aCol.SetRed( cMapR[ aCol.GetRed() ] );
3481 						aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
3482 						aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
3483 						pAcc->SetPixel( nY, nX, aCol );
3484 					}
3485 				}
3486 			}
3487 
3488 			delete[] cMapR;
3489 			delete[] cMapG;
3490 			delete[] cMapB;
3491 			ReleaseAccess( pAcc );
3492 			bRet = sal_True;
3493 		}
3494 	}
3495 
3496 	return bRet;
3497 }
3498