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