xref: /aoo41x/main/vcl/source/gdi/bitmap.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 <rtl/crc.h>
32 #include <tools/stream.hxx>
33 #include <tools/poly.hxx>
34 #include <tools/rc.h>
35 
36 #include <vcl/salbtype.hxx>
37 #include <vcl/bmpacc.hxx>
38 #include <vcl/outdev.hxx>
39 #include <vcl/bitmap.hxx>
40 #include <vcl/bitmapex.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/image.hxx>
43 
44 #include <impbmp.hxx>
45 #include <salbmp.hxx>
46 
47 // ----------
48 // - Bitmap -
49 // ----------
50 
51 Bitmap::Bitmap() :
52 	mpImpBmp( NULL )
53 {
54 }
55 
56 // ------------------------------------------------------------------
57 
58 Bitmap::Bitmap( const ResId& rResId ) :
59 	mpImpBmp( NULL )
60 {
61 	const BitmapEx aBmpEx( rResId );
62 
63 	if( !aBmpEx.IsEmpty() )
64 		*this = aBmpEx.GetBitmap();
65 }
66 
67 // ------------------------------------------------------------------
68 
69 Bitmap::Bitmap( const Bitmap& rBitmap ) :
70 	maPrefMapMode	( rBitmap.maPrefMapMode ),
71 	maPrefSize		( rBitmap.maPrefSize )
72 {
73 	mpImpBmp = rBitmap.mpImpBmp;
74 
75 	if ( mpImpBmp )
76 		mpImpBmp->ImplIncRefCount();
77 }
78 
79 // ------------------------------------------------------------------
80 
81 Bitmap::Bitmap( SalBitmap* pSalBitmap )
82 {
83     mpImpBmp = new ImpBitmap();
84     mpImpBmp->ImplSetSalBitmap( pSalBitmap );
85     maPrefMapMode = MapMode( MAP_PIXEL );
86     maPrefSize = mpImpBmp->ImplGetSize();
87 }
88 
89 // ------------------------------------------------------------------
90 
91 Bitmap::Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal )
92 {
93 	if( rSizePixel.Width() && rSizePixel.Height() )
94 	{
95 		BitmapPalette	aPal;
96 		BitmapPalette*	pRealPal = NULL;
97 
98 		if( nBitCount <= 8 )
99 		{
100 			if( !pPal )
101 			{
102 				if( 1 == nBitCount )
103 				{
104 					aPal.SetEntryCount( 2 );
105 					aPal[ 0 ] = Color( COL_BLACK );
106 					aPal[ 1 ] = Color( COL_WHITE );
107 				}
108 				else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
109 				{
110 					aPal.SetEntryCount( 1 << nBitCount );
111 					aPal[ 0 ] = Color( COL_BLACK );
112 					aPal[ 1 ] = Color( COL_BLUE );
113 					aPal[ 2 ] = Color( COL_GREEN );
114 					aPal[ 3 ] = Color( COL_CYAN );
115 					aPal[ 4 ] = Color( COL_RED );
116 					aPal[ 5 ] = Color( COL_MAGENTA );
117 					aPal[ 6 ] = Color( COL_BROWN );
118 					aPal[ 7 ] = Color( COL_GRAY );
119 					aPal[ 8 ] = Color( COL_LIGHTGRAY );
120 					aPal[ 9 ] = Color( COL_LIGHTBLUE );
121 					aPal[ 10 ] = Color( COL_LIGHTGREEN );
122 					aPal[ 11 ] = Color( COL_LIGHTCYAN );
123 					aPal[ 12 ] = Color( COL_LIGHTRED );
124 					aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
125 					aPal[ 14 ] = Color( COL_YELLOW );
126 					aPal[ 15 ] = Color( COL_WHITE );
127 
128 					// Dither-Palette erzeugen
129 					if( 8 == nBitCount )
130 					{
131 						sal_uInt16 nActCol = 16;
132 
133 						for( sal_uInt16 nB = 0; nB < 256; nB += 51 )
134 							for( sal_uInt16 nG = 0; nG < 256; nG += 51 )
135 								for( sal_uInt16 nR = 0; nR < 256; nR += 51 )
136 									aPal[ nActCol++ ] = BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB );
137 
138 						// Standard-Office-Farbe setzen
139 						aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
140 					}
141 				}
142 			}
143 			else
144 				pRealPal = (BitmapPalette*) pPal;
145 		}
146 
147 		mpImpBmp = new ImpBitmap;
148 		mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
149 	}
150 	else
151 		mpImpBmp = NULL;
152 }
153 
154 // ------------------------------------------------------------------
155 
156 Bitmap::~Bitmap()
157 {
158 	ImplReleaseRef();
159 }
160 
161 // ------------------------------------------------------------------
162 
163 const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
164 {
165 	static BitmapPalette aGreyPalette2;
166 	static BitmapPalette aGreyPalette4;
167 	static BitmapPalette aGreyPalette16;
168 	static BitmapPalette aGreyPalette256;
169 
170 	// create greyscale palette with 2, 4, 16 or 256 entries
171 	if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
172 	{
173 		if( 2 == nEntries )
174 		{
175 			if( !aGreyPalette2.GetEntryCount() )
176 			{
177 				aGreyPalette2.SetEntryCount( 2 );
178 				aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
179 				aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
180 			}
181 
182 			return aGreyPalette2;
183 		}
184 		else if( 4 == nEntries )
185 		{
186 			if( !aGreyPalette4.GetEntryCount() )
187 			{
188 				aGreyPalette4.SetEntryCount( 4 );
189 				aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
190 				aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
191 				aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
192 				aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
193 			}
194 
195 			return aGreyPalette4;
196 		}
197 		else if( 16 == nEntries )
198 		{
199 			if( !aGreyPalette16.GetEntryCount() )
200 			{
201 				sal_uInt8 cGrey = 0, cGreyInc = 17;
202 
203 				aGreyPalette16.SetEntryCount( 16 );
204 
205 				for( sal_uInt16 i = 0; i < 16; i++, cGrey = sal::static_int_cast<sal_uInt8>(cGrey + cGreyInc) )
206 					aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
207 			}
208 
209 			return aGreyPalette16;
210 		}
211 		else
212 		{
213 			if( !aGreyPalette256.GetEntryCount() )
214 			{
215 				aGreyPalette256.SetEntryCount( 256 );
216 
217 				for( sal_uInt16 i = 0; i < 256; i++ )
218 					aGreyPalette256[ i ] = BitmapColor( (sal_uInt8) i, (sal_uInt8) i, (sal_uInt8) i );
219 			}
220 
221 			return aGreyPalette256;
222 		}
223 	}
224 	else
225 	{
226 		DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
227 		return aGreyPalette2;
228 	}
229 }
230 
231 // ------------------------------------------------------------------
232 
233 bool BitmapPalette::IsGreyPalette() const
234 {
235 	// TODO: add an IsGreyPalette flag to BitmapPalette
236 	// TODO: unless this causes problems binary compatibility
237 	const int nEntryCount = GetEntryCount();
238 	if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
239 		return true;
240 	// see above: only certain entry values will result in a valid call to GetGreyPalette
241 	if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 )
242 	{
243 	    const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
244 	    if( rGreyPalette == *this )
245             return true;
246     }
247 	// TODO: is it worth to compare the entries?
248 	return false;
249 }
250 
251 // ------------------------------------------------------------------
252 
253 Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
254 {
255 	maPrefSize = rBitmap.maPrefSize;
256 	maPrefMapMode = rBitmap.maPrefMapMode;
257 
258 	if ( rBitmap.mpImpBmp )
259 		rBitmap.mpImpBmp->ImplIncRefCount();
260 
261 	ImplReleaseRef();
262 	mpImpBmp = rBitmap.mpImpBmp;
263 
264 	return *this;
265 }
266 
267 // ------------------------------------------------------------------
268 
269 sal_Bool Bitmap::IsEqual( const Bitmap& rBmp ) const
270 {
271 	return( IsSameInstance( rBmp ) ||
272 			( rBmp.GetSizePixel() == GetSizePixel() &&
273 			  rBmp.GetBitCount() == GetBitCount() &&
274 			  rBmp.GetChecksum() == GetChecksum() ) );
275 }
276 
277 // ------------------------------------------------------------------
278 
279 void Bitmap::SetEmpty()
280 {
281 	maPrefMapMode = MapMode();
282 	maPrefSize = Size();
283 
284 	ImplReleaseRef();
285 	mpImpBmp = NULL;
286 }
287 
288 // ------------------------------------------------------------------
289 
290 Size Bitmap::GetSizePixel() const
291 {
292 	return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
293 }
294 // ------------------------------------------------------------------
295 
296 void Bitmap::SetSizePixel( const Size& rNewSize )
297 {
298 	Scale( rNewSize );
299 }
300 
301 // ------------------------------------------------------------------
302 
303 Size Bitmap::GetSourceSizePixel() const
304 {
305 	return( mpImpBmp ? mpImpBmp->ImplGetSourceSize() : Size() );
306 }
307 
308 // ------------------------------------------------------------------
309 
310 void Bitmap::SetSourceSizePixel( const Size& rSize)
311 {
312 	if( mpImpBmp )
313 		mpImpBmp->ImplSetSourceSize( rSize);
314 }
315 
316 // ------------------------------------------------------------------
317 
318 sal_uInt16 Bitmap::GetBitCount() const
319 {
320 	return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
321 }
322 
323 // ------------------------------------------------------------------
324 
325 sal_Bool Bitmap::HasGreyPalette() const
326 {
327 	const sal_uInt16	nBitCount = GetBitCount();
328 	sal_Bool			bRet = sal_False;
329 
330 	if( 1 == nBitCount )
331 	{
332 		BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
333 
334 		if( pRAcc )
335 		{
336 		    const BitmapColor& rCol0( pRAcc->GetPaletteColor( 0 ) );
337 		    const BitmapColor& rCol1( pRAcc->GetPaletteColor( 1 ) );
338 		    if( rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() &&
339 		        rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue() )
340 		    {
341 		        bRet = sal_True;
342 		    }
343 			 ( (Bitmap*) this )->ReleaseAccess( pRAcc );
344 		}
345 		else
346 		    bRet = sal_True;
347 	}
348 	else if( 4 == nBitCount || 8 == nBitCount )
349 	{
350 		BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
351 
352 		if( pRAcc )
353 		{
354 			if( pRAcc->HasPalette() && ( (BitmapPalette&) pRAcc->GetPalette() == GetGreyPalette( 1 << nBitCount ) ) )
355 				bRet = sal_True;
356 
357 			 ( (Bitmap*) this )->ReleaseAccess( pRAcc );
358 		}
359 	}
360 
361 	return bRet;
362 }
363 
364 // ------------------------------------------------------------------
365 
366 sal_uLong Bitmap::GetChecksum() const
367 {
368 	sal_uLong nRet = 0UL;
369 
370 	if( mpImpBmp )
371 	{
372 		nRet = mpImpBmp->ImplGetChecksum();
373 
374 		if( !nRet )
375 		{
376 			BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
377 
378 			if( pRAcc && pRAcc->Width() && pRAcc->Height() )
379 			{
380 				sal_uInt32	nCrc = 0;
381 				SVBT32		aBT32;
382 
383 				pRAcc->ImplZeroInitUnusedBits();
384 
385 				UInt32ToSVBT32( pRAcc->Width(), aBT32 );
386 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
387 
388 				UInt32ToSVBT32( pRAcc->Height(), aBT32 );
389 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
390 
391 				UInt32ToSVBT32( pRAcc->GetBitCount(), aBT32 );
392 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
393 
394 				UInt32ToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
395 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
396 
397 				UInt32ToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
398 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
399 
400 				UInt32ToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
401 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
402 
403 				if( pRAcc->HasPalette() )
404 				{
405 					nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
406 									  pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
407 				}
408 
409 				nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
410 
411 				mpImpBmp->ImplSetChecksum( nRet = nCrc );
412 			}
413 
414 			if (pRAcc) ( (Bitmap*) this )->ReleaseAccess( pRAcc );
415 		}
416 	}
417 
418 	return nRet;
419 }
420 
421 // ------------------------------------------------------------------
422 
423 void Bitmap::ImplReleaseRef()
424 {
425 	if( mpImpBmp )
426 	{
427 		if( mpImpBmp->ImplGetRefCount() > 1UL )
428 			mpImpBmp->ImplDecRefCount();
429 		else
430 		{
431 			delete mpImpBmp;
432 			mpImpBmp = NULL;
433 		}
434 	}
435 }
436 
437 // ------------------------------------------------------------------
438 
439 void Bitmap::ImplMakeUnique()
440 {
441 	if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
442 	{
443 		ImpBitmap* pOldImpBmp = mpImpBmp;
444 
445 		pOldImpBmp->ImplDecRefCount();
446 
447 		mpImpBmp = new ImpBitmap;
448 		mpImpBmp->ImplCreate( *pOldImpBmp );
449 	}
450 }
451 
452 // ------------------------------------------------------------------
453 
454 void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
455 {
456 	const Size		aOldSizePix( GetSizePixel() );
457 	const Size		aNewSizePix( rBitmap.GetSizePixel() );
458 	const MapMode	aOldMapMode( maPrefMapMode );
459 	Size			aNewPrefSize;
460 
461 	if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
462 	{
463 		aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
464 		aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
465 	}
466 	else
467 		aNewPrefSize = maPrefSize;
468 
469 	*this = rBitmap;
470 
471 	maPrefSize = aNewPrefSize;
472 	maPrefMapMode = aOldMapMode;
473 }
474 
475 // ------------------------------------------------------------------
476 
477 ImpBitmap* Bitmap::ImplGetImpBitmap() const
478 {
479 	return mpImpBmp;
480 }
481 
482 // ------------------------------------------------------------------
483 
484 void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
485 {
486 	if( pImpBmp != mpImpBmp )
487 	{
488 		ImplReleaseRef();
489 		mpImpBmp = pImpBmp;
490 	}
491 }
492 
493 // ------------------------------------------------------------------
494 
495 BitmapReadAccess* Bitmap::AcquireReadAccess()
496 {
497 	BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
498 
499 	if( !*pReadAccess )
500 	{
501 		delete pReadAccess;
502 		pReadAccess = NULL;
503 	}
504 
505 	return pReadAccess;
506 }
507 
508 // ------------------------------------------------------------------
509 
510 BitmapWriteAccess* Bitmap::AcquireWriteAccess()
511 {
512 	BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
513 
514 	if( !*pWriteAccess )
515 	{
516 		delete pWriteAccess;
517 		pWriteAccess = NULL;
518 	}
519 
520 	return pWriteAccess;
521 }
522 
523 // ------------------------------------------------------------------
524 
525 void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
526 {
527 	delete pBitmapAccess;
528 }
529 
530 // ------------------------------------------------------------------
531 
532 sal_Bool Bitmap::Erase( const Color& rFillColor )
533 {
534 	if( !(*this) )
535 		return sal_True;
536 
537 	BitmapWriteAccess*	pWriteAcc = AcquireWriteAccess();
538 	sal_Bool				bRet = sal_False;
539 
540 	if( pWriteAcc )
541 	{
542 		const sal_uLong nFormat = pWriteAcc->GetScanlineFormat();
543 		sal_uInt8		cIndex = 0;
544 		sal_Bool		bFast = sal_False;
545 
546 		switch( nFormat )
547 		{
548 			case( BMP_FORMAT_1BIT_MSB_PAL ):
549 			case( BMP_FORMAT_1BIT_LSB_PAL ):
550 			{
551 				cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
552 				cIndex = ( cIndex ? 255 : 0 );
553 				bFast = sal_True;
554 			}
555 			break;
556 
557 			case( BMP_FORMAT_4BIT_MSN_PAL ):
558 			case( BMP_FORMAT_4BIT_LSN_PAL ):
559 			{
560 				cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
561 				cIndex = cIndex | ( cIndex << 4 );
562 				bFast = sal_True;
563 			}
564 			break;
565 
566 			case( BMP_FORMAT_8BIT_PAL ):
567 			{
568 				cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
569 				bFast = sal_True;
570 			}
571 			break;
572 
573 			case( BMP_FORMAT_24BIT_TC_BGR ):
574 			case( BMP_FORMAT_24BIT_TC_RGB ):
575 			{
576 				if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
577 					( rFillColor.GetRed() == rFillColor.GetBlue() ) )
578 				{
579 					cIndex = rFillColor.GetRed();
580 					bFast = sal_True;
581 				}
582 				else
583 					bFast = sal_False;
584 			}
585 			break;
586 
587 			default:
588 				bFast = sal_False;
589 			break;
590 		}
591 
592 		if( bFast )
593 		{
594 			const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
595 			memset( pWriteAcc->GetBuffer(), cIndex, nBufSize );
596 		}
597 		else
598 		{
599 			Point aTmpPoint;
600 			const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
601 			pWriteAcc->SetFillColor( rFillColor );
602 			pWriteAcc->FillRect( aRect );
603 		}
604 
605 		ReleaseAccess( pWriteAcc );
606 		bRet = sal_True;
607 	}
608 
609 	return bRet;
610 }
611 
612 // ------------------------------------------------------------------
613 
614 sal_Bool Bitmap::Invert()
615 {
616 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
617 	sal_Bool				bRet = sal_False;
618 
619 	if( pAcc )
620 	{
621 		if( pAcc->HasPalette() )
622 		{
623 			BitmapPalette	aBmpPal( pAcc->GetPalette() );
624 			const sal_uInt16	nCount = aBmpPal.GetEntryCount();
625 
626 			for( sal_uInt16 i = 0; i < nCount; i++ )
627 				aBmpPal[ i ].Invert();
628 
629 			pAcc->SetPalette( aBmpPal );
630 		}
631 		else
632 		{
633 			const long	nWidth = pAcc->Width();
634 			const long	nHeight = pAcc->Height();
635 
636 			for( long nX = 0L; nX < nWidth; nX++ )
637 				for( long nY = 0L; nY < nHeight; nY++ )
638 					pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
639 		}
640 
641 		ReleaseAccess( pAcc );
642 		bRet = sal_True;
643 	}
644 
645 	return bRet;
646 }
647 
648 // ------------------------------------------------------------------
649 
650 sal_Bool Bitmap::Mirror( sal_uLong nMirrorFlags )
651 {
652 	sal_Bool bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
653 	sal_Bool bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
654 	sal_Bool bRet = sal_False;
655 
656 	if( bHorz && !bVert )
657 	{
658 		BitmapWriteAccess*	pAcc = AcquireWriteAccess();
659 
660 		if( pAcc )
661 		{
662 			const long	nWidth = pAcc->Width();
663 			const long	nHeight = pAcc->Height();
664 			const long	nWidth1 = nWidth - 1L;
665 			const long	nWidth_2 = nWidth >> 1L;
666 
667 			for( long nY = 0L; nY < nHeight; nY++ )
668 			{
669 				for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
670 				{
671 					const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
672 
673 					pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
674 					pAcc->SetPixel( nY, nOther, aTemp );
675 				}
676 			}
677 
678 			ReleaseAccess( pAcc );
679 			bRet = sal_True;
680 		}
681 	}
682 	else if( bVert && !bHorz )
683 	{
684 		BitmapWriteAccess*	pAcc = AcquireWriteAccess();
685 
686 		if( pAcc )
687 		{
688 			const long	nScanSize = pAcc->GetScanlineSize();
689 			sal_uInt8*		pBuffer = new sal_uInt8[ nScanSize ];
690 			const long	nHeight = pAcc->Height();
691 			const long	nHeight1 = nHeight - 1L;
692 			const long	nHeight_2 = nHeight >> 1L;
693 
694 			for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
695 			{
696 				memcpy( pBuffer, pAcc->GetScanline( nY ), nScanSize );
697 				memcpy( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
698 				memcpy( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
699 			}
700 
701 			delete[] pBuffer;
702 			ReleaseAccess( pAcc );
703 			bRet = sal_True;
704 		}
705 	}
706 	else if( bHorz && bVert )
707 	{
708 		BitmapWriteAccess*	pAcc = AcquireWriteAccess();
709 
710 		if( pAcc )
711 		{
712 			const long	nWidth = pAcc->Width();
713 			const long	nWidth1 = nWidth - 1L;
714 			const long	nHeight = pAcc->Height();
715 			long		nHeight_2 = nHeight >> 1;
716 
717 			for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
718 			{
719 				for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
720 				{
721 					const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
722 
723 					pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
724 					pAcc->SetPixel( nOtherY, nOtherX, aTemp );
725 				}
726 			}
727 
728 			// ggf. noch mittlere Zeile horizontal spiegeln
729 			if( nHeight & 1 )
730 			{
731 				for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
732 				{
733 					const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
734 					pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
735 					pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
736 				}
737 			}
738 
739 			ReleaseAccess( pAcc );
740 			bRet = sal_True;
741 		}
742 	}
743 	else
744 		bRet = sal_True;
745 
746 	return bRet;
747 }
748 
749 // ------------------------------------------------------------------
750 
751 sal_Bool Bitmap::Rotate( long nAngle10, const Color& rFillColor )
752 {
753 	sal_Bool bRet = sal_False;
754 
755 	nAngle10 %= 3600L;
756 	nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
757 
758 	if( !nAngle10	 )
759 		bRet = sal_True;
760 	else if( 1800L == nAngle10 )
761 		bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
762 	else
763 	{
764 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
765 		Bitmap				aRotatedBmp;
766 
767 		if( pReadAcc )
768 		{
769 			const Size	aSizePix( GetSizePixel() );
770 
771 			if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
772 			{
773 				const Size			aNewSizePix( aSizePix.Height(), aSizePix.Width() );
774 				Bitmap				aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
775 				BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
776 
777 				if( pWriteAcc )
778 				{
779 					const long	nWidth = aSizePix.Width();
780 					const long	nWidth1 = nWidth - 1L;
781 					const long	nHeight = aSizePix.Height();
782 					const long	nHeight1 = nHeight - 1L;
783 					const long	nNewWidth = aNewSizePix.Width();
784 					const long	nNewHeight = aNewSizePix.Height();
785 
786 					if( 900L == nAngle10 )
787 					{
788 						for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
789 							for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
790 								pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
791 					}
792 					else if( 2700L == nAngle10 )
793 					{
794 						for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
795 							for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
796 								pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
797 					}
798 
799 					aNewBmp.ReleaseAccess( pWriteAcc );
800 				}
801 
802 				aRotatedBmp = aNewBmp;
803 			}
804 			else
805 			{
806 				Point		aTmpPoint;
807 				Rectangle	aTmpRectangle( aTmpPoint, aSizePix );
808 				Polygon 	aPoly( aTmpRectangle );
809 				aPoly.Rotate( aTmpPoint, (sal_uInt16) nAngle10 );
810 
811 				Rectangle			aNewBound( aPoly.GetBoundRect() );
812 				const Size			aNewSizePix( aNewBound.GetSize() );
813 				Bitmap				aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
814 				BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
815 
816 				if( pWriteAcc )
817 				{
818 					const BitmapColor	aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
819 					const double		fCosAngle = cos( nAngle10 * F_PI1800 );
820 					const double		fSinAngle = sin( nAngle10 * F_PI1800 );
821 					const double		fXMin = aNewBound.Left();
822 					const double		fYMin = aNewBound.Top();
823 					const long			nWidth = aSizePix.Width();
824 					const long			nHeight = aSizePix.Height();
825 					const long			nNewWidth = aNewSizePix.Width();
826 					const long			nNewHeight = aNewSizePix.Height();
827 					long				nX;
828 					long				nY;
829 					long				nRotX;
830 					long				nRotY;
831 					long				nSinY;
832 					long				nCosY;
833 					long*				pCosX = new long[ nNewWidth ];
834 					long*				pSinX = new long[ nNewWidth ];
835 					long*				pCosY = new long[ nNewHeight ];
836 					long*				pSinY = new long[ nNewHeight ];
837 
838 					for ( nX = 0; nX < nNewWidth; nX++ )
839 					{
840 						const double fTmp = ( fXMin + nX ) * 64.;
841 
842 						pCosX[ nX ] = FRound( fCosAngle * fTmp );
843 						pSinX[ nX ] = FRound( fSinAngle * fTmp );
844 					}
845 
846 					for ( nY = 0; nY < nNewHeight; nY++ )
847 					{
848 						const double fTmp = ( fYMin + nY ) * 64.;
849 
850 						pCosY[ nY ] = FRound( fCosAngle * fTmp );
851 						pSinY[ nY ] = FRound( fSinAngle * fTmp );
852 					}
853 
854 					for( nY = 0L; nY < nNewHeight; nY++ )
855 					{
856 						nSinY = pSinY[ nY ];
857 						nCosY = pCosY[ nY ];
858 
859 						for( nX = 0L; nX < nNewWidth; nX++ )
860 						{
861 							nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
862 							nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
863 
864 							if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
865 								pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
866 							else
867 								pWriteAcc->SetPixel( nY, nX, aFillColor );
868 						}
869 					}
870 
871 					delete[] pSinX;
872 					delete[] pCosX;
873 					delete[] pSinY;
874 					delete[] pCosY;
875 
876 					aNewBmp.ReleaseAccess( pWriteAcc );
877 				}
878 
879 				aRotatedBmp = aNewBmp;
880 			}
881 
882 			ReleaseAccess( pReadAcc );
883 		}
884 
885 		if( ( bRet = !!aRotatedBmp ) == sal_True )
886 			ImplAssignWithSize( aRotatedBmp );
887 	}
888 
889 	return bRet;
890 };
891 
892 // ------------------------------------------------------------------
893 
894 sal_Bool Bitmap::Crop( const Rectangle& rRectPixel )
895 {
896 	const Size			aSizePix( GetSizePixel() );
897 	Rectangle			aRect( rRectPixel );
898 	sal_Bool				bRet = sal_False;
899 
900 	aRect.Intersection( Rectangle( Point(), aSizePix ) );
901 
902 	if( !aRect.IsEmpty() )
903 	{
904 		BitmapReadAccess* pReadAcc = AcquireReadAccess();
905 
906 		if( pReadAcc )
907 		{
908 			Point				aTmpPoint;
909 			const Rectangle 	aNewRect( aTmpPoint, aRect.GetSize() );
910 			Bitmap				aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
911 			BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
912 
913 			if( pWriteAcc )
914 			{
915 				const long nOldX = aRect.Left();
916 				const long nOldY = aRect.Top();
917 				const long nNewWidth = aNewRect.GetWidth();
918 				const long nNewHeight = aNewRect.GetHeight();
919 
920 				for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
921 					for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
922 						pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
923 
924 				aNewBmp.ReleaseAccess( pWriteAcc );
925 				bRet = sal_True;
926 			}
927 
928 			ReleaseAccess( pReadAcc );
929 
930 			if( bRet )
931 				ImplAssignWithSize( aNewBmp );
932 		}
933 	}
934 
935 	return bRet;
936 };
937 
938 // ------------------------------------------------------------------
939 
940 sal_Bool Bitmap::CopyPixel( const Rectangle& rRectDst,
941 						const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
942 {
943 	const Size	aSizePix( GetSizePixel() );
944 	Rectangle	aRectDst( rRectDst );
945 	sal_Bool		bRet = sal_False;
946 
947 	aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
948 
949 	if( !aRectDst.IsEmpty() )
950 	{
951 		if( pBmpSrc && ( *pBmpSrc != *this ) )
952 		{
953 			Bitmap* 		pSrc = (Bitmap*) pBmpSrc;
954 			const Size		aCopySizePix( pSrc->GetSizePixel() );
955 			Rectangle		aRectSrc( rRectSrc );
956 			const sal_uInt16	nSrcBitCount = pBmpSrc->GetBitCount();
957 			const sal_uInt16	nDstBitCount = GetBitCount();
958 
959 			if( nSrcBitCount > nDstBitCount )
960 			{
961 				long nNextIndex = 0L;
962 
963 				if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
964 					Convert( BMP_CONVERSION_24BIT );
965 				else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
966 				{
967 					Convert( BMP_CONVERSION_8BIT_COLORS );
968 					nNextIndex = 16;
969 				}
970 				else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
971 				{
972 					Convert( BMP_CONVERSION_4BIT_COLORS );
973 					nNextIndex = 2;
974 				}
975 
976 				if( nNextIndex )
977 				{
978 					BitmapReadAccess*	pSrcAcc = pSrc->AcquireReadAccess();
979 					BitmapWriteAccess*	pDstAcc = AcquireWriteAccess();
980 
981 					if( pSrcAcc && pDstAcc )
982 					{
983 						const long		nSrcCount = pDstAcc->GetPaletteEntryCount();
984 						const long		nDstCount = 1 << nDstBitCount;
985 						sal_Bool			bFound;
986 
987 						for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
988 						{
989 							const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (sal_uInt16) i );
990 
991 							bFound = sal_False;
992 
993 							for( long j = 0L; j < nDstCount; j++ )
994 							{
995 								if( rSrcCol == pDstAcc->GetPaletteColor( (sal_uInt16) j ) )
996 								{
997 									bFound = sal_True;
998 									break;
999 								}
1000 							}
1001 
1002 							if( !bFound )
1003 								pDstAcc->SetPaletteColor( (sal_uInt16) nNextIndex++, rSrcCol );
1004 						}
1005 					}
1006 
1007 					if( pSrcAcc )
1008 						pSrc->ReleaseAccess( pSrcAcc );
1009 
1010 					if( pDstAcc )
1011 						ReleaseAccess( pDstAcc );
1012 				}
1013 			}
1014 
1015 			aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
1016 
1017 			if( !aRectSrc.IsEmpty() )
1018 			{
1019 				BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
1020 
1021 				if( pReadAcc )
1022 				{
1023 					BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
1024 
1025 					if( pWriteAcc )
1026 					{
1027 						const long	nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
1028 						const long	nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
1029 						const long	nSrcEndX = aRectSrc.Left() + nWidth;
1030 						const long	nSrcEndY = aRectSrc.Top() + nHeight;
1031 						long		nDstY = aRectDst.Top();
1032 
1033 						if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
1034 						{
1035 							const sal_uInt16	nCount = pReadAcc->GetPaletteEntryCount();
1036 							sal_uInt8*			pMap = new sal_uInt8[ nCount ];
1037 
1038 							// Index-Map fuer Farbtabelle
1039 							// aufbauen, da das Bild ja (relativ) farbgenau
1040 							// kopiert werden soll
1041 							for( sal_uInt16 i = 0; i < nCount; i++ )
1042 								pMap[ i ] = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
1043 
1044 							for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1045 								for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1046 									pWriteAcc->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] );
1047 
1048 							delete[] pMap;
1049 						}
1050 						else if( pReadAcc->HasPalette() )
1051 						{
1052 							for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1053 								for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1054 									pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nSrcY, nSrcX ) ) );
1055 						}
1056 						else
1057 							for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1058 								for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1059 									pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
1060 
1061 						ReleaseAccess( pWriteAcc );
1062 						bRet = ( nWidth > 0L ) && ( nHeight > 0L );
1063 					}
1064 
1065 					pSrc->ReleaseAccess( pReadAcc );
1066 				}
1067 			}
1068 		}
1069 		else
1070 		{
1071 			Rectangle aRectSrc( rRectSrc );
1072 
1073 			aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
1074 
1075 			if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
1076 			{
1077 				BitmapWriteAccess*	pWriteAcc = AcquireWriteAccess();
1078 
1079 				if( pWriteAcc )
1080 				{
1081 					const long	nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
1082 					const long	nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
1083 					const long	nSrcX = aRectSrc.Left();
1084 					const long	nSrcY = aRectSrc.Top();
1085 					const long	nSrcEndX1 = nSrcX + nWidth - 1L;
1086 					const long	nSrcEndY1 = nSrcY + nHeight - 1L;
1087 					const long	nDstX = aRectDst.Left();
1088 					const long	nDstY = aRectDst.Top();
1089 					const long	nDstEndX1 = nDstX + nWidth - 1L;
1090 					const long	nDstEndY1 = nDstY + nHeight - 1L;
1091 
1092 					if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
1093 					{
1094 						for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
1095 							for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
1096 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1097 					}
1098 					else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
1099 					{
1100 						for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
1101 							for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
1102 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1103 					}
1104 					else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
1105 					{
1106 						for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
1107 							for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
1108 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1109 					}
1110 					else
1111 					{
1112 						for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
1113 							for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
1114 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1115 					}
1116 
1117 					ReleaseAccess( pWriteAcc );
1118 					bRet = sal_True;
1119 				}
1120 			}
1121 		}
1122 	}
1123 
1124 	return bRet;
1125 }
1126 
1127 // ------------------------------------------------------------------
1128 
1129 sal_Bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor )
1130 {
1131 	sal_Bool bRet = sal_False;
1132 
1133 	if( nDX || nDY )
1134 	{
1135 		const Size			aSizePixel( GetSizePixel() );
1136 		const long			nWidth = aSizePixel.Width();
1137 		const long			nHeight = aSizePixel.Height();
1138 		const Size			aNewSize( nWidth + nDX, nHeight + nDY );
1139 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1140 
1141 		if( pReadAcc )
1142 		{
1143 			BitmapPalette		aBmpPal( pReadAcc->GetPalette() );
1144 			Bitmap				aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
1145 			BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1146 
1147 			if( pWriteAcc )
1148 			{
1149 				BitmapColor aColor;
1150 				const long	nNewX = nWidth;
1151 				const long	nNewY = nHeight;
1152 				const long	nNewWidth = pWriteAcc->Width();
1153 				const long	nNewHeight = pWriteAcc->Height();
1154 				long		nX;
1155 				long		nY;
1156 
1157 				if( pInitColor )
1158 					aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
1159 
1160 				for( nY = 0L; nY < nHeight; nY++ )
1161 				{
1162 					pWriteAcc->CopyScanline( nY, *pReadAcc );
1163 
1164 					if( pInitColor && nDX )
1165 						for( nX = nNewX; nX < nNewWidth; nX++ )
1166 							pWriteAcc->SetPixel( nY, nX, aColor );
1167 				}
1168 
1169 				if( pInitColor && nDY )
1170 					for( nY = nNewY; nY < nNewHeight; nY++ )
1171 						for( nX = 0; nX < nNewWidth; nX++ )
1172 							pWriteAcc->SetPixel( nY, nX, aColor );
1173 
1174 				aNewBmp.ReleaseAccess( pWriteAcc );
1175 				bRet = sal_True;
1176 			}
1177 
1178 			ReleaseAccess( pReadAcc );
1179 
1180 			if( bRet )
1181 				ImplAssignWithSize( aNewBmp );
1182 		}
1183 	}
1184 
1185 	return bRet;
1186 }
1187 
1188 // ------------------------------------------------------------------
1189 
1190 Bitmap Bitmap::CreateMask( const Color& rTransColor, sal_uLong nTol ) const
1191 {
1192 	Bitmap				aNewBmp( GetSizePixel(), 1 );
1193 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1194 	sal_Bool				bRet = sal_False;
1195 
1196 	if( pWriteAcc )
1197 	{
1198 		BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
1199 
1200 		if( pReadAcc )
1201 		{
1202 			const long			nWidth = pReadAcc->Width();
1203 			const long			nHeight = pReadAcc->Height();
1204 			const BitmapColor	aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
1205 			const BitmapColor	aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1206 
1207 			if( !nTol )
1208 			{
1209 				const BitmapColor	aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
1210 				long				nX, nY, nShift;
1211 
1212 				if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
1213 					pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
1214 				{
1215 					// optimized for 4Bit-MSN/LSN source palette
1216 					const sal_uInt8 cTest = aTest.GetIndex();
1217 					const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
1218 
1219 					if(	pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1220 						aWhite.GetIndex() == 1 )
1221 					{
1222 						// optimized for 1Bit-MSB destination palette
1223 						for( nY = 0L; nY < nHeight; nY++ )
1224 						{
1225 							Scanline pSrc = pReadAcc->GetScanline( nY );
1226 							Scanline pDst = pWriteAcc->GetScanline( nY );
1227 							for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
1228 							{
1229 								if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
1230 									pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1231 								else
1232 									pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1233 							}
1234 						}
1235 					}
1236 					else
1237 					{
1238 						for( nY = 0L; nY < nHeight; nY++ )
1239 						{
1240 							Scanline pSrc = pReadAcc->GetScanline( nY );
1241 							for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
1242 							{
1243 								if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
1244 									pWriteAcc->SetPixel( nY, nX, aWhite );
1245 								else
1246 									pWriteAcc->SetPixel( nY, nX, aBlack );
1247 							}
1248 						}
1249 					}
1250 				}
1251 				else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1252 				{
1253 					// optimized for 8Bit source palette
1254 					const sal_uInt8 cTest = aTest.GetIndex();
1255 
1256 					if(	pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1257 						aWhite.GetIndex() == 1 )
1258 					{
1259 						// optimized for 1Bit-MSB destination palette
1260 						for( nY = 0L; nY < nHeight; nY++ )
1261 						{
1262 							Scanline pSrc = pReadAcc->GetScanline( nY );
1263 							Scanline pDst = pWriteAcc->GetScanline( nY );
1264 							for( nX = 0L; nX < nWidth; nX++ )
1265 							{
1266 								if( cTest == pSrc[ nX ] )
1267 									pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1268 								else
1269 									pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1270 							}
1271 						}
1272 					}
1273 					else
1274 					{
1275 						for( nY = 0L; nY < nHeight; nY++ )
1276 						{
1277 							Scanline pSrc = pReadAcc->GetScanline( nY );
1278 							for( nX = 0L; nX < nWidth; nX++ )
1279 							{
1280 								if( cTest == pSrc[ nX ] )
1281 									pWriteAcc->SetPixel( nY, nX, aWhite );
1282 								else
1283 									pWriteAcc->SetPixel( nY, nX, aBlack );
1284 							}
1285 						}
1286 					}
1287 				}
1288 				else
1289 				{
1290 					// not optimized
1291 					for( nY = 0L; nY < nHeight; nY++ )
1292 					{
1293 						for( nX = 0L; nX < nWidth; nX++ )
1294 						{
1295 							if( aTest == pReadAcc->GetPixel( nY, nX ) )
1296 								pWriteAcc->SetPixel( nY, nX, aWhite );
1297 							else
1298 								pWriteAcc->SetPixel( nY, nX, aBlack );
1299 						}
1300 					}
1301 				}
1302 			}
1303 			else
1304 			{
1305 				BitmapColor aCol;
1306 				long		nR, nG, nB;
1307 				const long	nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
1308 				const long	nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
1309 				const long	nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
1310 				const long	nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
1311 				const long	nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
1312 				const long	nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
1313 
1314 				if( pReadAcc->HasPalette() )
1315 				{
1316 					for( long nY = 0L; nY < nHeight; nY++ )
1317 					{
1318 						for( long nX = 0L; nX < nWidth; nX++ )
1319 						{
1320 							aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) );
1321 							nR = aCol.GetRed();
1322 							nG = aCol.GetGreen();
1323 							nB = aCol.GetBlue();
1324 
1325 							if( nMinR <= nR && nMaxR >= nR &&
1326 								nMinG <= nG && nMaxG >= nG &&
1327 								nMinB <= nB && nMaxB >= nB )
1328 							{
1329 								pWriteAcc->SetPixel( nY, nX, aWhite );
1330 							}
1331 							else
1332 								pWriteAcc->SetPixel( nY, nX, aBlack );
1333 						}
1334 					}
1335 				}
1336 				else
1337 				{
1338 					for( long nY = 0L; nY < nHeight; nY++ )
1339 					{
1340 						for( long nX = 0L; nX < nWidth; nX++ )
1341 						{
1342 							aCol = pReadAcc->GetPixel( nY, nX );
1343 							nR = aCol.GetRed();
1344 							nG = aCol.GetGreen();
1345 							nB = aCol.GetBlue();
1346 
1347 							if( nMinR <= nR && nMaxR >= nR &&
1348 								nMinG <= nG && nMaxG >= nG &&
1349 								nMinB <= nB && nMaxB >= nB )
1350 							{
1351 								pWriteAcc->SetPixel( nY, nX, aWhite );
1352 							}
1353 							else
1354 								pWriteAcc->SetPixel( nY, nX, aBlack );
1355 						}
1356 					}
1357 				}
1358 			}
1359 
1360 			( (Bitmap*) this )->ReleaseAccess( pReadAcc );
1361 			bRet = sal_True;
1362 		}
1363 
1364 		aNewBmp.ReleaseAccess( pWriteAcc );
1365 	}
1366 
1367 	if( bRet )
1368 	{
1369 		aNewBmp.maPrefSize = maPrefSize;
1370 		aNewBmp.maPrefMapMode = maPrefMapMode;
1371 	}
1372 	else
1373 		aNewBmp = Bitmap();
1374 
1375 	return aNewBmp;
1376 }
1377 
1378 // ------------------------------------------------------------------
1379 
1380 Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
1381 {
1382 	Region				aRegion;
1383 	Rectangle			aRect( rRect );
1384 	BitmapReadAccess*	pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
1385 
1386 	aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
1387 	aRect.Justify();
1388 
1389 	if( pReadAcc )
1390 	{
1391 		Rectangle			aSubRect;
1392 		const long			nLeft = aRect.Left();
1393 		const long			nTop = aRect.Top();
1394 		const long			nRight = aRect.Right();
1395 		const long			nBottom = aRect.Bottom();
1396 		const BitmapColor	aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
1397 
1398 		aRegion.ImplBeginAddRect();
1399 
1400 		for( long nY = nTop; nY <= nBottom; nY++ )
1401 		{
1402 			aSubRect.Top() = aSubRect.Bottom() = nY;
1403 
1404 			for( long nX = nLeft; nX <= nRight; )
1405 			{
1406 				while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
1407 					nX++;
1408 
1409 				if( nX <= nRight )
1410 				{
1411 					aSubRect.Left() = nX;
1412 
1413 					while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
1414 						nX++;
1415 
1416 					aSubRect.Right() = nX - 1L;
1417 					aRegion.ImplAddRect( aSubRect );
1418 				}
1419 			}
1420 		}
1421 
1422 		aRegion.ImplEndAddRect();
1423 		( (Bitmap*) this )->ReleaseAccess( pReadAcc );
1424 	}
1425 	else
1426 		aRegion = aRect;
1427 
1428 	return aRegion;
1429 }
1430 
1431 // ------------------------------------------------------------------
1432 
1433 sal_Bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
1434 {
1435 	BitmapReadAccess*	pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
1436 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1437 	sal_Bool				bRet = sal_False;
1438 
1439 	if( pMaskAcc && pAcc )
1440 	{
1441 		const long			nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
1442 		const long			nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
1443 		const BitmapColor	aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1444 		BitmapColor 		aReplace;
1445 
1446 		if( pAcc->HasPalette() )
1447 		{
1448 			const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount();
1449 			const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount();
1450 
1451 			// erst einmal naechste Farbe nehmen
1452 			aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
1453 
1454 			// falls Palettenbild, und die zu setzende Farbe ist nicht
1455 			// in der Palette, suchen wir nach freien Eintraegen (teuer)
1456 			if( pAcc->GetPaletteColor( (sal_uInt8) aReplace ) != BitmapColor( rReplaceColor ) )
1457 			{
1458 				// erst einmal nachsehen, ob wir unsere ReplaceColor
1459 				// nicht auf einen freien Platz am Ende der Palette
1460 				// setzen koennen
1461 				if( nActColors < nMaxColors )
1462 				{
1463 					pAcc->SetPaletteEntryCount( nActColors + 1 );
1464 					pAcc->SetPaletteColor( nActColors, rReplaceColor );
1465 					aReplace = BitmapColor( (sal_uInt8) nActColors );
1466 				}
1467 				else
1468 				{
1469 					sal_Bool* pFlags = new sal_Bool[ nMaxColors ];
1470 
1471 					// alle Eintraege auf 0 setzen
1472 					memset( pFlags, 0, nMaxColors );
1473 
1474 					for( long nY = 0L; nY < nHeight; nY++ )
1475 						for( long nX = 0L; nX < nWidth; nX++ )
1476 							pFlags[ (sal_uInt8) pAcc->GetPixel( nY, nX ) ] = sal_True;
1477 
1478 					for( sal_uInt16 i = 0UL; i < nMaxColors; i++ )
1479 					{
1480 						// Hurra, wir haben einen unbenutzten Eintrag
1481 						if( !pFlags[ i ] )
1482 						{
1483 							pAcc->SetPaletteColor( (sal_uInt16) i, rReplaceColor );
1484 							aReplace = BitmapColor( (sal_uInt8) i );
1485 						}
1486 					}
1487 
1488 					delete[] pFlags;
1489 				}
1490 			}
1491 		}
1492 		else
1493 			aReplace = rReplaceColor;
1494 
1495 		for( long nY = 0L; nY < nHeight; nY++ )
1496 			for( long nX = 0L; nX < nWidth; nX++ )
1497 				if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
1498 					pAcc->SetPixel( nY, nX, aReplace );
1499 
1500         bRet = sal_True;
1501 	}
1502 
1503 	( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
1504 	ReleaseAccess( pAcc );
1505 
1506 	return bRet;
1507 }
1508 
1509 // ------------------------------------------------------------------
1510 
1511 sal_Bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
1512 {
1513 	Bitmap				aNewBmp( GetSizePixel(), 24 );
1514 	BitmapReadAccess*	pAcc = AcquireReadAccess();
1515 	BitmapReadAccess*	pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
1516 	BitmapWriteAccess*	pNewAcc = aNewBmp.AcquireWriteAccess();
1517 	sal_Bool				bRet = sal_False;
1518 
1519 	if( pAcc && pAlphaAcc && pNewAcc )
1520 	{
1521 		BitmapColor	aCol;
1522 		const long	nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
1523 		const long	nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
1524 
1525 		for( long nY = 0L; nY < nHeight; nY++ )
1526 		{
1527 			for( long nX = 0L; nX < nWidth; nX++ )
1528 			{
1529 				aCol = pAcc->GetColor( nY, nX );
1530 				pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (sal_uInt8) pAlphaAcc->GetPixel( nY, nX ) ) );
1531 			}
1532 		}
1533 
1534 		bRet = sal_True;
1535 	}
1536 
1537 	ReleaseAccess( pAcc );
1538 	( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
1539 	aNewBmp.ReleaseAccess( pNewAcc );
1540 
1541 	if( bRet )
1542 	{
1543 		const MapMode	aMap( maPrefMapMode );
1544 		const Size		aSize( maPrefSize );
1545 
1546 		*this = aNewBmp;
1547 
1548 		maPrefMapMode = aMap;
1549 		maPrefSize = aSize;
1550 	}
1551 
1552 	return bRet;
1553 }
1554 
1555 // ------------------------------------------------------------------
1556 
1557 sal_Bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
1558 {
1559 	// Bitmaps with 1 bit color depth can cause problems
1560 	// if they have other entries than black/white in their palette
1561 	if( 1 == GetBitCount() )
1562 		Convert( BMP_CONVERSION_4BIT_COLORS );
1563 
1564 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1565 	sal_Bool				bRet = sal_False;
1566 
1567 	if( pAcc )
1568 	{
1569 		const long	nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
1570 		const long	nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
1571 		const long	nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
1572 		const long	nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
1573 		const long	nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
1574 		const long	nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
1575 
1576 		if( pAcc->HasPalette() )
1577 		{
1578 			for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
1579 			{
1580 				const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1581 
1582 				if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
1583 					nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
1584 					nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
1585 				{
1586 					pAcc->SetPaletteColor( i, rReplaceColor );
1587 				}
1588 			}
1589 		}
1590 		else
1591 		{
1592 			BitmapColor 		aCol;
1593 			const BitmapColor	aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
1594 
1595 			for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
1596 			{
1597 				for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
1598 				{
1599 					aCol = pAcc->GetPixel( nY, nX );
1600 
1601 					if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
1602 						nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
1603 						nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
1604 					{
1605 						pAcc->SetPixel( nY, nX, aReplace );
1606 					}
1607 				}
1608 			}
1609 		}
1610 
1611 		ReleaseAccess( pAcc );
1612 		bRet = sal_True;
1613 	}
1614 
1615 	return bRet;
1616 }
1617 
1618 // ------------------------------------------------------------------
1619 
1620 sal_Bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
1621 					  sal_uLong nColorCount, sal_uLong* _pTols )
1622 {
1623 	// Bitmaps with 1 bit color depth can cause problems
1624 	// if they have other entries than black/white in their palette
1625 	if( 1 == GetBitCount() )
1626 		Convert( BMP_CONVERSION_4BIT_COLORS );
1627 
1628 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1629 	sal_Bool				bRet = sal_False;
1630 
1631 	if( pAcc )
1632 	{
1633 		long*	pMinR = new long[ nColorCount ];
1634 		long*	pMaxR = new long[ nColorCount ];
1635 		long*	pMinG = new long[ nColorCount ];
1636 		long*	pMaxG = new long[ nColorCount ];
1637 		long*	pMinB = new long[ nColorCount ];
1638 		long*	pMaxB = new long[ nColorCount ];
1639 		long*	pTols;
1640 		sal_uLong	i;
1641 
1642 		if( !_pTols )
1643 		{
1644 			pTols = new long[ nColorCount ];
1645 			memset( pTols, 0, nColorCount * sizeof( long ) );
1646 		}
1647 		else
1648 			pTols = (long*) _pTols;
1649 
1650 		for( i = 0UL; i < nColorCount; i++ )
1651 		{
1652 			const Color&	rCol = pSearchColors[ i ];
1653 			const long		nTol = pTols[ i ];
1654 
1655 			pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
1656 			pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
1657 			pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
1658 			pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
1659 			pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
1660 			pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
1661 		}
1662 
1663 		if( pAcc->HasPalette() )
1664 		{
1665 			for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
1666 			{
1667 				const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
1668 
1669 				for( i = 0UL; i < nColorCount; i++ )
1670 				{
1671 					if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
1672 						pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
1673 						pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
1674 					{
1675 						pAcc->SetPaletteColor( (sal_uInt16)nEntry, pReplaceColors[ i ] );
1676 						break;
1677 					}
1678 				}
1679 			}
1680 		}
1681 		else
1682 		{
1683 			BitmapColor 	aCol;
1684 			BitmapColor*	pReplaces = new BitmapColor[ nColorCount ];
1685 
1686 			for( i = 0UL; i < nColorCount; i++ )
1687 				pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
1688 
1689 			for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
1690 			{
1691 				for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
1692 				{
1693 					aCol = pAcc->GetPixel( nY, nX );
1694 
1695 					for( i = 0UL; i < nColorCount; i++ )
1696 					{
1697 						if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
1698 							pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
1699 							pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
1700 						{
1701 							pAcc->SetPixel( nY, nX, pReplaces[ i ] );
1702 							break;
1703 						}
1704 					}
1705 				}
1706 			}
1707 
1708 			delete[] pReplaces;
1709 		}
1710 
1711 		if( !_pTols )
1712 			delete[] pTols;
1713 
1714 		delete[] pMinR;
1715 		delete[] pMaxR;
1716 		delete[] pMinG;
1717 		delete[] pMaxG;
1718 		delete[] pMinB;
1719 		delete[] pMaxB;
1720 		ReleaseAccess( pAcc );
1721 		bRet = sal_True;
1722 	}
1723 
1724 	return bRet;
1725 }
1726 
1727 // ------------------------------------------------------------------
1728 
1729 Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
1730 {
1731 	Bitmap aDispBmp( *this );
1732 
1733 	if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
1734 	{
1735 		ImpBitmap* pImpDispBmp = new ImpBitmap;
1736 
1737 		if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
1738 			aDispBmp.ImplSetImpBitmap( pImpDispBmp );
1739 		else
1740 			delete pImpDispBmp;
1741 	}
1742 
1743 	return aDispBmp;
1744 }
1745 
1746 // ------------------------------------------------------------------
1747 
1748 Bitmap Bitmap::GetColorTransformedBitmap( BmpColorMode eColorMode ) const
1749 {
1750     Bitmap  aRet;
1751 
1752 	if( BMP_COLOR_HIGHCONTRAST == eColorMode )
1753 	{
1754 	    Color*  pSrcColors = NULL;
1755     	Color*  pDstColors = NULL;
1756     	sal_uLong   nColorCount = 0;
1757 
1758 		aRet = *this;
1759 
1760     	Image::GetColorTransformArrays( (ImageColorTransform) eColorMode, pSrcColors, pDstColors, nColorCount );
1761 
1762     	if( nColorCount && pSrcColors && pDstColors )
1763        		aRet.Replace( pSrcColors, pDstColors, nColorCount );
1764 
1765     	delete[] pSrcColors;
1766     	delete[] pDstColors;
1767 	}
1768 	else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode ||
1769 			 BMP_COLOR_MONOCHROME_WHITE == eColorMode )
1770 	{
1771 		aRet = *this;
1772 		aRet.MakeMono( BMP_COLOR_MONOCHROME_THRESHOLD );
1773 	}
1774 
1775     return aRet;
1776 }
1777 
1778 // ------------------------------------------------------------------
1779 
1780 sal_Bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
1781 {
1782 	BitmapReadAccess*	pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
1783 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1784 	sal_Bool				bRet = sal_False;
1785 
1786 	if( pMaskAcc && pAcc )
1787 	{
1788 		const long			nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
1789 		const long			nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
1790 		const Color 		aColBlack( COL_BLACK );
1791 		BitmapColor 		aPixel;
1792 		BitmapColor 		aMaskPixel;
1793 		const BitmapColor	aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1794 		const BitmapColor	aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
1795 		const BitmapColor	aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
1796 
1797 		switch( eCombine )
1798 		{
1799 			case( BMP_COMBINE_COPY ):
1800 			{
1801 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1802 				{
1803 					if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
1804 						pAcc->SetPixel( nY, nX, aBlack );
1805 					else
1806 						pAcc->SetPixel( nY, nX, aWhite );
1807 				}
1808 			}
1809 			break;
1810 
1811 			case( BMP_COMBINE_INVERT ):
1812 			{
1813 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1814 				{
1815 					if( pAcc->GetPixel( nY, nX ) == aBlack )
1816 						pAcc->SetPixel( nY, nX, aWhite );
1817 					else
1818 						pAcc->SetPixel( nY, nX, aBlack );
1819 				}
1820 			}
1821 			break;
1822 
1823 			case( BMP_COMBINE_AND ):
1824 			{
1825 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1826 				{
1827 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
1828 						pAcc->SetPixel( nY, nX, aWhite );
1829 					else
1830 						pAcc->SetPixel( nY, nX, aBlack );
1831 				}
1832 			}
1833 			break;
1834 
1835 			case( BMP_COMBINE_NAND ):
1836 			{
1837 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1838 				{
1839 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
1840 						pAcc->SetPixel( nY, nX, aBlack );
1841 					else
1842 						pAcc->SetPixel( nY, nX, aWhite );
1843 				}
1844 			}
1845 			break;
1846 
1847 			case( BMP_COMBINE_OR ):
1848 			{
1849 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1850 				{
1851 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
1852 						pAcc->SetPixel( nY, nX, aWhite );
1853 					else
1854 						pAcc->SetPixel( nY, nX, aBlack );
1855 				}
1856 			}
1857 			break;
1858 
1859 			case( BMP_COMBINE_NOR ):
1860 			{
1861 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1862 				{
1863 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
1864 						pAcc->SetPixel( nY, nX, aBlack );
1865 					else
1866 						pAcc->SetPixel( nY, nX, aWhite );
1867 				}
1868 			}
1869 			break;
1870 
1871 			case( BMP_COMBINE_XOR ):
1872 			{
1873 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1874 				{
1875 					aPixel = pAcc->GetPixel( nY, nX );
1876 					aMaskPixel = pMaskAcc->GetPixel( nY, nX );
1877 
1878 					if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
1879 						( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
1880 					{
1881 						pAcc->SetPixel( nY, nX, aWhite );
1882 					}
1883 					else
1884 						pAcc->SetPixel( nY, nX, aBlack );
1885 				}
1886 			}
1887 			break;
1888 
1889 			case( BMP_COMBINE_NXOR ):
1890 			{
1891 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1892 				{
1893 					aPixel = pAcc->GetPixel( nY, nX );
1894 					aMaskPixel = pMaskAcc->GetPixel( nY, nX );
1895 
1896 					if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
1897 						( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
1898 					{
1899 						pAcc->SetPixel( nY, nX, aBlack );
1900 					}
1901 					else
1902 						pAcc->SetPixel( nY, nX, aWhite );
1903 				}
1904 			}
1905 			break;
1906 		}
1907 
1908         bRet = sal_True;
1909 	}
1910 
1911 	( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
1912 	ReleaseAccess( pAcc );
1913 
1914 	return bRet;
1915 }
1916 
1917 // ------------------------------------------------------------------
1918 
1919 sal_Bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor )
1920 {
1921     // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
1922     // optimizations. Might even consolidate the code here and there.
1923 
1924     // convert to a truecolor bitmap, if we're a paletted one. There's
1925     // room for tradeoff decision here, maybe later for an overload (or a flag)
1926     if( GetBitCount() <= 8 )
1927         Convert( BMP_CONVERSION_24BIT );
1928 
1929 	BitmapReadAccess*	pAlphaAcc = const_cast<AlphaMask&>(rAlpha).AcquireReadAccess();
1930 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1931 	sal_Bool				bRet = sal_False;
1932 
1933 	if( pAlphaAcc && pAcc )
1934 	{
1935 		const long			nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
1936 		const long			nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
1937 
1938 		for( long nY = 0L; nY < nHeight; ++nY )
1939 			for( long nX = 0L; nX < nWidth; ++nX )
1940                 pAcc->SetPixel( nY, nX,
1941                                 pAcc->GetPixel( nY, nX ).Merge( rBackgroundColor,
1942                                                                 255 - pAlphaAcc->GetPixel( nY, nX ) ) );
1943 
1944         bRet = sal_True;
1945 	}
1946 
1947 	const_cast<AlphaMask&>(rAlpha).ReleaseAccess( pAlphaAcc );
1948 	ReleaseAccess( pAcc );
1949 
1950 	return bRet;
1951 }
1952 
1953 // ------------------------------------------------------------------
1954 
1955 sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold )
1956 {
1957 	return ImplMakeMono( cThreshold );
1958 }
1959 
1960 // ------------------------------------------------------------------
1961 
1962 bool Bitmap::GetSystemData( BitmapSystemData& rData ) const
1963 {
1964     bool bRet = false;
1965     if( mpImpBmp )
1966     {
1967         SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap();
1968         if( pSalBitmap )
1969             bRet = pSalBitmap->GetSystemData( rData );
1970     }
1971 
1972     return bRet;
1973 }
1974