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