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