xref: /trunk/main/vcl/source/gdi/bitmapex.cxx (revision e1d5bd03a6ea7ac2b26b792c9e2a94e9f347a43b)
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 <ctype.h>
28 
29 #include <rtl/crc.h>
30 
31 #include <tools/stream.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/rc.h>
34 
35 #include <vcl/salbtype.hxx>
36 #include <vcl/outdev.hxx>
37 #include <vcl/alpha.hxx>
38 #include <vcl/bitmapex.hxx>
39 #include <vcl/pngread.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/bmpacc.hxx>
42 
43 #include <image.h>
44 #include <impimagetree.hxx>
45 
46 // ------------
47 // - BitmapEx -
48 // ------------
49 
50 BitmapEx::BitmapEx() :
51         eTransparent( TRANSPARENT_NONE ),
52         bAlpha      ( sal_False )
53 {
54 }
55 
56 // ------------------------------------------------------------------
57 
58 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
59         aBitmap             ( rBitmapEx.aBitmap ),
60         aMask               ( rBitmapEx.aMask ),
61         aBitmapSize         ( rBitmapEx.aBitmapSize ),
62         aTransparentColor   ( rBitmapEx.aTransparentColor ),
63         eTransparent        ( rBitmapEx.eTransparent ),
64         bAlpha              ( rBitmapEx.bAlpha )
65 {
66 }
67 
68 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize ) :
69         eTransparent( TRANSPARENT_NONE ),
70         bAlpha      ( sal_False )
71 {
72     if( rBitmapEx.IsEmpty() )
73         return;
74 
75     aBitmap = Bitmap( aSize, rBitmapEx.aBitmap.GetBitCount() );
76     aBitmapSize = aSize;
77     if( rBitmapEx.IsAlpha() )
78     {
79         bAlpha = sal_True;
80         aMask = AlphaMask( aSize ).ImplGetBitmap();
81     }
82     else if( rBitmapEx.IsTransparent() )
83         aMask = Bitmap( aSize, rBitmapEx.aMask.GetBitCount() );
84 
85     Rectangle aDestRect( Point( 0, 0 ), aSize );
86     Rectangle aSrcRect( aSrc, aSize );
87     CopyPixel( aDestRect, aSrcRect, &rBitmapEx );
88 }
89 
90 // ------------------------------------------------------------------
91 
92 BitmapEx::BitmapEx( const ResId& rResId ) :
93         eTransparent( TRANSPARENT_NONE ),
94         bAlpha      ( sal_False )
95 {
96     static ImplImageTreeSingletonRef    aImageTree;
97     ResMgr*                             pResMgr = NULL;
98 
99     ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
100     pResMgr->ReadLong();
101     pResMgr->ReadLong();
102 
103     const String aFileName( pResMgr->ReadString() );
104     ::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName();
105 
106     if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this ) )
107     {
108 #ifdef DBG_UTIL
109         ByteString aErrorStr( "BitmapEx::BitmapEx( const ResId& rResId ): could not load image <" );
110         DBG_ERROR( ( ( aErrorStr += ByteString( aFileName, RTL_TEXTENCODING_ASCII_US ) ) += '>' ).GetBuffer() );
111 #endif
112     }
113 }
114 
115 // ------------------------------------------------------------------
116 
117 BitmapEx::BitmapEx( const Bitmap& rBmp ) :
118         aBitmap     ( rBmp ),
119         aBitmapSize ( aBitmap.GetSizePixel() ),
120         eTransparent( TRANSPARENT_NONE ),
121         bAlpha      ( sal_False )
122 {
123 }
124 
125 // ------------------------------------------------------------------
126 
127 BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
128         aBitmap         ( rBmp ),
129         aMask           ( rMask ),
130         aBitmapSize     ( aBitmap.GetSizePixel() ),
131         eTransparent    ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
132         bAlpha          ( sal_False )
133 {
134     DBG_ASSERT( !rMask || rBmp.GetSizePixel() == rMask.GetSizePixel(),
135                 "BitmapEx::BitmapEx(): size mismatch for bitmap and mask." );
136 
137     // #105489# Ensure a mask is exactly one bit deep
138     if( !!aMask && aMask.GetBitCount() != 1 )
139     {
140         OSL_TRACE("BitmapEx: forced mask to monochrome");
141         aMask.ImplMakeMono( 255 );
142     }
143 }
144 
145 // ------------------------------------------------------------------
146 
147 BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
148         aBitmap         ( rBmp ),
149         aMask           ( rAlphaMask.ImplGetBitmap() ),
150         aBitmapSize     ( aBitmap.GetSizePixel() ),
151         eTransparent    ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
152         bAlpha          ( !rAlphaMask ? sal_False : sal_True )
153 {
154     DBG_ASSERT( !rAlphaMask || rBmp.GetSizePixel() == rAlphaMask.GetSizePixel(),
155                 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
156 
157     // #i75531# the workaround below can go when
158     // X11SalGraphics::drawAlphaBitmap()'s render acceleration
159     // can handle the bitmap depth mismatch directly
160     if( aBitmap.GetBitCount() < aMask.GetBitCount() )
161         aBitmap.Convert( BMP_CONVERSION_24BIT );
162 }
163 
164 // ------------------------------------------------------------------
165 
166 BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
167         aBitmap             ( rBmp ),
168         aBitmapSize         ( aBitmap.GetSizePixel() ),
169         aTransparentColor   ( rTransparentColor ),
170         eTransparent        ( TRANSPARENT_BITMAP ),
171         bAlpha              ( sal_False )
172 {
173     aMask = aBitmap.CreateMask( aTransparentColor );
174 
175     DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(),
176                 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
177 }
178 
179 // ------------------------------------------------------------------
180 
181 BitmapEx::~BitmapEx()
182 {
183 }
184 
185 // ------------------------------------------------------------------
186 
187 // ------------------------------------------------------------------
188 
189 BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
190 {
191     if( &rBitmapEx != this )
192     {
193         aBitmap = rBitmapEx.aBitmap;
194         aMask = rBitmapEx.aMask;
195         aBitmapSize = rBitmapEx.aBitmapSize;
196         aTransparentColor = rBitmapEx.aTransparentColor;
197         eTransparent = rBitmapEx.eTransparent;
198         bAlpha = rBitmapEx.bAlpha;
199     }
200 
201     return *this;
202 }
203 
204 // ------------------------------------------------------------------
205 
206 sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
207 {
208     if( eTransparent != rBitmapEx.eTransparent )
209         return sal_False;
210 
211     if( aBitmap != rBitmapEx.aBitmap )
212         return sal_False;
213 
214     if( aBitmapSize != rBitmapEx.aBitmapSize )
215         return sal_False;
216 
217     if( eTransparent == TRANSPARENT_NONE )
218         return sal_True;
219 
220     if( eTransparent == TRANSPARENT_COLOR )
221         return aTransparentColor == rBitmapEx.aTransparentColor;
222 
223     return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
224 }
225 
226 // ------------------------------------------------------------------
227 
228 sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
229 {
230     return( rBmpEx.eTransparent == eTransparent &&
231             rBmpEx.bAlpha == bAlpha &&
232             rBmpEx.aBitmap.IsEqual( aBitmap ) &&
233             rBmpEx.aMask.IsEqual( aMask ) );
234 }
235 
236 // ------------------------------------------------------------------
237 
238 sal_Bool BitmapEx::IsEmpty() const
239 {
240     return( aBitmap.IsEmpty() && aMask.IsEmpty() );
241 }
242 
243 // ------------------------------------------------------------------
244 
245 void BitmapEx::SetEmpty()
246 {
247     aBitmap.SetEmpty();
248     aMask.SetEmpty();
249     eTransparent = TRANSPARENT_NONE;
250     bAlpha = sal_False;
251 }
252 
253 // ------------------------------------------------------------------
254 
255 void BitmapEx::Clear()
256 {
257     SetEmpty();
258 }
259 
260 // ------------------------------------------------------------------
261 
262 sal_Bool BitmapEx::IsTransparent() const
263 {
264     return( eTransparent != TRANSPARENT_NONE );
265 }
266 
267 // ------------------------------------------------------------------
268 
269 sal_Bool BitmapEx::IsAlpha() const
270 {
271     return( IsTransparent() && bAlpha );
272 }
273 
274 // ------------------------------------------------------------------
275 
276 Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
277 {
278     Bitmap aRetBmp( aBitmap );
279 
280     if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
281     {
282         Bitmap aTempMask;
283 
284         if( eTransparent == TRANSPARENT_COLOR )
285             aTempMask = aBitmap.CreateMask( aTransparentColor );
286         else
287             aTempMask = aMask;
288 
289         if( !IsAlpha() )
290             aRetBmp.Replace( aTempMask, *pTransReplaceColor );
291         else
292             aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
293     }
294 
295     return aRetBmp;
296 }
297 
298 // ------------------------------------------------------------------
299 
300 BitmapEx BitmapEx::GetColorTransformedBitmapEx( BmpColorMode eColorMode ) const
301 {
302     BitmapEx aRet;
303 
304     if( BMP_COLOR_HIGHCONTRAST == eColorMode )
305     {
306         aRet = *this;
307         aRet.aBitmap = aBitmap.GetColorTransformedBitmap( eColorMode );
308     }
309     else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode ||
310              BMP_COLOR_MONOCHROME_WHITE == eColorMode )
311     {
312         aRet = *this;
313         aRet.aBitmap = aRet.aBitmap.GetColorTransformedBitmap( eColorMode );
314 
315         if( !aRet.aMask.IsEmpty() )
316         {
317             aRet.aMask.CombineSimple( aRet.aBitmap, BMP_COMBINE_OR );
318             aRet.aBitmap.Erase( ( BMP_COLOR_MONOCHROME_BLACK == eColorMode ) ? COL_BLACK : COL_WHITE );
319 
320             DBG_ASSERT( aRet.aBitmap.GetSizePixel() == aRet.aMask.GetSizePixel(),
321                         "BitmapEx::GetColorTransformedBitmapEx(): size mismatch for bitmap and alpha mask." );
322         }
323     }
324 
325     return aRet;
326 }
327 
328 // ------------------------------------------------------------------
329 
330 Bitmap BitmapEx::GetMask() const
331 {
332     Bitmap aRet( aMask );
333 
334     if( IsAlpha() )
335         aRet.ImplMakeMono( 255 );
336 
337     return aRet;
338 }
339 
340 // ------------------------------------------------------------------
341 
342 AlphaMask BitmapEx::GetAlpha() const
343 {
344     AlphaMask aAlpha;
345 
346     if( IsAlpha() )
347         aAlpha.ImplSetBitmap( aMask );
348     else
349         aAlpha = aMask;
350 
351     return aAlpha;
352 }
353 
354 // ------------------------------------------------------------------
355 
356 sal_uLong BitmapEx::GetSizeBytes() const
357 {
358     sal_uLong nSizeBytes = aBitmap.GetSizeBytes();
359 
360     if( eTransparent == TRANSPARENT_BITMAP )
361         nSizeBytes += aMask.GetSizeBytes();
362 
363     return nSizeBytes;
364 }
365 
366 // ------------------------------------------------------------------
367 
368 sal_uLong BitmapEx::GetChecksum() const
369 {
370     sal_uInt32  nCrc = aBitmap.GetChecksum();
371     SVBT32      aBT32;
372 
373     UInt32ToSVBT32( (long) eTransparent, aBT32 );
374     nCrc = rtl_crc32( nCrc, aBT32, 4 );
375 
376     UInt32ToSVBT32( (long) bAlpha, aBT32 );
377     nCrc = rtl_crc32( nCrc, aBT32, 4 );
378 
379     if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
380     {
381         UInt32ToSVBT32( aMask.GetChecksum(), aBT32 );
382         nCrc = rtl_crc32( nCrc, aBT32, 4 );
383     }
384 
385     return nCrc;
386 }
387 
388 // ------------------------------------------------------------------
389 
390 void BitmapEx::SetSizePixel( const Size& rNewSize )
391 {
392     Scale( rNewSize );
393 }
394 
395 // ------------------------------------------------------------------
396 
397 sal_Bool BitmapEx::Invert()
398 {
399     sal_Bool bRet = sal_False;
400 
401     if( !!aBitmap )
402     {
403         bRet = aBitmap.Invert();
404 
405         if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
406             aTransparentColor = BitmapColor( aTransparentColor ).Invert();
407     }
408 
409     return bRet;
410 }
411 
412 // ------------------------------------------------------------------
413 
414 sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags )
415 {
416     sal_Bool bRet = sal_False;
417 
418     if( !!aBitmap )
419     {
420         bRet = aBitmap.Mirror( nMirrorFlags );
421 
422         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
423             aMask.Mirror( nMirrorFlags );
424     }
425 
426     return bRet;
427 }
428 
429 // ------------------------------------------------------------------
430 
431 sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
432 {
433     sal_Bool bRet = sal_False;
434 
435     if( !!aBitmap )
436     {
437         bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
438 
439         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
440             aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST );
441 
442         aBitmapSize = aBitmap.GetSizePixel();
443 
444         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
445                     "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
446     }
447 
448     return bRet;
449 }
450 
451 // ------------------------------------------------------------------------
452 
453 sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
454 {
455     sal_Bool bRet;
456 
457     if( aBitmapSize.Width() && aBitmapSize.Height() )
458     {
459         bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
460                       (double) rNewSize.Height() / aBitmapSize.Height(),
461                       nScaleFlag );
462     }
463     else
464         bRet = sal_True;
465 
466     return bRet;
467 }
468 
469 // ------------------------------------------------------------------
470 
471 sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
472 {
473     sal_Bool bRet = sal_False;
474 
475     if( !!aBitmap )
476     {
477         const sal_Bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
478 
479         if( bTransRotate )
480         {
481             if( eTransparent == TRANSPARENT_COLOR )
482                 bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
483             else
484             {
485                 bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
486 
487                 if( eTransparent == TRANSPARENT_NONE )
488                 {
489                     aMask = Bitmap( aBitmapSize, 1 );
490                     aMask.Erase( COL_BLACK );
491                     eTransparent = TRANSPARENT_BITMAP;
492                 }
493 
494                 if( bRet && !!aMask )
495                     aMask.Rotate( nAngle10, COL_WHITE );
496             }
497         }
498         else
499         {
500             bRet = aBitmap.Rotate( nAngle10, rFillColor );
501 
502             if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
503                 aMask.Rotate( nAngle10, COL_WHITE );
504         }
505 
506         aBitmapSize = aBitmap.GetSizePixel();
507 
508         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
509                     "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." );
510     }
511 
512     return bRet;
513 }
514 
515 // ------------------------------------------------------------------
516 
517 sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel )
518 {
519     sal_Bool bRet = sal_False;
520 
521     if( !!aBitmap )
522     {
523         bRet = aBitmap.Crop( rRectPixel );
524 
525         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
526             aMask.Crop( rRectPixel );
527 
528         aBitmapSize = aBitmap.GetSizePixel();
529 
530         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
531                     "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." );
532     }
533 
534     return bRet;
535 }
536 
537 // ------------------------------------------------------------------
538 
539 sal_Bool BitmapEx::Convert( BmpConversion eConversion )
540 {
541     return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False );
542 }
543 
544 // ------------------------------------------------------------------
545 
546 sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
547 {
548     return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False );
549 }
550 
551 // ------------------------------------------------------------------
552 
553 sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent )
554 {
555     sal_Bool bRet = sal_False;
556 
557     if( !!aBitmap )
558     {
559         bRet = aBitmap.Expand( nDX, nDY, pInitColor );
560 
561         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
562         {
563             Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
564             aMask.Expand( nDX, nDY, &aColor );
565         }
566 
567         aBitmapSize = aBitmap.GetSizePixel();
568 
569         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
570                     "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." );
571     }
572 
573     return bRet;
574 }
575 
576 // ------------------------------------------------------------------
577 
578 sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
579                           const BitmapEx* pBmpExSrc )
580 {
581     sal_Bool bRet = sal_False;
582 
583     if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
584     {
585         if( !aBitmap.IsEmpty() )
586         {
587             bRet = aBitmap.CopyPixel( rRectDst, rRectSrc );
588 
589             if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
590                 aMask.CopyPixel( rRectDst, rRectSrc );
591         }
592     }
593     else
594     {
595         if( !aBitmap.IsEmpty() )
596         {
597             bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap );
598 
599             if( bRet )
600             {
601                 if( pBmpExSrc->IsAlpha() )
602                 {
603                     if( IsAlpha() )
604                         // cast to use the optimized AlphaMask::CopyPixel
605                         ((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask );
606                     else if( IsTransparent() )
607                     {
608                         AlphaMask* pAlpha = new AlphaMask( aMask );
609 
610                         aMask = pAlpha->ImplGetBitmap();
611                         delete pAlpha;
612                         bAlpha = sal_True;
613                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
614                     }
615                     else
616                     {
617                         sal_uInt8   cBlack = 0;
618                         AlphaMask*  pAlpha = new AlphaMask( GetSizePixel(), &cBlack );
619 
620                         aMask = pAlpha->ImplGetBitmap();
621                         delete pAlpha;
622                         eTransparent = TRANSPARENT_BITMAP;
623                         bAlpha = sal_True;
624                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
625                     }
626                 }
627                 else if( pBmpExSrc->IsTransparent() )
628                 {
629                     if( IsAlpha() )
630                     {
631                         AlphaMask aAlpha( pBmpExSrc->aMask );
632                         aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
633                     }
634                     else if( IsTransparent() )
635                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
636                     else
637                     {
638                         aMask = Bitmap( GetSizePixel(), 1 );
639                         aMask.Erase( Color( COL_BLACK ) );
640                         eTransparent = TRANSPARENT_BITMAP;
641                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
642                     }
643                 }
644                 else if( IsAlpha() )
645                 {
646                     sal_uInt8         cBlack = 0;
647                     const AlphaMask   aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack );
648 
649                     aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
650                 }
651                 else if( IsTransparent() )
652                 {
653                     Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 );
654 
655                     aMaskSrc.Erase( Color( COL_BLACK ) );
656                     aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
657                 }
658             }
659         }
660     }
661 
662     return bRet;
663 }
664 
665 // ------------------------------------------------------------------
666 
667 sal_Bool BitmapEx::Erase( const Color& rFillColor )
668 {
669     sal_Bool bRet = sal_False;
670 
671     if( !!aBitmap )
672     {
673         bRet = aBitmap.Erase( rFillColor );
674 
675         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
676         {
677             // #104416# Respect transparency on fill color
678             if( rFillColor.GetTransparency() )
679             {
680                 const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
681                 aMask.Erase( aFill );
682             }
683             else
684             {
685                 const Color aBlack( COL_BLACK );
686                 aMask.Erase( aBlack );
687             }
688         }
689     }
690 
691     return bRet;
692 }
693 
694 // ------------------------------------------------------------------
695 
696 sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags )
697 {
698     return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False );
699 }
700 
701 // ------------------------------------------------------------------
702 
703 sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
704 {
705     return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False );
706 }
707 
708 // ------------------------------------------------------------------
709 
710 sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols )
711 {
712     return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False );
713 }
714 
715 // ------------------------------------------------------------------
716 
717 sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
718                        short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
719                        double fGamma, sal_Bool bInvert )
720 {
721     return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
722                                         nChannelRPercent, nChannelGPercent, nChannelBPercent,
723                                         fGamma, bInvert ) : sal_False );
724 }
725 
726 // ------------------------------------------------------------------
727 
728 sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
729 {
730     return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False );
731 }
732 
733 // ------------------------------------------------------------------
734 
735 void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
736 {
737     pOutDev->DrawBitmapEx( rDestPt, *this );
738 }
739 
740 // ------------------------------------------------------------------
741 
742 void BitmapEx::Draw( OutputDevice* pOutDev,
743                      const Point& rDestPt, const Size& rDestSize ) const
744 {
745     pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
746 }
747 
748 // ------------------------------------------------------------------
749 
750 void BitmapEx::Draw( OutputDevice* pOutDev,
751                      const Point& rDestPt, const Size& rDestSize,
752                      const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const
753 {
754     pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this );
755 }
756 
757 // ------------------------------------------------------------------
758 
759 sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
760 {
761     sal_uInt8 nTransparency(0xff);
762 
763     if(!aBitmap.IsEmpty())
764     {
765         if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height())
766         {
767             switch(eTransparent)
768             {
769                 case TRANSPARENT_NONE:
770                 {
771                     // not transparent, ergo all covered
772                     nTransparency = 0x00;
773                     break;
774                 }
775                 case TRANSPARENT_COLOR:
776                 {
777                     Bitmap aTestBitmap(aBitmap);
778                     BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
779 
780                     if(pRead)
781                     {
782                         const Color aColor = pRead->GetColor(nY, nX);
783 
784                         // if color is not equal to TransparentColor, we are not transparent
785                         if(aColor != aTransparentColor)
786                         {
787                             nTransparency = 0x00;
788                         }
789 
790                         aTestBitmap.ReleaseAccess(pRead);
791                     }
792                     break;
793                 }
794                 case TRANSPARENT_BITMAP:
795                 {
796                     if(!aMask.IsEmpty())
797                     {
798                         Bitmap aTestBitmap(aMask);
799                         BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
800 
801                         if(pRead)
802                         {
803                             const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
804 
805                             if(bAlpha)
806                             {
807                                 nTransparency = aBitmapColor.GetIndex();
808                             }
809                             else
810                             {
811                                 if(0x00 == aBitmapColor.GetIndex())
812                                 {
813                                     nTransparency = 0x00;
814                                 }
815                             }
816 
817                             aTestBitmap.ReleaseAccess(pRead);
818                         }
819                     }
820                     break;
821                 }
822             }
823         }
824     }
825 
826     return nTransparency;
827 }
828 
829 // ------------------------------------------------------------------
830 
831 SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx )
832 {
833     rBitmapEx.aBitmap.Write( rOStm );
834 
835     rOStm << (sal_uInt32) 0x25091962;
836     rOStm << (sal_uInt32) 0xACB20201;
837     rOStm << (sal_uInt8) rBitmapEx.eTransparent;
838 
839     if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP )
840         rBitmapEx.aMask.Write( rOStm );
841     else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR )
842         rOStm << rBitmapEx.aTransparentColor;
843 
844     return rOStm;
845 }
846 
847 // ------------------------------------------------------------------
848 
849 SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx )
850 {
851     Bitmap aBmp;
852 
853     rIStm >> aBmp;
854 
855     if( !rIStm.GetError() )
856     {
857         const sal_uLong nStmPos = rIStm.Tell();
858         sal_uInt32      nMagic1 = 0;
859         sal_uInt32      nMagic2 = 0;
860 
861         rIStm >> nMagic1 >> nMagic2;
862 
863         if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() )
864         {
865             rIStm.ResetError();
866             rIStm.Seek( nStmPos );
867             rBitmapEx = aBmp;
868         }
869         else
870         {
871             sal_uInt8 bTransparent = false;
872 
873             rIStm >> bTransparent;
874 
875             if( bTransparent == (sal_uInt8) TRANSPARENT_BITMAP )
876             {
877                 Bitmap aMask;
878 
879                 rIStm >> aMask;
880 
881                 if( !!aMask)
882                 {
883                     // do we have an alpha mask?
884                     if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() )
885                     {
886                         AlphaMask aAlpha;
887 
888                         // create alpha mask quickly (without greyscale conversion)
889                         aAlpha.ImplSetBitmap( aMask );
890                         rBitmapEx = BitmapEx( aBmp, aAlpha );
891                     }
892                     else
893                         rBitmapEx = BitmapEx( aBmp, aMask );
894                 }
895                 else
896                     rBitmapEx = aBmp;
897             }
898             else if( bTransparent == (sal_uInt8) TRANSPARENT_COLOR )
899             {
900                 Color aTransparentColor;
901 
902                 rIStm >> aTransparentColor;
903                 rBitmapEx = BitmapEx( aBmp, aTransparentColor );
904             }
905             else
906                 rBitmapEx = aBmp;
907         }
908     }
909 
910     return rIStm;
911 }
912