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
Bitmap()47 Bitmap::Bitmap() :
48 mpImpBmp( NULL )
49 {
50 }
51
52 // ------------------------------------------------------------------
53
Bitmap(const ResId & rResId)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
Bitmap(const Bitmap & rBitmap)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
Bitmap(SalBitmap * pSalBitmap)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
Bitmap(const Size & rSizePixel,sal_uInt16 nBitCount,const BitmapPalette * pPal)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
~Bitmap()152 Bitmap::~Bitmap()
153 {
154 ImplReleaseRef();
155 }
156
157 // ------------------------------------------------------------------
158
GetGreyPalette(int nEntries)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
IsGreyPalette() const229 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
operator =(const Bitmap & rBitmap)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
IsEqual(const Bitmap & rBmp) const265 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
SetEmpty()275 void Bitmap::SetEmpty()
276 {
277 maPrefMapMode = MapMode();
278 maPrefSize = Size();
279
280 ImplReleaseRef();
281 mpImpBmp = NULL;
282 }
283
284 // ------------------------------------------------------------------
285
GetSizePixel() const286 Size Bitmap::GetSizePixel() const
287 {
288 return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
289 }
290 // ------------------------------------------------------------------
291
SetSizePixel(const Size & rNewSize,sal_uInt32 nScaleFlag)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
GetSourceSizePixel() const302 Size Bitmap::GetSourceSizePixel() const
303 {
304 return( mpImpBmp ? mpImpBmp->ImplGetSourceSize() : Size() );
305 }
306
307 // ------------------------------------------------------------------
308
SetSourceSizePixel(const Size & rSize)309 void Bitmap::SetSourceSizePixel( const Size& rSize)
310 {
311 if( mpImpBmp )
312 mpImpBmp->ImplSetSourceSize( rSize);
313 }
314
315 // ------------------------------------------------------------------
316
GetBitCount() const317 sal_uInt16 Bitmap::GetBitCount() const
318 {
319 return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
320 }
321
322 // ------------------------------------------------------------------
323
HasGreyPalette() const324 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
GetChecksum() const365 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
ImplReleaseRef()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
ImplMakeUnique()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
ImplAssignWithSize(const Bitmap & rBitmap)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
ImplGetImpBitmap() const476 ImpBitmap* Bitmap::ImplGetImpBitmap() const
477 {
478 return mpImpBmp;
479 }
480
481 // ------------------------------------------------------------------
482
ImplSetImpBitmap(ImpBitmap * pImpBmp)483 void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
484 {
485 if( pImpBmp != mpImpBmp )
486 {
487 ImplReleaseRef();
488 mpImpBmp = pImpBmp;
489 }
490 }
491
492 // ------------------------------------------------------------------
493
AcquireReadAccess()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
AcquireWriteAccess()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
ReleaseAccess(BitmapReadAccess * pBitmapAccess)524 void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
525 {
526 delete pBitmapAccess;
527 }
528
529 // ------------------------------------------------------------------
530
Erase(const Color & rFillColor)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
Invert()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
Mirror(sal_uLong nMirrorFlags)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
Rotate(long nAngle10,const Color & rFillColor)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
Crop(const Rectangle & rRectPixel)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
CopyPixel(const Rectangle & rRectDst,const Rectangle & rRectSrc,const Bitmap * pBmpSrc)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
Expand(sal_uLong nDX,sal_uLong nDY,const Color * pInitColor)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
CreateMask(const Color & rTransColor,sal_uLong nTol) const1189 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
CreateRegion(const Color & rColor,const Rectangle & rRect) const1379 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
Replace(const Bitmap & rMask,const Color & rReplaceColor)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
Replace(const AlphaMask & rAlpha,const Color & rMergeColor)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
Replace(const Color & rSearchColor,const Color & rReplaceColor,sal_uLong nTol)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
Replace(const Color * pSearchColors,const Color * pReplaceColors,sal_uLong nColorCount,sal_uLong * _pTols)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
CreateDisplayBitmap(OutputDevice * pDisplay)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
GetColorTransformedBitmap(BmpColorMode eColorMode) const1799 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
CombineSimple(const Bitmap & rMask,BmpCombine eCombine)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
Blend(const AlphaMask & rAlpha,const Color & rBackgroundColor)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
MakeMono(sal_uInt8 cThreshold)2006 sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold )
2007 {
2008 return ImplMakeMono( cThreshold );
2009 }
2010
2011 // ------------------------------------------------------------------
2012
GetSystemData(BitmapSystemData & rData) const2013 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