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