xref: /trunk/main/vcl/source/gdi/bitmap.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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