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->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] ); 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->GetPixel( 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->GetPixel( 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 aRegion.ImplBeginAddRect(); 1395 1396 for( long nY = nTop; nY <= nBottom; nY++ ) 1397 { 1398 aSubRect.Top() = aSubRect.Bottom() = nY; 1399 1400 for( long nX = nLeft; nX <= nRight; ) 1401 { 1402 while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) ) 1403 nX++; 1404 1405 if( nX <= nRight ) 1406 { 1407 aSubRect.Left() = nX; 1408 1409 while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) ) 1410 nX++; 1411 1412 aSubRect.Right() = nX - 1L; 1413 aRegion.ImplAddRect( aSubRect ); 1414 } 1415 } 1416 } 1417 1418 aRegion.ImplEndAddRect(); 1419 ( (Bitmap*) this )->ReleaseAccess( pReadAcc ); 1420 } 1421 else 1422 aRegion = aRect; 1423 1424 return aRegion; 1425 } 1426 1427 // ------------------------------------------------------------------ 1428 1429 sal_Bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor ) 1430 { 1431 BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess(); 1432 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 1433 sal_Bool bRet = sal_False; 1434 1435 if( pMaskAcc && pAcc ) 1436 { 1437 const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() ); 1438 const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() ); 1439 const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 1440 BitmapColor aReplace; 1441 1442 if( pAcc->HasPalette() ) 1443 { 1444 const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount(); 1445 const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount(); 1446 1447 // erst einmal naechste Farbe nehmen 1448 aReplace = pAcc->GetBestMatchingColor( rReplaceColor ); 1449 1450 // falls Palettenbild, und die zu setzende Farbe ist nicht 1451 // in der Palette, suchen wir nach freien Eintraegen (teuer) 1452 if( pAcc->GetPaletteColor( (sal_uInt8) aReplace ) != BitmapColor( rReplaceColor ) ) 1453 { 1454 // erst einmal nachsehen, ob wir unsere ReplaceColor 1455 // nicht auf einen freien Platz am Ende der Palette 1456 // setzen koennen 1457 if( nActColors < nMaxColors ) 1458 { 1459 pAcc->SetPaletteEntryCount( nActColors + 1 ); 1460 pAcc->SetPaletteColor( nActColors, rReplaceColor ); 1461 aReplace = BitmapColor( (sal_uInt8) nActColors ); 1462 } 1463 else 1464 { 1465 sal_Bool* pFlags = new sal_Bool[ nMaxColors ]; 1466 1467 // alle Eintraege auf 0 setzen 1468 memset( pFlags, 0, nMaxColors ); 1469 1470 for( long nY = 0L; nY < nHeight; nY++ ) 1471 for( long nX = 0L; nX < nWidth; nX++ ) 1472 pFlags[ (sal_uInt8) pAcc->GetPixel( nY, nX ) ] = sal_True; 1473 1474 for( sal_uInt16 i = 0UL; i < nMaxColors; i++ ) 1475 { 1476 // Hurra, wir haben einen unbenutzten Eintrag 1477 if( !pFlags[ i ] ) 1478 { 1479 pAcc->SetPaletteColor( (sal_uInt16) i, rReplaceColor ); 1480 aReplace = BitmapColor( (sal_uInt8) i ); 1481 } 1482 } 1483 1484 delete[] pFlags; 1485 } 1486 } 1487 } 1488 else 1489 aReplace = rReplaceColor; 1490 1491 for( long nY = 0L; nY < nHeight; nY++ ) 1492 for( long nX = 0L; nX < nWidth; nX++ ) 1493 if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite ) 1494 pAcc->SetPixel( nY, nX, aReplace ); 1495 1496 bRet = sal_True; 1497 } 1498 1499 ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc ); 1500 ReleaseAccess( pAcc ); 1501 1502 return bRet; 1503 } 1504 1505 // ------------------------------------------------------------------ 1506 1507 sal_Bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor ) 1508 { 1509 Bitmap aNewBmp( GetSizePixel(), 24 ); 1510 BitmapReadAccess* pAcc = AcquireReadAccess(); 1511 BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); 1512 BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess(); 1513 sal_Bool bRet = sal_False; 1514 1515 if( pAcc && pAlphaAcc && pNewAcc ) 1516 { 1517 BitmapColor aCol; 1518 const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() ); 1519 const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() ); 1520 1521 for( long nY = 0L; nY < nHeight; nY++ ) 1522 { 1523 for( long nX = 0L; nX < nWidth; nX++ ) 1524 { 1525 aCol = pAcc->GetColor( nY, nX ); 1526 pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (sal_uInt8) pAlphaAcc->GetPixel( nY, nX ) ) ); 1527 } 1528 } 1529 1530 bRet = sal_True; 1531 } 1532 1533 ReleaseAccess( pAcc ); 1534 ( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc ); 1535 aNewBmp.ReleaseAccess( pNewAcc ); 1536 1537 if( bRet ) 1538 { 1539 const MapMode aMap( maPrefMapMode ); 1540 const Size aSize( maPrefSize ); 1541 1542 *this = aNewBmp; 1543 1544 maPrefMapMode = aMap; 1545 maPrefSize = aSize; 1546 } 1547 1548 return bRet; 1549 } 1550 1551 // ------------------------------------------------------------------ 1552 1553 sal_Bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) 1554 { 1555 // Bitmaps with 1 bit color depth can cause problems 1556 // if they have other entries than black/white in their palette 1557 if( 1 == GetBitCount() ) 1558 Convert( BMP_CONVERSION_4BIT_COLORS ); 1559 1560 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 1561 sal_Bool bRet = sal_False; 1562 1563 if( pAcc ) 1564 { 1565 const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 ); 1566 const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 ); 1567 const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 ); 1568 const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 ); 1569 const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 ); 1570 const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 ); 1571 1572 if( pAcc->HasPalette() ) 1573 { 1574 for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ ) 1575 { 1576 const BitmapColor& rCol = pAcc->GetPaletteColor( i ); 1577 1578 if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() && 1579 nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() && 1580 nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() ) 1581 { 1582 pAcc->SetPaletteColor( i, rReplaceColor ); 1583 } 1584 } 1585 } 1586 else 1587 { 1588 BitmapColor aCol; 1589 const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) ); 1590 1591 for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ ) 1592 { 1593 for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ ) 1594 { 1595 aCol = pAcc->GetPixel( nY, nX ); 1596 1597 if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() && 1598 nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() && 1599 nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() ) 1600 { 1601 pAcc->SetPixel( nY, nX, aReplace ); 1602 } 1603 } 1604 } 1605 } 1606 1607 ReleaseAccess( pAcc ); 1608 bRet = sal_True; 1609 } 1610 1611 return bRet; 1612 } 1613 1614 // ------------------------------------------------------------------ 1615 1616 sal_Bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors, 1617 sal_uLong nColorCount, sal_uLong* _pTols ) 1618 { 1619 // Bitmaps with 1 bit color depth can cause problems 1620 // if they have other entries than black/white in their palette 1621 if( 1 == GetBitCount() ) 1622 Convert( BMP_CONVERSION_4BIT_COLORS ); 1623 1624 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 1625 sal_Bool bRet = sal_False; 1626 1627 if( pAcc ) 1628 { 1629 long* pMinR = new long[ nColorCount ]; 1630 long* pMaxR = new long[ nColorCount ]; 1631 long* pMinG = new long[ nColorCount ]; 1632 long* pMaxG = new long[ nColorCount ]; 1633 long* pMinB = new long[ nColorCount ]; 1634 long* pMaxB = new long[ nColorCount ]; 1635 long* pTols; 1636 sal_uLong i; 1637 1638 if( !_pTols ) 1639 { 1640 pTols = new long[ nColorCount ]; 1641 memset( pTols, 0, nColorCount * sizeof( long ) ); 1642 } 1643 else 1644 pTols = (long*) _pTols; 1645 1646 for( i = 0UL; i < nColorCount; i++ ) 1647 { 1648 const Color& rCol = pSearchColors[ i ]; 1649 const long nTol = pTols[ i ]; 1650 1651 pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 ); 1652 pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 ); 1653 pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 ); 1654 pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 ); 1655 pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 ); 1656 pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 ); 1657 } 1658 1659 if( pAcc->HasPalette() ) 1660 { 1661 for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ ) 1662 { 1663 const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry ); 1664 1665 for( i = 0UL; i < nColorCount; i++ ) 1666 { 1667 if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() && 1668 pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() && 1669 pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() ) 1670 { 1671 pAcc->SetPaletteColor( (sal_uInt16)nEntry, pReplaceColors[ i ] ); 1672 break; 1673 } 1674 } 1675 } 1676 } 1677 else 1678 { 1679 BitmapColor aCol; 1680 BitmapColor* pReplaces = new BitmapColor[ nColorCount ]; 1681 1682 for( i = 0UL; i < nColorCount; i++ ) 1683 pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] ); 1684 1685 for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ ) 1686 { 1687 for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ ) 1688 { 1689 aCol = pAcc->GetPixel( nY, nX ); 1690 1691 for( i = 0UL; i < nColorCount; i++ ) 1692 { 1693 if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() && 1694 pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() && 1695 pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() ) 1696 { 1697 pAcc->SetPixel( nY, nX, pReplaces[ i ] ); 1698 break; 1699 } 1700 } 1701 } 1702 } 1703 1704 delete[] pReplaces; 1705 } 1706 1707 if( !_pTols ) 1708 delete[] pTols; 1709 1710 delete[] pMinR; 1711 delete[] pMaxR; 1712 delete[] pMinG; 1713 delete[] pMaxG; 1714 delete[] pMinB; 1715 delete[] pMaxB; 1716 ReleaseAccess( pAcc ); 1717 bRet = sal_True; 1718 } 1719 1720 return bRet; 1721 } 1722 1723 // ------------------------------------------------------------------ 1724 1725 Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay ) 1726 { 1727 Bitmap aDispBmp( *this ); 1728 1729 if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) ) 1730 { 1731 ImpBitmap* pImpDispBmp = new ImpBitmap; 1732 1733 if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) ) 1734 aDispBmp.ImplSetImpBitmap( pImpDispBmp ); 1735 else 1736 delete pImpDispBmp; 1737 } 1738 1739 return aDispBmp; 1740 } 1741 1742 // ------------------------------------------------------------------ 1743 1744 Bitmap Bitmap::GetColorTransformedBitmap( BmpColorMode eColorMode ) const 1745 { 1746 Bitmap aRet; 1747 1748 if( BMP_COLOR_HIGHCONTRAST == eColorMode ) 1749 { 1750 Color* pSrcColors = NULL; 1751 Color* pDstColors = NULL; 1752 sal_uLong nColorCount = 0; 1753 1754 aRet = *this; 1755 1756 Image::GetColorTransformArrays( (ImageColorTransform) eColorMode, pSrcColors, pDstColors, nColorCount ); 1757 1758 if( nColorCount && pSrcColors && pDstColors ) 1759 aRet.Replace( pSrcColors, pDstColors, nColorCount ); 1760 1761 delete[] pSrcColors; 1762 delete[] pDstColors; 1763 } 1764 else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode || 1765 BMP_COLOR_MONOCHROME_WHITE == eColorMode ) 1766 { 1767 aRet = *this; 1768 aRet.MakeMono( BMP_COLOR_MONOCHROME_THRESHOLD ); 1769 } 1770 1771 return aRet; 1772 } 1773 1774 // ------------------------------------------------------------------ 1775 1776 sal_Bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine ) 1777 { 1778 BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess(); 1779 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 1780 sal_Bool bRet = sal_False; 1781 1782 if( pMaskAcc && pAcc ) 1783 { 1784 const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() ); 1785 const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() ); 1786 const Color aColBlack( COL_BLACK ); 1787 BitmapColor aPixel; 1788 BitmapColor aMaskPixel; 1789 const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 1790 const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) ); 1791 const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) ); 1792 1793 switch( eCombine ) 1794 { 1795 case( BMP_COMBINE_COPY ): 1796 { 1797 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1798 { 1799 if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack ) 1800 pAcc->SetPixel( nY, nX, aBlack ); 1801 else 1802 pAcc->SetPixel( nY, nX, aWhite ); 1803 } 1804 } 1805 break; 1806 1807 case( BMP_COMBINE_INVERT ): 1808 { 1809 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1810 { 1811 if( pAcc->GetPixel( nY, nX ) == aBlack ) 1812 pAcc->SetPixel( nY, nX, aWhite ); 1813 else 1814 pAcc->SetPixel( nY, nX, aBlack ); 1815 } 1816 } 1817 break; 1818 1819 case( BMP_COMBINE_AND ): 1820 { 1821 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1822 { 1823 if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack ) 1824 pAcc->SetPixel( nY, nX, aWhite ); 1825 else 1826 pAcc->SetPixel( nY, nX, aBlack ); 1827 } 1828 } 1829 break; 1830 1831 case( BMP_COMBINE_NAND ): 1832 { 1833 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1834 { 1835 if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack ) 1836 pAcc->SetPixel( nY, nX, aBlack ); 1837 else 1838 pAcc->SetPixel( nY, nX, aWhite ); 1839 } 1840 } 1841 break; 1842 1843 case( BMP_COMBINE_OR ): 1844 { 1845 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1846 { 1847 if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack ) 1848 pAcc->SetPixel( nY, nX, aWhite ); 1849 else 1850 pAcc->SetPixel( nY, nX, aBlack ); 1851 } 1852 } 1853 break; 1854 1855 case( BMP_COMBINE_NOR ): 1856 { 1857 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1858 { 1859 if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack ) 1860 pAcc->SetPixel( nY, nX, aBlack ); 1861 else 1862 pAcc->SetPixel( nY, nX, aWhite ); 1863 } 1864 } 1865 break; 1866 1867 case( BMP_COMBINE_XOR ): 1868 { 1869 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1870 { 1871 aPixel = pAcc->GetPixel( nY, nX ); 1872 aMaskPixel = pMaskAcc->GetPixel( nY, nX ); 1873 1874 if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) || 1875 ( aMaskPixel == aMaskBlack && aPixel != aBlack ) ) 1876 { 1877 pAcc->SetPixel( nY, nX, aWhite ); 1878 } 1879 else 1880 pAcc->SetPixel( nY, nX, aBlack ); 1881 } 1882 } 1883 break; 1884 1885 case( BMP_COMBINE_NXOR ): 1886 { 1887 for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) 1888 { 1889 aPixel = pAcc->GetPixel( nY, nX ); 1890 aMaskPixel = pMaskAcc->GetPixel( nY, nX ); 1891 1892 if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) || 1893 ( aMaskPixel == aMaskBlack && aPixel != aBlack ) ) 1894 { 1895 pAcc->SetPixel( nY, nX, aBlack ); 1896 } 1897 else 1898 pAcc->SetPixel( nY, nX, aWhite ); 1899 } 1900 } 1901 break; 1902 } 1903 1904 bRet = sal_True; 1905 } 1906 1907 ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc ); 1908 ReleaseAccess( pAcc ); 1909 1910 return bRet; 1911 } 1912 1913 // ------------------------------------------------------------------ 1914 1915 sal_Bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor ) 1916 { 1917 // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some 1918 // optimizations. Might even consolidate the code here and there. 1919 1920 // convert to a truecolor bitmap, if we're a paletted one. There's 1921 // room for tradeoff decision here, maybe later for an overload (or a flag) 1922 if( GetBitCount() <= 8 ) 1923 Convert( BMP_CONVERSION_24BIT ); 1924 1925 BitmapReadAccess* pAlphaAcc = const_cast<AlphaMask&>(rAlpha).AcquireReadAccess(); 1926 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 1927 sal_Bool bRet = sal_False; 1928 1929 if( pAlphaAcc && pAcc ) 1930 { 1931 const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() ); 1932 const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() ); 1933 1934 for( long nY = 0L; nY < nHeight; ++nY ) 1935 for( long nX = 0L; nX < nWidth; ++nX ) 1936 pAcc->SetPixel( nY, nX, 1937 pAcc->GetPixel( nY, nX ).Merge( rBackgroundColor, 1938 255 - pAlphaAcc->GetPixel( nY, nX ) ) ); 1939 1940 bRet = sal_True; 1941 } 1942 1943 const_cast<AlphaMask&>(rAlpha).ReleaseAccess( pAlphaAcc ); 1944 ReleaseAccess( pAcc ); 1945 1946 return bRet; 1947 } 1948 1949 // ------------------------------------------------------------------ 1950 1951 sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold ) 1952 { 1953 return ImplMakeMono( cThreshold ); 1954 } 1955 1956 // ------------------------------------------------------------------ 1957 1958 bool Bitmap::GetSystemData( BitmapSystemData& rData ) const 1959 { 1960 bool bRet = false; 1961 if( mpImpBmp ) 1962 { 1963 SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap(); 1964 if( pSalBitmap ) 1965 bRet = pSalBitmap->GetSystemData( rData ); 1966 } 1967 1968 return bRet; 1969 } 1970