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