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