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