xref: /aoo42x/main/vcl/source/gdi/bitmap3.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <stdlib.h>
32 
33 #include <vcl/bmpacc.hxx>
34 #include <vcl/octree.hxx>
35 #include <vcl/bitmapex.hxx>
36 #include <vcl/bitmap.hxx>
37 
38 #include <impoct.hxx>
39 #include <impvect.hxx>
40 
41 // -----------
42 // - Defines -
43 // -----------
44 
45 #define RGB15( _def_cR, _def_cG, _def_cB )	(((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
46 #define GAMMA( _def_cVal, _def_InvGamma )	((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
47 
48 #define CALC_ERRORS																\
49 						nTemp   = p1T[nX++] >> 12;								\
50 						nBErr = MinMax( nTemp, 0, 255 );						\
51 						nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ];	\
52 						nTemp   = p1T[nX++] >> 12;								\
53 						nGErr = MinMax( nTemp, 0, 255 );						\
54 						nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ];	\
55 						nTemp   = p1T[nX] >> 12;								\
56 						nRErr = MinMax( nTemp, 0, 255 );						\
57 						nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
58 
59 #define CALC_TABLES3										\
60 						p2T[nX++] += FloydError3[nBErr];	\
61 						p2T[nX++] += FloydError3[nGErr];	\
62 						p2T[nX++] += FloydError3[nRErr];
63 
64 #define CALC_TABLES5										\
65 						p2T[nX++] += FloydError5[nBErr];	\
66 						p2T[nX++] += FloydError5[nGErr];	\
67 						p2T[nX++] += FloydError5[nRErr];
68 
69 #define CALC_TABLES7										\
70 						p1T[++nX] += FloydError7[nBErr];	\
71 						p2T[nX++] += FloydError1[nBErr];	\
72 						p1T[nX] += FloydError7[nGErr];		\
73 						p2T[nX++] += FloydError1[nGErr];	\
74 						p1T[nX] += FloydError7[nRErr];		\
75 						p2T[nX] += FloydError1[nRErr];
76 
77 // -----------
78 // - Statics -
79 // -----------
80 
81 sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
82 sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
83 sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
84 
85 // ------------------------------------------------------------------------
86 
87 sal_uLong nVCLDitherLut[ 256 ] =
88 {
89        0, 49152, 12288, 61440,  3072, 52224, 15360, 64512,   768, 49920, 13056,
90    62208,  3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
91    48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
92    57344,  4096, 53248, 11264, 60416,  7168, 56320,  8960, 58112,  4864, 54016,
93    12032, 61184,  7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
94    23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
95    14336, 63488,  1024, 50176, 13312, 62464,  2816, 51968, 15104, 64256,  1792,
96    50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
97    35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392,  6144,
98    55296,  9216, 58368,  5120, 54272, 11008, 60160,  6912, 56064,  9984, 59136,
99     5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
100    27392, 39680, 23296, 42752, 26368, 38656, 22272,   512, 49664, 12800, 61952,
101     3584, 52736, 15872, 65024,   256, 49408, 12544, 61696,  3328, 52480, 15616,
102    64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
103    45312, 28928, 36096, 19712, 48384, 32000,  8704, 57856,  4608, 53760, 11776,
104    60928,  7680, 56832,  8448, 57600,  4352, 53504, 11520, 60672,  7424, 56576,
105    41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
106    20736, 44288, 27904, 40192, 23808,  2560, 51712, 14848, 64000,  1536, 50688,
107    13824, 62976,  2304, 51456, 14592, 63744,  1280, 50432, 13568, 62720, 35328,
108    18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
109    34048, 17664, 46336, 29952, 10752, 59904,  6656, 55808,  9728, 58880,  5632,
110    54784, 10496, 59648,  6400, 55552,  9472, 58624,  5376, 54528, 43520, 27136,
111    39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
112    25856, 38144, 21760
113 };
114 
115 // ------------------------------------------------------------------------
116 
117 sal_uLong nVCLLut[ 256 ] =
118 {
119          0,  1286,  2572,  3858,  5144,  6430,  7716,  9002,
120      10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
121      20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
122      30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
123      41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
124      51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
125      61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
126      72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
127      82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
128      92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
129     102880,104166,105452,106738,108024,109310,110596,111882,
130     113168,114454,115740,117026,118312,119598,120884,122170,
131     123456,124742,126028,127314,128600,129886,131172,132458,
132     133744,135030,136316,137602,138888,140174,141460,142746,
133     144032,145318,146604,147890,149176,150462,151748,153034,
134     154320,155606,156892,158178,159464,160750,162036,163322,
135     164608,165894,167180,168466,169752,171038,172324,173610,
136     174896,176182,177468,178754,180040,181326,182612,183898,
137     185184,186470,187756,189042,190328,191614,192900,194186,
138     195472,196758,198044,199330,200616,201902,203188,204474,
139     205760,207046,208332,209618,210904,212190,213476,214762,
140     216048,217334,218620,219906,221192,222478,223764,225050,
141     226336,227622,228908,230194,231480,232766,234052,235338,
142     236624,237910,239196,240482,241768,243054,244340,245626,
143     246912,248198,249484,250770,252056,253342,254628,255914,
144     257200,258486,259772,261058,262344,263630,264916,266202,
145     267488,268774,270060,271346,272632,273918,275204,276490,
146     277776,279062,280348,281634,282920,284206,285492,286778,
147     288064,289350,290636,291922,293208,294494,295780,297066,
148     298352,299638,300924,302210,303496,304782,306068,307354,
149     308640,309926,311212,312498,313784,315070,316356,317642,
150     318928,320214,321500,322786,324072,325358,326644,327930
151 };
152 
153 // ------------------------------------------------------------------------
154 
155 long FloydMap[256] =
156 {
157     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
158     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
159     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
160     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
161     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
162     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
164     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
165     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
166     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
167     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
168     3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
169     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
170     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
171     4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
172     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
173 };
174 
175 // ------------------------------------------------------------------------
176 
177 long FloydError1[61] =
178 {
179     -7680, -7424, -7168, -6912, -6656, -6400, -6144,
180     -5888, -5632, -5376, -5120, -4864, -4608, -4352,
181     -4096, -3840, -3584, -3328, -3072, -2816, -2560,
182     -2304, -2048, -1792, -1536, -1280, -1024, -768,
183     -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
184     1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
185     3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
186     5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
187 };
188 
189 // ------------------------------------------------------------------------
190 
191 long FloydError3[61] =
192 {
193     -23040, -22272, -21504, -20736, -19968, -19200,
194     -18432, -17664, -16896, -16128, -15360, -14592,
195     -13824, -13056, -12288, -11520, -10752, -9984,
196     -9216, -8448, -7680, -6912, -6144, -5376, -4608,
197     -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
198     2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
199     8448, 9216, 9984, 10752, 11520, 12288, 13056,
200     13824, 14592, 15360, 16128, 16896, 17664, 18432,
201     19200, 19968, 20736, 21504, 22272, 23040
202 };
203 
204 // ------------------------------------------------------------------------
205 
206 long FloydError5[61] =
207 {
208     -38400, -37120, -35840, -34560, -33280, -32000,
209     -30720, -29440, -28160, -26880, -25600, -24320,
210     -23040, -21760, -20480, -19200, -17920, -16640,
211     -15360, -14080, -12800, -11520, -10240, -8960,
212     -7680, -6400, -5120, -3840, -2560, -1280,   0,
213     1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
214     11520, 12800, 14080, 15360, 16640, 17920, 19200,
215     20480, 21760, 23040, 24320, 25600, 26880, 28160,
216     29440, 30720, 32000, 33280, 34560, 35840, 37120,
217     38400
218 };
219 
220 // ------------------------------------------------------------------------
221 
222 long FloydError7[61] =
223 {
224     -53760, -51968, -50176, -48384, -46592, -44800,
225     -43008, -41216, -39424, -37632, -35840, -34048,
226     -32256, -30464, -28672, -26880, -25088, -23296,
227     -21504, -19712, -17920, -16128, -14336, -12544,
228     -10752, -8960, -7168, -5376, -3584, -1792,  0,
229     1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
230     16128, 17920, 19712, 21504, 23296, 25088, 26880,
231     28672, 30464, 32256, 34048, 35840, 37632, 39424,
232     41216, 43008, 44800, 46592, 48384, 50176, 51968,
233     53760
234 };
235 
236 // ------------------------------------------------------------------------
237 
238 long FloydIndexMap[6] =
239 {
240     -30,  21, 72, 123, 174, 225
241 };
242 
243 // --------------------------
244 // - ImplCreateDitherMatrix -
245 // --------------------------
246 
247 void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] )
248 {
249 	double			fVal = 3.125;
250 	const double	fVal16 = fVal / 16.;
251 	long			i, j, k, l;
252 	sal_uInt16			pMtx[ 16 ][ 16 ];
253 	sal_uInt16			nMax = 0;
254 	static sal_uInt8 	pMagic[4][4] = { { 0, 14,  3, 13, },
255                                      {11,  5,  8,  6, },
256                                      {12,  2, 15,  1, },
257                                      {7,   9,  4, 10 } };
258 
259 	// MagicSquare aufbauen
260 	for ( i = 0; i < 4; i++ )
261 	   for ( j = 0; j < 4; j++ )
262 		   for ( k = 0; k < 4; k++ )
263 				for ( l = 0; l < 4; l++ )
264 					nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
265 					(sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
266 
267 	// auf Intervall [0;254] skalieren
268 	for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
269 		for( j = 0; j < 16; j++ )
270 			(*pDitherMatrix)[i][j] = (sal_uInt8) ( fVal * pMtx[i][j] );
271 }
272 
273 // ----------
274 // - Bitmap -
275 // ----------
276 
277 sal_Bool Bitmap::Convert( BmpConversion eConversion )
278 {
279 	const sal_uInt16	nBitCount = GetBitCount();
280 	sal_Bool			bRet = sal_False;
281 
282 	switch( eConversion )
283 	{
284 		case( BMP_CONVERSION_1BIT_THRESHOLD ):
285 			bRet = ImplMakeMono( 128 );
286 		break;
287 
288 		case( BMP_CONVERSION_1BIT_MATRIX ):
289 			bRet = ImplMakeMonoDither();
290 		break;
291 
292 		case( BMP_CONVERSION_4BIT_GREYS ):
293 			bRet = ImplMakeGreyscales( 16 );
294 		break;
295 
296 		case( BMP_CONVERSION_4BIT_COLORS ):
297 		{
298 			if( nBitCount < 4 )
299 				bRet = ImplConvertUp( 4, NULL );
300 			else if( nBitCount > 4 )
301 				bRet = ImplConvertDown( 4, NULL );
302 			else
303 				bRet = sal_True;
304 		}
305 		break;
306 
307 		case( BMP_CONVERSION_4BIT_TRANS ):
308 		{
309 			Color aTrans( BMP_COL_TRANS );
310 
311 			if( nBitCount < 4 )
312 				bRet = ImplConvertUp( 4, &aTrans );
313 			else
314 				bRet = ImplConvertDown( 4, &aTrans );
315 		}
316 		break;
317 
318 		case( BMP_CONVERSION_8BIT_GREYS ):
319 			bRet = ImplMakeGreyscales( 256 );
320 		break;
321 
322 		case( BMP_CONVERSION_8BIT_COLORS ):
323 		{
324 			if( nBitCount < 8 )
325 				bRet = ImplConvertUp( 8 );
326 			else if( nBitCount > 8 )
327 				bRet = ImplConvertDown( 8 );
328 			else
329 				bRet = sal_True;
330 		}
331 		break;
332 
333 		case( BMP_CONVERSION_8BIT_TRANS ):
334 		{
335 			Color aTrans( BMP_COL_TRANS );
336 
337 			if( nBitCount < 8 )
338 				bRet = ImplConvertUp( 8, &aTrans );
339 			else
340 				bRet = ImplConvertDown( 8, &aTrans );
341 		}
342 		break;
343 
344 		case( BMP_CONVERSION_24BIT ):
345 		{
346 			if( nBitCount < 24 )
347 				bRet = ImplConvertUp( 24, sal_False );
348 			else
349 				bRet = sal_True;
350 		}
351 		break;
352 
353 		case( BMP_CONVERSION_GHOSTED ):
354 			bRet = ImplConvertGhosted();
355 		break;
356 
357 		default:
358 			DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
359 		break;
360 	}
361 
362 	return bRet;
363 }
364 
365 // ------------------------------------------------------------------------
366 
367 sal_Bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold )
368 {
369 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
370 	sal_Bool				bRet = sal_False;
371 
372 	if( pReadAcc )
373 	{
374 		Bitmap				aNewBmp( GetSizePixel(), 1 );
375 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
376 
377 		if( pWriteAcc )
378 		{
379 			const BitmapColor	aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
380 			const BitmapColor	aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
381 			const long			nWidth = pWriteAcc->Width();
382 			const long			nHeight = pWriteAcc->Height();
383 
384 			if( pReadAcc->HasPalette() )
385 			{
386 				for( long nY = 0L; nY < nHeight; nY++ )
387 				{
388 					for( long nX = 0L; nX < nWidth; nX++ )
389 					{
390 						if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >=
391 							cThreshold )
392 						{
393 							pWriteAcc->SetPixel( nY, nX, aWhite );
394 						}
395 						else
396 							pWriteAcc->SetPixel( nY, nX, aBlack );
397 					}
398 				}
399 			}
400 			else
401 			{
402 				for( long nY = 0L; nY < nHeight; nY++ )
403 				{
404 					for( long nX = 0L; nX < nWidth; nX++ )
405 					{
406 						if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
407 							cThreshold )
408 						{
409 							pWriteAcc->SetPixel( nY, nX, aWhite );
410 						}
411 						else
412 							pWriteAcc->SetPixel( nY, nX, aBlack );
413 					}
414 				}
415 			}
416 
417 			aNewBmp.ReleaseAccess( pWriteAcc );
418 			bRet = sal_True;
419 		}
420 
421 		ReleaseAccess( pReadAcc );
422 
423 		if( bRet )
424 		{
425 			const MapMode	aMap( maPrefMapMode );
426 			const Size		aSize( maPrefSize );
427 
428 			*this = aNewBmp;
429 
430 			maPrefMapMode = aMap;
431 			maPrefSize = aSize;
432 		}
433 	}
434 
435 	return bRet;
436 }
437 
438 // ------------------------------------------------------------------------
439 
440 sal_Bool Bitmap::ImplMakeMonoDither()
441 {
442 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
443 	sal_Bool				bRet = sal_False;
444 
445 	if( pReadAcc )
446 	{
447 		Bitmap				aNewBmp( GetSizePixel(), 1 );
448 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
449 
450 		if( pWriteAcc )
451 		{
452 			const BitmapColor	aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
453 			const BitmapColor	aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
454 			const long			nWidth = pWriteAcc->Width();
455 			const long			nHeight = pWriteAcc->Height();
456 			sal_uInt8				pDitherMatrix[ 16 ][ 16 ];
457 
458 			ImplCreateDitherMatrix( &pDitherMatrix );
459 
460 			if( pReadAcc->HasPalette() )
461 			{
462 				for( long nY = 0L; nY < nHeight; nY++ )
463 				{
464 					for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
465 					{
466 						if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >
467 							pDitherMatrix[ nModY ][ nX % 16 ] )
468 						{
469 							pWriteAcc->SetPixel( nY, nX, aWhite );
470 						}
471 						else
472 							pWriteAcc->SetPixel( nY, nX, aBlack );
473 					}
474 				}
475 			}
476 			else
477 			{
478 				for( long nY = 0L; nY < nHeight; nY++ )
479 				{
480 					for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
481 					{
482 						if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
483 							pDitherMatrix[ nModY ][ nX % 16 ]  )
484 						{
485 							pWriteAcc->SetPixel( nY, nX, aWhite );
486 						}
487 						else
488 							pWriteAcc->SetPixel( nY, nX, aBlack );
489 					}
490 				}
491 			}
492 
493 			aNewBmp.ReleaseAccess( pWriteAcc );
494 			bRet = sal_True;
495 		}
496 
497 		ReleaseAccess( pReadAcc );
498 
499 		if( bRet )
500 		{
501 			const MapMode	aMap( maPrefMapMode );
502 			const Size		aSize( maPrefSize );
503 
504 			*this = aNewBmp;
505 
506 			maPrefMapMode = aMap;
507 			maPrefSize = aSize;
508 		}
509 	}
510 
511 	return bRet;
512 }
513 
514 // ------------------------------------------------------------------------
515 
516 sal_Bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
517 {
518 	DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" );
519 
520 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
521 	sal_Bool				bRet = sal_False;
522 
523 	if( pReadAcc )
524 	{
525 		const BitmapPalette&	rPal = GetGreyPalette( nGreys );
526 		sal_uLong 					nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
527 		sal_Bool					bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
528 
529 		if( !bPalDiffers )
530 			bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
531 
532 		if( bPalDiffers )
533 		{
534 			Bitmap				aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
535 			BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
536 
537 			if( pWriteAcc )
538 			{
539 				const long	nWidth = pWriteAcc->Width();
540 				const long	nHeight = pWriteAcc->Height();
541 
542 				if( pReadAcc->HasPalette() )
543 				{
544 					for( long nY = 0L; nY < nHeight; nY++ )
545 					{
546 						for( long nX = 0L; nX < nWidth; nX++ )
547 						{
548 							pWriteAcc->SetPixel( nY, nX,
549 								(sal_uInt8) ( pReadAcc->GetPaletteColor(
550 									pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift ) );
551 						}
552 					}
553 				}
554 				else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
555 						 pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
556 				{
557 					nShift += 8;
558 
559 					for( long nY = 0L; nY < nHeight; nY++ )
560 					{
561 						Scanline pReadScan = pReadAcc->GetScanline( nY );
562 						Scanline pWriteScan = pWriteAcc->GetScanline( nY );
563 
564 						for( long nX = 0L; nX < nWidth; nX++ )
565 						{
566 							const sal_uLong nB = *pReadScan++;
567 							const sal_uLong nG = *pReadScan++;
568 							const sal_uLong nR = *pReadScan++;
569 
570 							*pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
571 						}
572 					}
573 				}
574 				else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
575 						 pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
576 				{
577 					nShift += 8;
578 
579 					for( long nY = 0L; nY < nHeight; nY++ )
580 					{
581 						Scanline pReadScan = pReadAcc->GetScanline( nY );
582 						Scanline pWriteScan = pWriteAcc->GetScanline( nY );
583 
584 						for( long nX = 0L; nX < nWidth; nX++ )
585 						{
586 							const sal_uLong nR = *pReadScan++;
587 							const sal_uLong nG = *pReadScan++;
588 							const sal_uLong nB = *pReadScan++;
589 
590 							*pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
591 						}
592 					}
593 				}
594 				else
595 				{
596 					for( long nY = 0L; nY < nHeight; nY++ )
597 						for( long nX = 0L; nX < nWidth; nX++ )
598 							pWriteAcc->SetPixel( nY, nX, sal::static_int_cast<sal_uInt8>(( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift) );
599 				}
600 
601 				aNewBmp.ReleaseAccess( pWriteAcc );
602 				bRet = sal_True;
603 			}
604 
605 			ReleaseAccess( pReadAcc );
606 
607 			if( bRet )
608 			{
609 				const MapMode	aMap( maPrefMapMode );
610 				const Size		aSize( maPrefSize );
611 
612 				*this = aNewBmp;
613 
614 				maPrefMapMode = aMap;
615 				maPrefSize = aSize;
616 			}
617 		}
618 		else
619 		{
620 			ReleaseAccess( pReadAcc );
621 			bRet = sal_True;
622 		}
623 	}
624 
625 	return bRet;
626 }
627 
628 // ------------------------------------------------------------------------
629 
630 sal_Bool Bitmap::ImplConvertUp( sal_uInt16 nBitCount, Color* pExtColor )
631 {
632 	DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
633 
634 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
635 	sal_Bool				bRet = sal_False;
636 
637 	if( pReadAcc )
638 	{
639 		BitmapPalette		aPal;
640 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPal );
641 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
642 
643 		if( pWriteAcc )
644 		{
645 			const long	nWidth = pWriteAcc->Width();
646 			const long	nHeight = pWriteAcc->Height();
647 
648 			if( pWriteAcc->HasPalette() )
649 			{
650 				const sal_uInt16			nOldCount = 1 << GetBitCount();
651 				const BitmapPalette&	rOldPal = pReadAcc->GetPalette();
652 
653 				aPal.SetEntryCount( 1 << nBitCount );
654 
655 				for( sal_uInt16 i = 0; i < nOldCount; i++ )
656 					aPal[ i ] = rOldPal[ i ];
657 
658 				if( pExtColor )
659 					aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
660 
661 				pWriteAcc->SetPalette( aPal );
662 
663 				for( long nY = 0L; nY < nHeight; nY++ )
664 					for( long nX = 0L; nX < nWidth; nX++ )
665 						pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
666 			}
667 			else
668 			{
669 				if( pReadAcc->HasPalette() )
670 				{
671 					for( long nY = 0L; nY < nHeight; nY++ )
672 						for( long nX = 0L; nX < nWidth; nX++ )
673 							pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
674 				}
675 				else
676 				{
677 					for( long nY = 0L; nY < nHeight; nY++ )
678 						for( long nX = 0L; nX < nWidth; nX++ )
679 							pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
680 				}
681 			}
682 
683 			aNewBmp.ReleaseAccess( pWriteAcc );
684 			bRet = sal_True;
685 		}
686 
687 		ReleaseAccess( pReadAcc );
688 
689 		if( bRet )
690 		{
691 			const MapMode	aMap( maPrefMapMode );
692 			const Size		aSize( maPrefSize );
693 
694 			*this = aNewBmp;
695 
696 			maPrefMapMode = aMap;
697 			maPrefSize = aSize;
698 		}
699 	}
700 
701 	return bRet;
702 }
703 
704 // ------------------------------------------------------------------------
705 
706 sal_Bool Bitmap::ImplConvertDown( sal_uInt16 nBitCount, Color* pExtColor )
707 {
708 	DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
709 
710 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
711 	sal_Bool				bRet = sal_False;
712 
713 	if( pReadAcc )
714 	{
715 		BitmapPalette		aPal;
716 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, &aPal );
717 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
718 
719 		if( pWriteAcc )
720 		{
721 			const sal_uInt16	nCount = 1 << nBitCount;
722 			const long		nWidth = pWriteAcc->Width();
723 			const long		nWidth1 = nWidth - 1L;
724 			const long		nHeight = pWriteAcc->Height();
725 			Octree			aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
726 			InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
727 			BitmapColor 	aColor;
728 			ImpErrorQuad	aErrQuad;
729 			ImpErrorQuad*	pErrQuad1 = new ImpErrorQuad[ nWidth ];
730 			ImpErrorQuad*	pErrQuad2 = new ImpErrorQuad[ nWidth ];
731 			ImpErrorQuad*	pQLine1 = pErrQuad1;
732 			ImpErrorQuad*	pQLine2 = 0;
733 			long			nX, nY;
734 			long			nYTmp = 0L;
735 			sal_uInt8			cIndex;
736 			sal_Bool			bQ1 = sal_True;
737 
738 			if( pExtColor )
739 			{
740 				aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
741 				aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
742 			}
743 
744 			// set Black/White always, if we have enough space
745 			if( aPal.GetEntryCount() < ( nCount - 1 ) )
746 			{
747 				aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
748 				aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
749 				aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
750 			}
751 
752 			pWriteAcc->SetPalette( aPal );
753 
754 			for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
755 			{
756 				for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
757 				{
758 					if( pReadAcc->HasPalette() )
759 						pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
760 					else
761 						pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
762 				}
763 			}
764 
765 			for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
766 			{
767 				// erstes ZeilenPixel
768 				cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
769 				pWriteAcc->SetPixel( nY, 0, cIndex );
770 
771 				for( nX = 1L; nX < nWidth1; nX++ )
772 				{
773 					cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
774 					aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
775 					pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
776 					pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
777 					pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
778 					pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
779 					pWriteAcc->SetPixel( nY, nX, cIndex );
780 				}
781 
782 				// letztes ZeilenPixel
783                 if( nX < nWidth )
784                 {
785 				    cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
786 				    pWriteAcc->SetPixel( nY, nX, cIndex );
787                 }
788 
789 				// Zeilenpuffer neu fuellen/kopieren
790 				pQLine1 = pQLine2;
791 				pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
792 
793 				if( nYTmp < nHeight )
794 				{
795 					for( nX = 0L; nX < nWidth; nX++ )
796 					{
797 						if( pReadAcc->HasPalette() )
798 								pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
799 						else
800 							pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
801 					}
802 				}
803 			}
804 
805 			// Zeilenpuffer zerstoeren
806 			delete[] pErrQuad1;
807 			delete[] pErrQuad2;
808 
809 			aNewBmp.ReleaseAccess( pWriteAcc );
810 			bRet = sal_True;
811 		}
812 
813 		ReleaseAccess( pReadAcc );
814 
815 		if( bRet )
816 		{
817 			const MapMode	aMap( maPrefMapMode );
818 			const Size		aSize( maPrefSize );
819 
820 			*this = aNewBmp;
821 
822 			maPrefMapMode = aMap;
823 			maPrefSize = aSize;
824 		}
825 	}
826 
827 	return bRet;
828 }
829 
830 // ------------------------------------------------------------------------
831 
832 sal_Bool Bitmap::ImplConvertGhosted()
833 {
834 	Bitmap				aNewBmp;
835 	BitmapReadAccess*	pR = AcquireReadAccess();
836 	sal_Bool				bRet = sal_False;
837 
838 	if( pR )
839 	{
840 		if( pR->HasPalette() )
841 		{
842 			BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
843 
844 			for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
845 			{
846 				const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i );
847 				aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
848 													 ( rOld.GetGreen() >> 1 ) | 0x80,
849 													 ( rOld.GetBlue() >> 1 ) | 0x80 );
850 			}
851 
852 			aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
853 			BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
854 
855 			if( pW )
856 			{
857 				pW->CopyBuffer( *pR );
858 				aNewBmp.ReleaseAccess( pW );
859 				bRet = sal_True;
860 			}
861 		}
862 		else
863 		{
864 			aNewBmp = Bitmap( GetSizePixel(), 24 );
865 
866 			BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
867 
868 			if( pW )
869 			{
870 				const long nWidth = pR->Width(), nHeight = pR->Height();
871 
872 				for( long nY = 0; nY < nHeight; nY++ )
873 				{
874 					for( long nX = 0; nX < nWidth; nX++ )
875 					{
876 						const BitmapColor aOld( pR->GetPixel( nY, nX ) );
877 						pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
878 														   ( aOld.GetGreen() >> 1 ) | 0x80,
879 														   ( aOld.GetBlue() >> 1 ) | 0x80 ) );
880 
881 					}
882 				}
883 
884 				aNewBmp.ReleaseAccess( pW );
885 				bRet = sal_True;
886 			}
887 		}
888 
889 		ReleaseAccess( pR );
890 	}
891 
892 	if( bRet )
893 	{
894 		const MapMode	aMap( maPrefMapMode );
895 		const Size		aSize( maPrefSize );
896 
897 		*this = aNewBmp;
898 
899 		maPrefMapMode = aMap;
900 		maPrefSize = aSize;
901 	}
902 
903 	return bRet;
904 }
905 
906 // ------------------------------------------------------------------------
907 
908 sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
909 {
910 	sal_Bool bRet;
911 
912 	if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) )
913 	{
914 		if( BMP_SCALE_FAST == nScaleFlag )
915 			bRet = ImplScaleFast( rScaleX, rScaleY );
916 		else if( BMP_SCALE_INTERPOLATE == nScaleFlag )
917 			bRet = ImplScaleInterpolate( rScaleX, rScaleY );
918 		else
919 			bRet = sal_False;
920 	}
921 	else
922 		bRet = sal_True;
923 
924 	return bRet;
925 }
926 
927 // ------------------------------------------------------------------------
928 
929 sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
930 {
931 	const Size	aSize( GetSizePixel() );
932 	sal_Bool		bRet;
933 
934 	if( aSize.Width() && aSize.Height() )
935 	{
936 		bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
937 					  (double) rNewSize.Height() / aSize.Height(),
938 					  nScaleFlag );
939 	}
940 	else
941 		bRet = sal_True;
942 
943 	return bRet;
944 }
945 
946 // ------------------------------------------------------------------------
947 
948 sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
949 {
950 	const Size	aSizePix( GetSizePixel() );
951 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
952 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
953 	sal_Bool		bRet = sal_False;
954 
955 	if( nNewWidth && nNewHeight )
956 	{
957 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
958 		Bitmap				aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
959 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
960 
961 		if( pReadAcc && pWriteAcc )
962 		{
963 			const long	nScanlineSize = pWriteAcc->GetScanlineSize();
964 			const long	nNewWidth1 = nNewWidth - 1L;
965 			const long	nNewHeight1 = nNewHeight - 1L;
966 			const long	nWidth = pReadAcc->Width();
967 			const long	nHeight = pReadAcc->Height();
968 			long*		pLutX = new long[ nNewWidth ];
969 			long*		pLutY = new long[ nNewHeight ];
970 			long		nX, nY, nMapY, nActY = 0L;
971 
972 			if( nNewWidth1 && nNewHeight1 )
973 			{
974 				for( nX = 0L; nX < nNewWidth; nX++ )
975 					pLutX[ nX ] = nX * nWidth / nNewWidth;
976 
977 				for( nY = 0L; nY < nNewHeight; nY++ )
978 					pLutY[ nY ] = nY * nHeight / nNewHeight;
979 
980 				while( nActY < nNewHeight )
981 				{
982 					nMapY = pLutY[ nActY ];
983 
984 					for( nX = 0L; nX < nNewWidth; nX++ )
985 						pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
986 
987 					while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
988 					{
989 						memcpy( pWriteAcc->GetScanline( nActY + 1L ),
990 								 pWriteAcc->GetScanline( nActY ), nScanlineSize );
991 						nActY++;
992 					}
993 
994 					nActY++;
995 				}
996 
997 				bRet = sal_True;
998 			}
999 
1000 			delete[] pLutX;
1001 			delete[] pLutY;
1002 		}
1003 
1004 		ReleaseAccess( pReadAcc );
1005 		aNewBmp.ReleaseAccess( pWriteAcc );
1006 
1007 		if( bRet )
1008 			ImplAssignWithSize( aNewBmp );
1009 	}
1010 
1011 	return bRet;
1012 }
1013 
1014 // ------------------------------------------------------------------------
1015 
1016 sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1017 {
1018 	const Size	aSizePix( GetSizePixel() );
1019 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
1020 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
1021 	sal_Bool		bRet = sal_False;
1022 
1023 	if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1024 	{
1025 		BitmapColor 		aCol0;
1026 		BitmapColor 		aCol1;
1027 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1028 		long				nWidth = pReadAcc->Width();
1029 		long				nHeight = pReadAcc->Height();
1030 		Bitmap				aNewBmp( Size( nNewWidth, nHeight ), 24 );
1031 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1032 		long*				pLutInt;
1033 		long*				pLutFrac;
1034 		long				nX, nY;
1035 		long				lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1036 		double				fTemp;
1037 		long				nTemp;
1038 
1039 		if( pReadAcc && pWriteAcc )
1040 		{
1041 			const long		nNewWidth1 = nNewWidth - 1L;
1042 			const long		nWidth1 = pReadAcc->Width() - 1L;
1043 			const double	fRevScaleX = (double) nWidth1 / nNewWidth1;
1044 
1045 			pLutInt = new long[ nNewWidth ];
1046 			pLutFrac = new long[ nNewWidth ];
1047 
1048 			for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1049 			{
1050 				fTemp = nX * fRevScaleX;
1051 				pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1052 				fTemp -= pLutInt[ nX ];
1053 				pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1054 			}
1055 
1056 			if( pReadAcc->HasPalette() )
1057 			{
1058 				for( nY = 0L; nY < nHeight; nY++ )
1059 				{
1060 					if( 1 == nWidth )
1061 					{
1062 						aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, 0 ) );
1063 
1064 						for( nX = 0L; nX < nNewWidth; nX++ )
1065 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1066 					}
1067 					else
1068 					{
1069 						for( nX = 0L; nX < nNewWidth; nX++ )
1070 						{
1071 							nTemp = pLutInt[ nX ];
1072 
1073 							aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp++ ) );
1074 							aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp ) );
1075 
1076 							nTemp = pLutFrac[ nX ];
1077 
1078 							lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1079 							lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1080 							lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1081 
1082 							aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1083 							aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1084 							aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1085 
1086 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1087 						}
1088 					}
1089 				}
1090 			}
1091 			else
1092 			{
1093 				for( nY = 0L; nY < nHeight; nY++ )
1094 				{
1095 					if( 1 == nWidth )
1096 					{
1097 						aCol0 = pReadAcc->GetPixel( nY, 0 );
1098 
1099 						for( nX = 0L; nX < nNewWidth; nX++ )
1100 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1101 					}
1102 					else
1103 					{
1104 						for( nX = 0L; nX < nNewWidth; nX++ )
1105 						{
1106 							nTemp = pLutInt[ nX ];
1107 
1108 							aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1109 							aCol1 = pReadAcc->GetPixel( nY, nTemp );
1110 
1111 							nTemp = pLutFrac[ nX ];
1112 
1113 							lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1114 							lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1115 							lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1116 
1117 							aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1118 							aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1119 							aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1120 
1121 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1122 						}
1123 					}
1124 				}
1125 			}
1126 
1127 			delete[] pLutInt;
1128 			delete[] pLutFrac;
1129 			bRet = sal_True;
1130 		}
1131 
1132 		ReleaseAccess( pReadAcc );
1133 		aNewBmp.ReleaseAccess( pWriteAcc );
1134 
1135 		if( bRet )
1136 		{
1137 			bRet = sal_False;
1138 			ImplAssignWithSize( aNewBmp );
1139 			pReadAcc = AcquireReadAccess();
1140 			aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1141 			pWriteAcc = aNewBmp.AcquireWriteAccess();
1142 
1143 			if( pReadAcc && pWriteAcc )
1144 			{
1145 				const long		nNewHeight1 = nNewHeight - 1L;
1146 				const long		nHeight1 = pReadAcc->Height() - 1L;
1147 				const double	fRevScaleY = (double) nHeight1 / nNewHeight1;
1148 
1149 				pLutInt = new long[ nNewHeight ];
1150 				pLutFrac = new long[ nNewHeight ];
1151 
1152 				for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1153 				{
1154 					fTemp = nY * fRevScaleY;
1155 					pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1156 					fTemp -= pLutInt[ nY ];
1157 					pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1158 				}
1159 
1160 				if( pReadAcc->HasPalette() )
1161 				{
1162 					for( nX = 0L; nX < nNewWidth; nX++ )
1163 					{
1164 						if( 1 == nHeight )
1165 						{
1166 							aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nX ) );
1167 
1168 							for( nY = 0L; nY < nNewHeight; nY++ )
1169 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1170 						}
1171 						else
1172 						{
1173 							for( nY = 0L; nY < nNewHeight; nY++ )
1174 							{
1175 								nTemp = pLutInt[ nY ];
1176 
1177 								aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp++, nX ) );
1178 								aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp, nX ) );
1179 
1180 								nTemp = pLutFrac[ nY ];
1181 
1182 								lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1183 								lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1184 								lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1185 
1186 								aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1187 								aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1188 								aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1189 
1190 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1191 							}
1192 						}
1193 					}
1194 				}
1195 				else
1196 				{
1197 					for( nX = 0L; nX < nNewWidth; nX++ )
1198 					{
1199 						if( 1 == nHeight )
1200 						{
1201 							aCol0 = pReadAcc->GetPixel( 0, nX );
1202 
1203 							for( nY = 0L; nY < nNewHeight; nY++ )
1204 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1205 						}
1206 						else
1207 						{
1208 							for( nY = 0L; nY < nNewHeight; nY++ )
1209 							{
1210 								nTemp = pLutInt[ nY ];
1211 
1212 								aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1213 								aCol1 = pReadAcc->GetPixel( nTemp, nX );
1214 
1215 								nTemp = pLutFrac[ nY ];
1216 
1217 								lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1218 								lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1219 								lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1220 
1221 								aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1222 								aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1223 								aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1224 
1225 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1226 							}
1227 						}
1228 					}
1229 				}
1230 
1231 				delete[] pLutInt;
1232 				delete[] pLutFrac;
1233 				bRet = sal_True;
1234 			}
1235 
1236 			ReleaseAccess( pReadAcc );
1237 			aNewBmp.ReleaseAccess( pWriteAcc );
1238 
1239 			if( bRet )
1240 				ImplAssignWithSize( aNewBmp );
1241 		}
1242 	}
1243 
1244 	if( !bRet )
1245 		bRet = ImplScaleFast( rScaleX, rScaleY );
1246 
1247 	return bRet;
1248 }
1249 
1250 // ------------------------------------------------------------------------
1251 
1252 sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
1253 {
1254 	sal_Bool bRet = sal_False;
1255 
1256 	const Size aSizePix( GetSizePixel() );
1257 
1258 	if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
1259 		bRet = sal_True;
1260 	else if( nDitherFlags & BMP_DITHER_MATRIX )
1261 		bRet = ImplDitherMatrix();
1262 	else if( nDitherFlags & BMP_DITHER_FLOYD )
1263 		bRet = ImplDitherFloyd();
1264 	else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
1265 		bRet = ImplDitherFloyd16();
1266 
1267 	return bRet;
1268 }
1269 
1270 // ------------------------------------------------------------------------
1271 
1272 sal_Bool Bitmap::ImplDitherMatrix()
1273 {
1274 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1275 	Bitmap				aNewBmp( GetSizePixel(), 8 );
1276 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1277 	sal_Bool				bRet = sal_False;
1278 
1279 	if( pReadAcc && pWriteAcc )
1280 	{
1281 		const sal_uLong	nWidth = pReadAcc->Width();
1282 		const sal_uLong	nHeight = pReadAcc->Height();
1283 		BitmapColor	aIndex( (sal_uInt8) 0 );
1284 
1285 		if( pReadAcc->HasPalette() )
1286 		{
1287 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
1288 			{
1289 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
1290 				{
1291 					const BitmapColor	aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
1292 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
1293 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
1294 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
1295 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
1296 
1297 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
1298 					pWriteAcc->SetPixel( nY, nX, aIndex );
1299 				}
1300 			}
1301 		}
1302 		else
1303 		{
1304 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
1305 			{
1306 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
1307 				{
1308 					const BitmapColor	aCol( pReadAcc->GetPixel( nY, nX ) );
1309 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
1310 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
1311 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
1312 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
1313 
1314 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
1315 					pWriteAcc->SetPixel( nY, nX, aIndex );
1316 				}
1317 			}
1318 		}
1319 
1320 		bRet = sal_True;
1321 	}
1322 
1323 	ReleaseAccess( pReadAcc );
1324 	aNewBmp.ReleaseAccess( pWriteAcc );
1325 
1326 	if( bRet )
1327 	{
1328 		const MapMode	aMap( maPrefMapMode );
1329 		const Size		aSize( maPrefSize );
1330 
1331 		*this = aNewBmp;
1332 
1333 		maPrefMapMode = aMap;
1334 		maPrefSize = aSize;
1335 	}
1336 
1337 	return bRet;
1338 }
1339 
1340 // ------------------------------------------------------------------------
1341 
1342 sal_Bool Bitmap::ImplDitherFloyd()
1343 {
1344 	const Size	aSize( GetSizePixel() );
1345 	sal_Bool		bRet = sal_False;
1346 
1347 	if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
1348 	{
1349 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1350 		Bitmap				aNewBmp( GetSizePixel(), 8 );
1351 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1352 
1353 		if( pReadAcc && pWriteAcc )
1354 		{
1355 			BitmapColor	aColor;
1356 			long		nWidth = pReadAcc->Width();
1357 			long		nWidth1 = nWidth - 1L;
1358 			long		nHeight = pReadAcc->Height();
1359 			long		nX;
1360 			long		nW = nWidth * 3L;
1361 			long		nW2 = nW - 3L;
1362 			long		nRErr, nGErr, nBErr;
1363 			long		nRC, nGC, nBC;
1364 			long		nTemp;
1365 			long		nZ;
1366 			long*		p1 = new long[ nW ];
1367 			long*		p2 = new long[ nW ];
1368 			long*		p1T = p1;
1369 			long*		p2T = p2;
1370 			long*		pTmp;
1371 			sal_Bool		bPal = pReadAcc->HasPalette();
1372 
1373 			pTmp = p2T;
1374 
1375 			if( bPal )
1376 			{
1377 				for( nZ = 0; nZ < nWidth; nZ++ )
1378 				{
1379 					aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nZ ) );
1380 
1381 					*pTmp++ = (long) aColor.GetBlue() << 12;
1382 					*pTmp++ = (long) aColor.GetGreen() << 12;
1383 					*pTmp++ = (long) aColor.GetRed() << 12;
1384 				}
1385 			}
1386 			else
1387 			{
1388 				for( nZ = 0; nZ < nWidth; nZ++ )
1389 				{
1390 					aColor = pReadAcc->GetPixel( 0, nZ );
1391 
1392 					*pTmp++ = (long) aColor.GetBlue() << 12;
1393 					*pTmp++ = (long) aColor.GetGreen() << 12;
1394 					*pTmp++ = (long) aColor.GetRed() << 12;
1395 				}
1396 			}
1397 
1398 			for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
1399 			{
1400 				pTmp = p1T;
1401 				p1T = p2T;
1402 				p2T = pTmp;
1403 
1404 				if( nY < nHeight )
1405 				{
1406 					if( bPal )
1407 					{
1408 						for( nZ = 0; nZ < nWidth; nZ++ )
1409 						{
1410 							aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nZ ) );
1411 
1412 							*pTmp++ = (long) aColor.GetBlue() << 12;
1413 							*pTmp++ = (long) aColor.GetGreen() << 12;
1414 							*pTmp++ = (long) aColor.GetRed() << 12;
1415 						}
1416 					}
1417 					else
1418 					{
1419 						for( nZ = 0; nZ < nWidth; nZ++ )
1420 						{
1421 							aColor = pReadAcc->GetPixel( nY, nZ );
1422 
1423 							*pTmp++ = (long) aColor.GetBlue() << 12;
1424 							*pTmp++ = (long) aColor.GetGreen() << 12;
1425 							*pTmp++ = (long) aColor.GetRed() << 12;
1426 						}
1427 					}
1428 				}
1429 
1430 				// erstes Pixel gesondert betrachten
1431 				nX = 0;
1432 				CALC_ERRORS;
1433 				CALC_TABLES7;
1434 				nX -= 5;
1435 				CALC_TABLES5;
1436 				pWriteAcc->SetPixel( nYAcc, 0, BitmapColor( (sal_uInt8) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
1437 
1438 				// mittlere Pixel ueber Schleife
1439 				long nXAcc;
1440 				for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
1441 				{
1442 					CALC_ERRORS;
1443 					CALC_TABLES7;
1444 					nX -= 8;
1445 					CALC_TABLES3;
1446 					CALC_TABLES5;
1447 					pWriteAcc->SetPixel( nYAcc, nXAcc, BitmapColor( (sal_uInt8) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
1448 				}
1449 
1450 				// letztes Pixel gesondert betrachten
1451 				CALC_ERRORS;
1452 				nX -= 5;
1453 				CALC_TABLES3;
1454 				CALC_TABLES5;
1455 				pWriteAcc->SetPixel( nYAcc, nWidth1, BitmapColor( (sal_uInt8) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
1456 			}
1457 
1458 			delete[] p1;
1459 			delete[] p2;
1460 			bRet = sal_True;
1461 		}
1462 
1463 		ReleaseAccess( pReadAcc );
1464 		aNewBmp.ReleaseAccess( pWriteAcc );
1465 
1466 		if( bRet )
1467 		{
1468 			const MapMode	aMap( maPrefMapMode );
1469 			const Size		aPrefSize( maPrefSize );
1470 
1471 			*this = aNewBmp;
1472 
1473 			maPrefMapMode = aMap;
1474 			maPrefSize = aPrefSize;
1475 		}
1476 	}
1477 
1478 	return bRet;
1479 }
1480 
1481 // ------------------------------------------------------------------------
1482 
1483 sal_Bool Bitmap::ImplDitherFloyd16()
1484 {
1485 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1486 	Bitmap				aNewBmp( GetSizePixel(), 24 );
1487 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1488 	sal_Bool				bRet = sal_False;
1489 
1490 	if( pReadAcc && pWriteAcc )
1491 	{
1492 		const long		nWidth = pWriteAcc->Width();
1493 		const long		nWidth1 = nWidth - 1L;
1494 		const long		nHeight = pWriteAcc->Height();
1495 		BitmapColor 	aColor;
1496 		BitmapColor		aBestCol;
1497 		ImpErrorQuad	aErrQuad;
1498 		ImpErrorQuad*	pErrQuad1 = new ImpErrorQuad[ nWidth ];
1499 		ImpErrorQuad*	pErrQuad2 = new ImpErrorQuad[ nWidth ];
1500 		ImpErrorQuad*	pQLine1 = pErrQuad1;
1501 		ImpErrorQuad*	pQLine2 = 0;
1502 		long			nX, nY;
1503 		long			nYTmp = 0L;
1504 		sal_Bool			bQ1 = sal_True;
1505 
1506 		for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
1507 			for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
1508 				pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
1509 
1510 		for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
1511 		{
1512 			// erstes ZeilenPixel
1513 			aBestCol = pQLine1[ 0 ].ImplGetColor();
1514 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
1515 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
1516 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
1517 			pWriteAcc->SetPixel( nY, 0, aBestCol );
1518 
1519 			for( nX = 1L; nX < nWidth1; nX++ )
1520 			{
1521 				aColor = pQLine1[ nX ].ImplGetColor();
1522 				aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
1523 				aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
1524 				aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
1525 				aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
1526 				pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
1527 				pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
1528 				pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
1529 				pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
1530 				pWriteAcc->SetPixel( nY, nX, aBestCol );
1531 			}
1532 
1533 			// letztes ZeilenPixel
1534 			aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
1535 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
1536 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
1537 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
1538 			pWriteAcc->SetPixel( nY, nX, aBestCol );
1539 
1540 			// Zeilenpuffer neu fuellen/kopieren
1541 			pQLine1 = pQLine2;
1542 			pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
1543 
1544 			if( nYTmp < nHeight )
1545 				for( nX = 0L; nX < nWidth; nX++ )
1546 					pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
1547 		}
1548 
1549 		// Zeilenpuffer zerstoeren
1550 		delete[] pErrQuad1;
1551 		delete[] pErrQuad2;
1552 		bRet = sal_True;
1553 	}
1554 
1555 	ReleaseAccess( pReadAcc );
1556 	aNewBmp.ReleaseAccess( pWriteAcc );
1557 
1558 	if( bRet )
1559 	{
1560 		const MapMode	aMap( maPrefMapMode );
1561 		const Size		aSize( maPrefSize );
1562 
1563 		*this = aNewBmp;
1564 
1565 		maPrefMapMode = aMap;
1566 		maPrefSize = aSize;
1567 	}
1568 
1569 	return bRet;
1570 }
1571 
1572 // ------------------------------------------------------------------------
1573 
1574 sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
1575 {
1576 	sal_Bool bRet;
1577 
1578 	if( GetColorCount() <= (sal_uLong) nColorCount )
1579 		bRet = sal_True;
1580 	else if( nColorCount )
1581 	{
1582 		if( BMP_REDUCE_SIMPLE == eReduce )
1583 			bRet = ImplReduceSimple( nColorCount );
1584 		else if( BMP_REDUCE_POPULAR == eReduce )
1585 			bRet = ImplReducePopular( nColorCount );
1586 		else
1587 			bRet = ImplReduceMedian( nColorCount );
1588 	}
1589 	else
1590 		bRet = sal_False;
1591 
1592 	return bRet;
1593 }
1594 
1595 // ------------------------------------------------------------------------
1596 
1597 sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
1598 {
1599 	Bitmap				aNewBmp;
1600 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
1601 	const sal_uInt16		nColCount = Min( nColorCount, (sal_uInt16) 256 );
1602 	sal_uInt16				nBitCount;
1603 	sal_Bool				bRet = sal_False;
1604 
1605 	if( nColCount <= 2 )
1606 		nBitCount = 1;
1607 	else if( nColCount <= 16 )
1608 		nBitCount = 4;
1609 	else
1610 		nBitCount = 8;
1611 
1612 	if( pRAcc )
1613 	{
1614 		Octree					aOct( *pRAcc, nColCount );
1615 		const BitmapPalette&	rPal = aOct.GetPalette();
1616 		BitmapWriteAccess*		pWAcc;
1617 
1618 		aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
1619 		pWAcc = aNewBmp.AcquireWriteAccess();
1620 
1621 		if( pWAcc )
1622 		{
1623 			const long nWidth = pRAcc->Width();
1624 			const long nHeight = pRAcc->Height();
1625 
1626 			if( pRAcc->HasPalette() )
1627 			{
1628 				for( long nY = 0L; nY < nHeight; nY++ )
1629 					for( long nX =0L; nX < nWidth; nX++ )
1630 						pWAcc->SetPixel( nY, nX, (sal_uInt8) aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) ) ) );
1631 			}
1632 			else
1633 			{
1634 				for( long nY = 0L; nY < nHeight; nY++ )
1635 					for( long nX =0L; nX < nWidth; nX++ )
1636 						pWAcc->SetPixel( nY, nX, (sal_uInt8) aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) ) );
1637 			}
1638 
1639 			aNewBmp.ReleaseAccess( pWAcc );
1640 			bRet = sal_True;
1641 		}
1642 
1643 		ReleaseAccess( pRAcc );
1644 	}
1645 
1646 	if( bRet )
1647 	{
1648 		const MapMode	aMap( maPrefMapMode );
1649 		const Size		aSize( maPrefSize );
1650 
1651 		*this = aNewBmp;
1652 		maPrefMapMode = aMap;
1653 		maPrefSize = aSize;
1654 	}
1655 
1656 	return bRet;
1657 }
1658 
1659 // ------------------------------------------------------------------------
1660 
1661 struct PopularColorCount
1662 {
1663 	sal_uInt32	mnIndex;
1664 	sal_uInt32	mnCount;
1665 };
1666 
1667 // ------------------------------------------------------------------------
1668 
1669 extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
1670 {
1671 	int nRet;
1672 
1673 	if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
1674 		nRet = 1;
1675 	else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
1676 		nRet = 0;
1677 	else
1678 		nRet = -1;
1679 
1680 	return nRet;
1681 }
1682 
1683 // ------------------------------------------------------------------------
1684 
1685 sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
1686 {
1687 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
1688 	sal_uInt16				nBitCount;
1689 	sal_Bool				bRet = sal_False;
1690 
1691 	if( nColCount > 256 )
1692 		nColCount = 256;
1693 
1694 	if( nColCount < 17 )
1695 		nBitCount = 4;
1696 	else
1697 		nBitCount = 8;
1698 
1699 	if( pRAcc )
1700 	{
1701 		const sal_uInt32	nValidBits = 4;
1702 		const sal_uInt32	nRightShiftBits = 8 - nValidBits;
1703 		const sal_uInt32	nLeftShiftBits1 = nValidBits;
1704 		const sal_uInt32	nLeftShiftBits2 = nValidBits << 1;
1705 		const sal_uInt32	nColorsPerComponent = 1 << nValidBits;
1706 		const sal_uInt32	nColorOffset = 256 / nColorsPerComponent;
1707 		const sal_uInt32	nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
1708 		const long			nWidth = pRAcc->Width();
1709 		const long			nHeight = pRAcc->Height();
1710 		PopularColorCount*	pCountTable = new PopularColorCount[ nTotalColors ];
1711 		long				nX, nY, nR, nG, nB, nIndex;
1712 
1713 		rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
1714 
1715 		for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
1716         {
1717 			for( nG = 0; nG < 256; nG += nColorOffset )
1718             {
1719 				for( nB = 0; nB < 256; nB += nColorOffset )
1720                 {
1721 					pCountTable[ nIndex ].mnIndex = nIndex;
1722                     nIndex++;
1723                 }
1724             }
1725         }
1726 
1727 		if( pRAcc->HasPalette() )
1728 		{
1729 			for( nY = 0L; nY < nHeight; nY++ )
1730 			{
1731 				for( nX = 0L; nX < nWidth; nX++ )
1732 				{
1733 					const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
1734 					pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1735 								 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1736 								 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
1737 				}
1738 			}
1739 		}
1740 		else
1741 		{
1742 			for( nY = 0L; nY < nHeight; nY++ )
1743 			{
1744 				for( nX = 0L; nX < nWidth; nX++ )
1745 				{
1746 					const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
1747 					pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1748 								 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1749 								 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
1750 				}
1751 			}
1752 		}
1753 
1754 		BitmapPalette aNewPal( nColCount );
1755 
1756 		qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
1757 
1758 		for( sal_uInt16 n = 0; n < nColCount; n++ )
1759 		{
1760 			const PopularColorCount& rPop = pCountTable[ n ];
1761 			aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
1762 										(sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
1763 										(sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
1764 		}
1765 
1766 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
1767 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
1768 
1769 		if( pWAcc )
1770 		{
1771 			BitmapColor	aDstCol( (sal_uInt8) 0 );
1772 			sal_uInt8*		pIndexMap = new sal_uInt8[ nTotalColors ];
1773 
1774 			for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
1775 				for( nG = 0; nG < 256; nG += nColorOffset )
1776 					for( nB = 0; nB < 256; nB += nColorOffset )
1777 						pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
1778 
1779 			if( pRAcc->HasPalette() )
1780 			{
1781 				for( nY = 0L; nY < nHeight; nY++ )
1782 				{
1783 					for( nX = 0L; nX < nWidth; nX++ )
1784 					{
1785 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
1786 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1787 													 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1788 													 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
1789 						pWAcc->SetPixel( nY, nX, aDstCol );
1790 					}
1791 				}
1792 			}
1793 			else
1794 			{
1795 				for( nY = 0L; nY < nHeight; nY++ )
1796 				{
1797 					for( nX = 0L; nX < nWidth; nX++ )
1798 					{
1799 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
1800 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1801 													 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1802 													 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
1803 						pWAcc->SetPixel( nY, nX, aDstCol );
1804 					}
1805 				}
1806 			}
1807 
1808 			delete[] pIndexMap;
1809 			aNewBmp.ReleaseAccess( pWAcc );
1810 			bRet = sal_True;
1811 		}
1812 
1813 		delete[] pCountTable;
1814 		ReleaseAccess( pRAcc );
1815 
1816 		if( bRet )
1817 		{
1818 			const MapMode	aMap( maPrefMapMode );
1819 			const Size		aSize( maPrefSize );
1820 
1821 			*this = aNewBmp;
1822 			maPrefMapMode = aMap;
1823 			maPrefSize = aSize;
1824 		}
1825 	}
1826 
1827 	return bRet;
1828 }
1829 
1830 // ------------------------------------------------------------------------
1831 
1832 sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
1833 {
1834 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
1835 	sal_uInt16				nBitCount;
1836 	sal_Bool				bRet = sal_False;
1837 
1838 	if( nColCount < 17 )
1839 		nBitCount = 4;
1840 	else if( nColCount < 257 )
1841 		nBitCount = 8;
1842 	else
1843 	{
1844 		DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
1845 		nBitCount = 8;
1846 		nColCount = 256;
1847 	}
1848 
1849 	if( pRAcc )
1850 	{
1851 		Bitmap				aNewBmp( GetSizePixel(), nBitCount );
1852 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
1853 
1854 		if( pWAcc )
1855 		{
1856 			const sal_uLong	nSize = 32768UL * sizeof( sal_uLong );
1857 			sal_uLong*		pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
1858 			const long	nWidth = pWAcc->Width();
1859 			const long	nHeight = pWAcc->Height();
1860 			long		nIndex = 0L;
1861 
1862 			memset( (HPBYTE) pColBuf, 0, nSize );
1863 
1864 			// create Buffer
1865 			if( pRAcc->HasPalette() )
1866 			{
1867 				for( long nY = 0L; nY < nHeight; nY++ )
1868 				{
1869 					for( long nX = 0L; nX < nWidth; nX++ )
1870 					{
1871 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
1872 						pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
1873 					}
1874 				}
1875 			}
1876 			else
1877 			{
1878 				for( long nY = 0L; nY < nHeight; nY++ )
1879 				{
1880 					for( long nX = 0L; nX < nWidth; nX++ )
1881 					{
1882 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
1883 						pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
1884 					}
1885 				}
1886 			}
1887 
1888 			// create palette via median cut
1889 			BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
1890 			ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
1891 						   nColCount, nWidth * nHeight, nIndex );
1892 
1893 			// do mapping of colors to palette
1894 			InverseColorMap aMap( aPal );
1895 			pWAcc->SetPalette( aPal );
1896 			for( long nY = 0L; nY < nHeight; nY++ )
1897 				for( long nX = 0L; nX < nWidth; nX++ )
1898 					pWAcc->SetPixel( nY, nX, (sal_uInt8) aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) ) );
1899 
1900 			rtl_freeMemory( pColBuf );
1901 			aNewBmp.ReleaseAccess( pWAcc );
1902 			bRet = sal_True;
1903 		}
1904 
1905 		ReleaseAccess( pRAcc );
1906 
1907 		if( bRet )
1908 		{
1909 			const MapMode	aMap( maPrefMapMode );
1910 			const Size		aSize( maPrefSize );
1911 
1912 			*this = aNewBmp;
1913 			maPrefMapMode = aMap;
1914 			maPrefSize = aSize;
1915 		}
1916 	}
1917 
1918 	return bRet;
1919 }
1920 
1921 // ------------------------------------------------------------------------
1922 
1923 void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
1924 							long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
1925 							long nColors, long nPixels, long& rIndex )
1926 {
1927 	if( !nPixels )
1928 		return;
1929 
1930 	BitmapColor	aCol;
1931 	const long	nRLen = nR2 - nR1;
1932 	const long	nGLen = nG2 - nG1;
1933 	const long	nBLen = nB2 - nB1;
1934 	long 		nR, nG, nB;
1935 	sal_uLong*		pBuf = pColBuf;
1936 
1937 	if( !nRLen && !nGLen && !nBLen )
1938 	{
1939 		if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
1940 		{
1941 			aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
1942 			aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
1943 			aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
1944 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
1945 		}
1946 	}
1947 	else
1948 	{
1949 		if( 1 == nColors || 1 == nPixels )
1950 		{
1951 			long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
1952 
1953 			for( nR = nR1; nR <= nR2; nR++ )
1954 			{
1955 				for( nG = nG1; nG <= nG2; nG++ )
1956 				{
1957 					for( nB = nB1; nB <= nB2; nB++ )
1958 					{
1959 						nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
1960 
1961 						if( nPixSum )
1962 						{
1963 							nRSum += nR * nPixSum;
1964 							nGSum += nG * nPixSum;
1965 							nBSum += nB * nPixSum;
1966 						}
1967 					}
1968 				}
1969 			}
1970 
1971 			aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
1972 			aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
1973 			aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
1974 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
1975 		}
1976 		else
1977 		{
1978 			const long	nTest = ( nPixels >> 1 );
1979 			long		nPixOld = 0;
1980 			long		nPixNew = 0;
1981 
1982 			if( nBLen > nGLen && nBLen > nRLen )
1983 			{
1984 				nB = nB1 - 1;
1985 
1986 				while( nPixNew < nTest )
1987 				{
1988 					nB++, nPixOld = nPixNew;
1989 					for( nR = nR1; nR <= nR2; nR++ )
1990 						for( nG = nG1; nG <= nG2; nG++ )
1991 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
1992 				}
1993 
1994 				if( nB < nB2 )
1995 				{
1996 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
1997 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
1998 				}
1999 				else
2000 				{
2001 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
2002 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
2003 				}
2004 			}
2005 			else if( nGLen > nRLen )
2006 			{
2007 				nG = nG1 - 1;
2008 
2009 				while( nPixNew < nTest )
2010 				{
2011 					nG++, nPixOld = nPixNew;
2012 					for( nR = nR1; nR <= nR2; nR++ )
2013 						for( nB = nB1; nB <= nB2; nB++ )
2014 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
2015 				}
2016 
2017 				if( nG < nG2 )
2018 				{
2019 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
2020 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
2021 				}
2022 				else
2023 				{
2024 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
2025 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
2026 				}
2027 			}
2028 			else
2029 			{
2030 				nR = nR1 - 1;
2031 
2032 				while( nPixNew < nTest )
2033 				{
2034 					nR++, nPixOld = nPixNew;
2035 					for( nG = nG1; nG <= nG2; nG++ )
2036 						for( nB = nB1; nB <= nB2; nB++ )
2037 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
2038 				}
2039 
2040 				if( nR < nR2 )
2041 				{
2042 					ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
2043 					ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
2044 				}
2045 				else
2046 				{
2047 					ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
2048 					ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
2049 				}
2050 			}
2051 		}
2052 	}
2053 }
2054 
2055 // ------------------------------------------------------------------------
2056 
2057 sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
2058 {
2059 	return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
2060 }
2061 
2062 // ------------------------------------------------------------------------
2063 
2064 sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
2065 {
2066 	return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
2067 }
2068 
2069 // ------------------------------------------------------------------------
2070 
2071 sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
2072 					 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
2073 					 double fGamma, sal_Bool bInvert )
2074 {
2075 	sal_Bool bRet = sal_False;
2076 
2077 	// nothing to do => return quickly
2078 	if( !nLuminancePercent && !nContrastPercent &&
2079 		!nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
2080 		( fGamma == 1.0 ) && !bInvert )
2081 	{
2082 		bRet = sal_True;
2083 	}
2084 	else
2085 	{
2086 		BitmapWriteAccess* pAcc = AcquireWriteAccess();
2087 
2088 		if( pAcc )
2089 		{
2090 			BitmapColor		aCol;
2091 			const long		nW = pAcc->Width();
2092 			const long		nH = pAcc->Height();
2093 			sal_uInt8*			cMapR = new sal_uInt8[ 256 ];
2094 			sal_uInt8*			cMapG = new sal_uInt8[ 256 ];
2095 			sal_uInt8*			cMapB = new sal_uInt8[ 256 ];
2096 			long			nX, nY;
2097 			double			fM, fROff, fGOff, fBOff, fOff;
2098 
2099 			// calculate slope
2100 			if( nContrastPercent >= 0 )
2101 				fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
2102 			else
2103 				fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
2104 
2105 			// total offset = luminance offset + contrast offset
2106 			fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
2107 
2108 			// channel offset = channel offset  + total offset
2109 			fROff = nChannelRPercent * 2.55 + fOff;
2110 			fGOff = nChannelGPercent * 2.55 + fOff;
2111 			fBOff = nChannelBPercent * 2.55 + fOff;
2112 
2113 			// calculate gamma value
2114 			fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2115 			const sal_Bool bGamma = ( fGamma != 1.0 );
2116 
2117 			// create mapping table
2118 			for( nX = 0L; nX < 256L; nX++ )
2119 			{
2120 				cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
2121 				cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
2122 				cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
2123 
2124 				if( bGamma )
2125 				{
2126 					cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
2127 					cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
2128 					cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
2129 				}
2130 
2131 				if( bInvert )
2132 				{
2133 					cMapR[ nX ] = ~cMapR[ nX ];
2134 					cMapG[ nX ] = ~cMapG[ nX ];
2135 					cMapB[ nX ] = ~cMapB[ nX ];
2136 				}
2137 			}
2138 
2139 			// do modifying
2140 			if( pAcc->HasPalette() )
2141 			{
2142 				BitmapColor aNewCol;
2143 
2144 				for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
2145 				{
2146 					const BitmapColor& rCol = pAcc->GetPaletteColor( i );
2147 					aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
2148 					aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
2149 					aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
2150 					pAcc->SetPaletteColor( i, aNewCol );
2151 				}
2152 			}
2153 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
2154 			{
2155 				for( nY = 0L; nY < nH; nY++ )
2156 				{
2157 					Scanline pScan = pAcc->GetScanline( nY );
2158 
2159 					for( nX = 0L; nX < nW; nX++ )
2160 					{
2161 						*pScan = cMapB[ *pScan ]; pScan++;
2162 						*pScan = cMapG[ *pScan ]; pScan++;
2163 						*pScan = cMapR[ *pScan ]; pScan++;
2164 					}
2165 				}
2166 			}
2167 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
2168 			{
2169 				for( nY = 0L; nY < nH; nY++ )
2170 				{
2171 					Scanline pScan = pAcc->GetScanline( nY );
2172 
2173 					for( nX = 0L; nX < nW; nX++ )
2174 					{
2175 						*pScan = cMapR[ *pScan ]; pScan++;
2176 						*pScan = cMapG[ *pScan ]; pScan++;
2177 						*pScan = cMapB[ *pScan ]; pScan++;
2178 					}
2179 				}
2180 			}
2181 			else
2182 			{
2183 				for( nY = 0L; nY < nH; nY++ )
2184 				{
2185 					for( nX = 0L; nX < nW; nX++ )
2186 					{
2187 						aCol = pAcc->GetPixel( nY, nX );
2188 						aCol.SetRed( cMapR[ aCol.GetRed() ] );
2189 						aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
2190 						aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
2191 						pAcc->SetPixel( nY, nX, aCol );
2192 					}
2193 				}
2194 			}
2195 
2196 			delete[] cMapR;
2197 			delete[] cMapG;
2198 			delete[] cMapB;
2199 			ReleaseAccess( pAcc );
2200 			bRet = sal_True;
2201 		}
2202 	}
2203 
2204 	return bRet;
2205 }
2206