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