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