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