1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <tools/stream.hxx>
23 #include <tools/poly.hxx>
25 #include <vcl/salbtype.hxx>
26 #include <vcl/bmpacc.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/bitmap.hxx>
29 #include <vcl/bitmapex.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/image.hxx>
41 Bitmap::Bitmap( const ResId
& rResId
) :
44 const BitmapEx
aBmpEx( rResId
);
46 if( !aBmpEx
.IsEmpty() )
47 *this = aBmpEx
.GetBitmap();
50 Bitmap::Bitmap( const Bitmap
& rBitmap
) :
51 maPrefMapMode ( rBitmap
.maPrefMapMode
),
52 maPrefSize ( rBitmap
.maPrefSize
)
54 mpImpBmp
= rBitmap
.mpImpBmp
;
57 mpImpBmp
->ImplIncRefCount();
60 Bitmap::Bitmap( SalBitmap
* pSalBitmap
)
62 mpImpBmp
= new ImpBitmap();
63 mpImpBmp
->ImplSetSalBitmap( pSalBitmap
);
64 maPrefMapMode
= MapMode( MAP_PIXEL
);
65 maPrefSize
= mpImpBmp
->ImplGetSize();
68 Bitmap::Bitmap( const Size
& rSizePixel
, sal_uInt16 nBitCount
, const BitmapPalette
* pPal
)
70 if( rSizePixel
.Width() && rSizePixel
.Height() )
73 BitmapPalette
* pRealPal
= NULL
;
81 aPal
.SetEntryCount( 2 );
82 aPal
[ 0 ] = Color( COL_BLACK
);
83 aPal
[ 1 ] = Color( COL_WHITE
);
85 else if( ( 4 == nBitCount
) || ( 8 == nBitCount
) )
87 aPal
.SetEntryCount( 1 << nBitCount
);
88 aPal
[ 0 ] = Color( COL_BLACK
);
89 aPal
[ 1 ] = Color( COL_BLUE
);
90 aPal
[ 2 ] = Color( COL_GREEN
);
91 aPal
[ 3 ] = Color( COL_CYAN
);
92 aPal
[ 4 ] = Color( COL_RED
);
93 aPal
[ 5 ] = Color( COL_MAGENTA
);
94 aPal
[ 6 ] = Color( COL_BROWN
);
95 aPal
[ 7 ] = Color( COL_GRAY
);
96 aPal
[ 8 ] = Color( COL_LIGHTGRAY
);
97 aPal
[ 9 ] = Color( COL_LIGHTBLUE
);
98 aPal
[ 10 ] = Color( COL_LIGHTGREEN
);
99 aPal
[ 11 ] = Color( COL_LIGHTCYAN
);
100 aPal
[ 12 ] = Color( COL_LIGHTRED
);
101 aPal
[ 13 ] = Color( COL_LIGHTMAGENTA
);
102 aPal
[ 14 ] = Color( COL_YELLOW
);
103 aPal
[ 15 ] = Color( COL_WHITE
);
105 // Create dither palette
108 sal_uInt16 nActCol
= 16;
110 for( sal_uInt16 nB
= 0; nB
< 256; nB
+= 51 )
111 for( sal_uInt16 nG
= 0; nG
< 256; nG
+= 51 )
112 for( sal_uInt16 nR
= 0; nR
< 256; nR
+= 51 )
113 aPal
[ nActCol
++ ] = BitmapColor( (sal_uInt8
) nR
, (sal_uInt8
) nG
, (sal_uInt8
) nB
);
115 // Set standard Office colors
116 aPal
[ nActCol
++ ] = BitmapColor( 0, 184, 255 );
121 pRealPal
= (BitmapPalette
*) pPal
;
124 mpImpBmp
= new ImpBitmap
;
125 mpImpBmp
->ImplCreate( rSizePixel
, nBitCount
, pRealPal
? *pRealPal
: aPal
);
136 const BitmapPalette
& Bitmap::GetGreyPalette( int nEntries
)
138 static BitmapPalette aGreyPalette2
;
139 static BitmapPalette aGreyPalette4
;
140 static BitmapPalette aGreyPalette16
;
141 static BitmapPalette aGreyPalette256
;
143 // Create greyscale palette with 2, 4, 16 or 256 entries
144 if( 2 == nEntries
|| 4 == nEntries
|| 16 == nEntries
|| 256 == nEntries
)
148 if( !aGreyPalette2
.GetEntryCount() )
150 aGreyPalette2
.SetEntryCount( 2 );
151 aGreyPalette2
[ 0 ] = BitmapColor( 0, 0, 0 );
152 aGreyPalette2
[ 1 ] = BitmapColor( 255, 255, 255 );
155 return aGreyPalette2
;
157 else if( 4 == nEntries
)
159 if( !aGreyPalette4
.GetEntryCount() )
161 aGreyPalette4
.SetEntryCount( 4 );
162 aGreyPalette4
[ 0 ] = BitmapColor( 0, 0, 0 );
163 aGreyPalette4
[ 1 ] = BitmapColor( 85, 85, 85 );
164 aGreyPalette4
[ 2 ] = BitmapColor( 170, 170, 170 );
165 aGreyPalette4
[ 3 ] = BitmapColor( 255, 255, 255 );
168 return aGreyPalette4
;
170 else if( 16 == nEntries
)
172 if( !aGreyPalette16
.GetEntryCount() )
174 sal_uInt8 cGrey
= 0, cGreyInc
= 17;
176 aGreyPalette16
.SetEntryCount( 16 );
178 for( sal_uInt16 i
= 0; i
< 16; i
++, cGrey
= sal::static_int_cast
<sal_uInt8
>(cGrey
+ cGreyInc
) )
179 aGreyPalette16
[ i
] = BitmapColor( cGrey
, cGrey
, cGrey
);
182 return aGreyPalette16
;
186 if( !aGreyPalette256
.GetEntryCount() )
188 aGreyPalette256
.SetEntryCount( 256 );
190 for( sal_uInt16 i
= 0; i
< 256; i
++ )
191 aGreyPalette256
[ i
] = BitmapColor( (sal_uInt8
) i
, (sal_uInt8
) i
, (sal_uInt8
) i
);
194 return aGreyPalette256
;
199 OSL_FAIL( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
200 return aGreyPalette2
;
204 bool BitmapPalette::IsGreyPalette() const
206 const int nEntryCount
= GetEntryCount();
207 if( !nEntryCount
) // NOTE: an empty palette means 1:1 mapping
209 // See above: only certain entry values will result in a valid call to GetGreyPalette
210 if( nEntryCount
== 2 || nEntryCount
== 4 || nEntryCount
== 16 || nEntryCount
== 256 )
212 const BitmapPalette
& rGreyPalette
= Bitmap::GetGreyPalette( nEntryCount
);
213 if( rGreyPalette
== *this )
218 // TODO: is it worth to compare the entries for the general case?
219 if (nEntryCount
== 2)
221 const BitmapColor
& rCol0(mpBitmapColor
[0]);
222 const BitmapColor
& rCol1(mpBitmapColor
[1]);
223 bRet
= rCol0
.GetRed() == rCol0
.GetGreen() && rCol0
.GetRed() == rCol0
.GetBlue() &&
224 rCol1
.GetRed() == rCol1
.GetGreen() && rCol1
.GetRed() == rCol1
.GetBlue();
229 Bitmap
& Bitmap::operator=( const Bitmap
& rBitmap
)
231 maPrefSize
= rBitmap
.maPrefSize
;
232 maPrefMapMode
= rBitmap
.maPrefMapMode
;
234 if ( rBitmap
.mpImpBmp
)
235 rBitmap
.mpImpBmp
->ImplIncRefCount();
238 mpImpBmp
= rBitmap
.mpImpBmp
;
243 sal_Bool
Bitmap::IsEqual( const Bitmap
& rBmp
) const
245 return( IsSameInstance( rBmp
) ||
246 ( rBmp
.GetSizePixel() == GetSizePixel() &&
247 rBmp
.GetBitCount() == GetBitCount() &&
248 rBmp
.GetChecksum() == GetChecksum() ) );
251 void Bitmap::SetEmpty()
253 maPrefMapMode
= MapMode();
260 Size
Bitmap::GetSizePixel() const
262 return( mpImpBmp
? mpImpBmp
->ImplGetSize() : Size() );
265 void Bitmap::SetSourceSizePixel( const Size
& rSize
)
268 mpImpBmp
->ImplSetSourceSize( rSize
);
271 sal_uInt16
Bitmap::GetBitCount() const
273 return( mpImpBmp
? mpImpBmp
->ImplGetBitCount() : 0 );
276 sal_Bool
Bitmap::HasGreyPalette() const
278 const sal_uInt16 nBitCount
= GetBitCount();
279 sal_Bool bRet
= nBitCount
== 1 ? sal_True
: sal_False
;
281 BitmapReadAccess
* pRAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
285 bRet
= pRAcc
->HasPalette() && pRAcc
->GetPalette().IsGreyPalette();
286 ( (Bitmap
*) this )->ReleaseAccess( pRAcc
);
292 sal_uLong
Bitmap::GetChecksum() const
294 sal_uLong nRet
= 0UL;
298 nRet
= mpImpBmp
->ImplGetChecksum();
302 BitmapReadAccess
* pRAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
304 if( pRAcc
&& pRAcc
->Width() && pRAcc
->Height() )
309 pRAcc
->ImplZeroInitUnusedBits();
311 UInt32ToSVBT32( pRAcc
->Width(), aBT32
);
312 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
314 UInt32ToSVBT32( pRAcc
->Height(), aBT32
);
315 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
317 UInt32ToSVBT32( pRAcc
->GetBitCount(), aBT32
);
318 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
320 UInt32ToSVBT32( pRAcc
->GetColorMask().GetRedMask(), aBT32
);
321 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
323 UInt32ToSVBT32( pRAcc
->GetColorMask().GetGreenMask(), aBT32
);
324 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
326 UInt32ToSVBT32( pRAcc
->GetColorMask().GetBlueMask(), aBT32
);
327 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
329 if( pRAcc
->HasPalette() )
331 nCrc
= rtl_crc32( nCrc
, pRAcc
->GetPalette().ImplGetColorBuffer(),
332 pRAcc
->GetPaletteEntryCount() * sizeof( BitmapColor
) );
335 nCrc
= rtl_crc32( nCrc
, pRAcc
->GetBuffer(), pRAcc
->GetScanlineSize() * pRAcc
->Height() );
337 mpImpBmp
->ImplSetChecksum( nRet
= nCrc
);
340 if (pRAcc
) ( (Bitmap
*) this )->ReleaseAccess( pRAcc
);
347 void Bitmap::ImplReleaseRef()
351 if( mpImpBmp
->ImplGetRefCount() > 1UL )
352 mpImpBmp
->ImplDecRefCount();
361 void Bitmap::ImplMakeUnique()
363 if( mpImpBmp
&& mpImpBmp
->ImplGetRefCount() > 1UL )
365 ImpBitmap
* pOldImpBmp
= mpImpBmp
;
367 pOldImpBmp
->ImplDecRefCount();
369 mpImpBmp
= new ImpBitmap
;
370 mpImpBmp
->ImplCreate( *pOldImpBmp
);
374 void Bitmap::ImplAssignWithSize( const Bitmap
& rBitmap
)
376 const Size
aOldSizePix( GetSizePixel() );
377 const Size
aNewSizePix( rBitmap
.GetSizePixel() );
378 const MapMode
aOldMapMode( maPrefMapMode
);
381 if( ( aOldSizePix
!= aNewSizePix
) && aOldSizePix
.Width() && aOldSizePix
.Height() )
383 aNewPrefSize
.Width() = FRound( maPrefSize
.Width() * aNewSizePix
.Width() / aOldSizePix
.Width() );
384 aNewPrefSize
.Height() = FRound( maPrefSize
.Height() * aNewSizePix
.Height() / aOldSizePix
.Height() );
387 aNewPrefSize
= maPrefSize
;
391 maPrefSize
= aNewPrefSize
;
392 maPrefMapMode
= aOldMapMode
;
395 ImpBitmap
* Bitmap::ImplGetImpBitmap() const
400 void Bitmap::ImplSetImpBitmap( ImpBitmap
* pImpBmp
)
402 if( pImpBmp
!= mpImpBmp
)
409 BitmapReadAccess
* Bitmap::AcquireReadAccess()
411 BitmapReadAccess
* pReadAccess
= new BitmapReadAccess( *this );
422 BitmapWriteAccess
* Bitmap::AcquireWriteAccess()
424 BitmapWriteAccess
* pWriteAccess
= new BitmapWriteAccess( *this );
435 void Bitmap::ReleaseAccess( BitmapReadAccess
* pBitmapAccess
)
437 delete pBitmapAccess
;
440 sal_Bool
Bitmap::Erase( const Color
& rFillColor
)
445 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
446 sal_Bool bRet
= sal_False
;
450 const sal_uLong nFormat
= pWriteAcc
->GetScanlineFormat();
451 sal_uInt8 cIndex
= 0;
452 sal_Bool bFast
= sal_False
;
456 case( BMP_FORMAT_1BIT_MSB_PAL
):
457 case( BMP_FORMAT_1BIT_LSB_PAL
):
459 cIndex
= (sal_uInt8
) pWriteAcc
->GetBestPaletteIndex( rFillColor
);
460 cIndex
= ( cIndex
? 255 : 0 );
465 case( BMP_FORMAT_4BIT_MSN_PAL
):
466 case( BMP_FORMAT_4BIT_LSN_PAL
):
468 cIndex
= (sal_uInt8
) pWriteAcc
->GetBestPaletteIndex( rFillColor
);
469 cIndex
= cIndex
| ( cIndex
<< 4 );
474 case( BMP_FORMAT_8BIT_PAL
):
476 cIndex
= (sal_uInt8
) pWriteAcc
->GetBestPaletteIndex( rFillColor
);
481 case( BMP_FORMAT_24BIT_TC_BGR
):
482 case( BMP_FORMAT_24BIT_TC_RGB
):
484 if( ( rFillColor
.GetRed() == rFillColor
.GetGreen() ) &&
485 ( rFillColor
.GetRed() == rFillColor
.GetBlue() ) )
487 cIndex
= rFillColor
.GetRed();
502 const sal_uLong nBufSize
= pWriteAcc
->GetScanlineSize() * pWriteAcc
->Height();
503 memset( pWriteAcc
->GetBuffer(), cIndex
, nBufSize
);
508 const Rectangle
aRect( aTmpPoint
, Size( pWriteAcc
->Width(), pWriteAcc
->Height() ) );
509 pWriteAcc
->SetFillColor( rFillColor
);
510 pWriteAcc
->FillRect( aRect
);
513 ReleaseAccess( pWriteAcc
);
520 sal_Bool
Bitmap::Invert()
522 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
523 sal_Bool bRet
= sal_False
;
527 if( pAcc
->HasPalette() )
529 BitmapPalette
aBmpPal( pAcc
->GetPalette() );
530 const sal_uInt16 nCount
= aBmpPal
.GetEntryCount();
532 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
533 aBmpPal
[ i
].Invert();
535 pAcc
->SetPalette( aBmpPal
);
539 const long nWidth
= pAcc
->Width();
540 const long nHeight
= pAcc
->Height();
542 for( long nX
= 0L; nX
< nWidth
; nX
++ )
543 for( long nY
= 0L; nY
< nHeight
; nY
++ )
544 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nY
, nX
).Invert() );
547 ReleaseAccess( pAcc
);
554 sal_Bool
Bitmap::Mirror( sal_uLong nMirrorFlags
)
556 sal_Bool bHorz
= ( ( nMirrorFlags
& BMP_MIRROR_HORZ
) == BMP_MIRROR_HORZ
);
557 sal_Bool bVert
= ( ( nMirrorFlags
& BMP_MIRROR_VERT
) == BMP_MIRROR_VERT
);
558 sal_Bool bRet
= sal_False
;
560 if( bHorz
&& !bVert
)
562 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
566 const long nWidth
= pAcc
->Width();
567 const long nHeight
= pAcc
->Height();
568 const long nWidth1
= nWidth
- 1L;
569 const long nWidth_2
= nWidth
>> 1L;
571 for( long nY
= 0L; nY
< nHeight
; nY
++ )
573 for( long nX
= 0L, nOther
= nWidth1
; nX
< nWidth_2
; nX
++, nOther
-- )
575 const BitmapColor
aTemp( pAcc
->GetPixel( nY
, nX
) );
577 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nY
, nOther
) );
578 pAcc
->SetPixel( nY
, nOther
, aTemp
);
582 ReleaseAccess( pAcc
);
586 else if( bVert
&& !bHorz
)
588 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
592 const long nScanSize
= pAcc
->GetScanlineSize();
593 sal_uInt8
* pBuffer
= new sal_uInt8
[ nScanSize
];
594 const long nHeight
= pAcc
->Height();
595 const long nHeight1
= nHeight
- 1L;
596 const long nHeight_2
= nHeight
>> 1L;
598 for( long nY
= 0L, nOther
= nHeight1
; nY
< nHeight_2
; nY
++, nOther
-- )
600 memcpy( pBuffer
, pAcc
->GetScanline( nY
), nScanSize
);
601 memcpy( pAcc
->GetScanline( nY
), pAcc
->GetScanline( nOther
), nScanSize
);
602 memcpy( pAcc
->GetScanline( nOther
), pBuffer
, nScanSize
);
606 ReleaseAccess( pAcc
);
610 else if( bHorz
&& bVert
)
612 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
616 const long nWidth
= pAcc
->Width();
617 const long nWidth1
= nWidth
- 1L;
618 const long nHeight
= pAcc
->Height();
619 long nHeight_2
= nHeight
>> 1;
621 for( long nY
= 0L, nOtherY
= nHeight
- 1L; nY
< nHeight_2
; nY
++, nOtherY
-- )
623 for( long nX
= 0L, nOtherX
= nWidth1
; nX
< nWidth
; nX
++, nOtherX
-- )
625 const BitmapColor
aTemp( pAcc
->GetPixel( nY
, nX
) );
627 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nOtherY
, nOtherX
) );
628 pAcc
->SetPixel( nOtherY
, nOtherX
, aTemp
);
632 // ggf. noch mittlere Zeile horizontal spiegeln
635 for( long nX
= 0L, nOtherX
= nWidth1
, nWidth_2
= nWidth
>> 1; nX
< nWidth_2
; nX
++, nOtherX
-- )
637 const BitmapColor
aTemp( pAcc
->GetPixel( nHeight_2
, nX
) );
638 pAcc
->SetPixel( nHeight_2
, nX
, pAcc
->GetPixel( nHeight_2
, nOtherX
) );
639 pAcc
->SetPixel( nHeight_2
, nOtherX
, aTemp
);
643 ReleaseAccess( pAcc
);
653 sal_Bool
Bitmap::Rotate( long nAngle10
, const Color
& rFillColor
)
655 sal_Bool bRet
= sal_False
;
658 nAngle10
= ( nAngle10
< 0L ) ? ( 3599L + nAngle10
) : nAngle10
;
662 else if( 1800L == nAngle10
)
663 bRet
= Mirror( BMP_MIRROR_HORZ
| BMP_MIRROR_VERT
);
666 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
671 const Size
aSizePix( GetSizePixel() );
673 if( ( 900L == nAngle10
) || ( 2700L == nAngle10
) )
675 const Size
aNewSizePix( aSizePix
.Height(), aSizePix
.Width() );
676 Bitmap
aNewBmp( aNewSizePix
, GetBitCount(), &pReadAcc
->GetPalette() );
677 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
681 const long nWidth
= aSizePix
.Width();
682 const long nWidth1
= nWidth
- 1L;
683 const long nHeight
= aSizePix
.Height();
684 const long nHeight1
= nHeight
- 1L;
685 const long nNewWidth
= aNewSizePix
.Width();
686 const long nNewHeight
= aNewSizePix
.Height();
688 if( 900L == nAngle10
)
690 for( long nY
= 0L, nOtherX
= nWidth1
; nY
< nNewHeight
; nY
++, nOtherX
-- )
691 for( long nX
= 0L, nOtherY
= 0L; nX
< nNewWidth
; nX
++ )
692 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nOtherY
++, nOtherX
) );
694 else if( 2700L == nAngle10
)
696 for( long nY
= 0L, nOtherX
= 0L; nY
< nNewHeight
; nY
++, nOtherX
++ )
697 for( long nX
= 0L, nOtherY
= nHeight1
; nX
< nNewWidth
; nX
++ )
698 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nOtherY
--, nOtherX
) );
701 aNewBmp
.ReleaseAccess( pWriteAcc
);
704 aRotatedBmp
= aNewBmp
;
709 Rectangle
aTmpRectangle( aTmpPoint
, aSizePix
);
710 Polygon
aPoly( aTmpRectangle
);
711 aPoly
.Rotate( aTmpPoint
, (sal_uInt16
) nAngle10
);
713 Rectangle
aNewBound( aPoly
.GetBoundRect() );
714 const Size
aNewSizePix( aNewBound
.GetSize() );
715 Bitmap
aNewBmp( aNewSizePix
, GetBitCount(), &pReadAcc
->GetPalette() );
716 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
720 const BitmapColor
aFillColor( pWriteAcc
->GetBestMatchingColor( rFillColor
) );
721 const double fCosAngle
= cos( nAngle10
* F_PI1800
);
722 const double fSinAngle
= sin( nAngle10
* F_PI1800
);
723 const double fXMin
= aNewBound
.Left();
724 const double fYMin
= aNewBound
.Top();
725 const long nWidth
= aSizePix
.Width();
726 const long nHeight
= aSizePix
.Height();
727 const long nNewWidth
= aNewSizePix
.Width();
728 const long nNewHeight
= aNewSizePix
.Height();
735 long* pCosX
= new long[ nNewWidth
];
736 long* pSinX
= new long[ nNewWidth
];
737 long* pCosY
= new long[ nNewHeight
];
738 long* pSinY
= new long[ nNewHeight
];
740 for ( nX
= 0; nX
< nNewWidth
; nX
++ )
742 const double fTmp
= ( fXMin
+ nX
) * 64.;
744 pCosX
[ nX
] = FRound( fCosAngle
* fTmp
);
745 pSinX
[ nX
] = FRound( fSinAngle
* fTmp
);
748 for ( nY
= 0; nY
< nNewHeight
; nY
++ )
750 const double fTmp
= ( fYMin
+ nY
) * 64.;
752 pCosY
[ nY
] = FRound( fCosAngle
* fTmp
);
753 pSinY
[ nY
] = FRound( fSinAngle
* fTmp
);
756 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
761 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
763 nRotX
= ( pCosX
[ nX
] - nSinY
) >> 6;
764 nRotY
= ( pSinX
[ nX
] + nCosY
) >> 6;
766 if ( ( nRotX
> -1L ) && ( nRotX
< nWidth
) && ( nRotY
> -1L ) && ( nRotY
< nHeight
) )
767 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nRotY
, nRotX
) );
769 pWriteAcc
->SetPixel( nY
, nX
, aFillColor
);
778 aNewBmp
.ReleaseAccess( pWriteAcc
);
781 aRotatedBmp
= aNewBmp
;
784 ReleaseAccess( pReadAcc
);
787 if( ( bRet
= !!aRotatedBmp
) == sal_True
)
788 ImplAssignWithSize( aRotatedBmp
);
794 sal_Bool
Bitmap::Crop( const Rectangle
& rRectPixel
)
796 const Size
aSizePix( GetSizePixel() );
797 Rectangle
aRect( rRectPixel
);
798 sal_Bool bRet
= sal_False
;
800 aRect
.Intersection( Rectangle( Point(), aSizePix
) );
802 if( !aRect
.IsEmpty() )
804 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
809 const Rectangle
aNewRect( aTmpPoint
, aRect
.GetSize() );
810 Bitmap
aNewBmp( aNewRect
.GetSize(), GetBitCount(), &pReadAcc
->GetPalette() );
811 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
815 const long nOldX
= aRect
.Left();
816 const long nOldY
= aRect
.Top();
817 const long nNewWidth
= aNewRect
.GetWidth();
818 const long nNewHeight
= aNewRect
.GetHeight();
820 for( long nY
= 0, nY2
= nOldY
; nY
< nNewHeight
; nY
++, nY2
++ )
821 for( long nX
= 0, nX2
= nOldX
; nX
< nNewWidth
; nX
++, nX2
++ )
822 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nY2
, nX2
) );
824 aNewBmp
.ReleaseAccess( pWriteAcc
);
828 ReleaseAccess( pReadAcc
);
831 ImplAssignWithSize( aNewBmp
);
838 sal_Bool
Bitmap::CopyPixel( const Rectangle
& rRectDst
,
839 const Rectangle
& rRectSrc
, const Bitmap
* pBmpSrc
)
841 const Size
aSizePix( GetSizePixel() );
842 Rectangle
aRectDst( rRectDst
);
843 sal_Bool bRet
= sal_False
;
845 aRectDst
.Intersection( Rectangle( Point(), aSizePix
) );
847 if( !aRectDst
.IsEmpty() )
849 if( pBmpSrc
&& ( *pBmpSrc
!= *this ) )
851 Bitmap
* pSrc
= (Bitmap
*) pBmpSrc
;
852 const Size
aCopySizePix( pSrc
->GetSizePixel() );
853 Rectangle
aRectSrc( rRectSrc
);
854 const sal_uInt16 nSrcBitCount
= pBmpSrc
->GetBitCount();
855 const sal_uInt16 nDstBitCount
= GetBitCount();
857 if( nSrcBitCount
> nDstBitCount
)
859 long nNextIndex
= 0L;
861 if( ( nSrcBitCount
== 24 ) && ( nDstBitCount
< 24 ) )
862 Convert( BMP_CONVERSION_24BIT
);
863 else if( ( nSrcBitCount
== 8 ) && ( nDstBitCount
< 8 ) )
865 Convert( BMP_CONVERSION_8BIT_COLORS
);
868 else if( ( nSrcBitCount
== 4 ) && ( nDstBitCount
< 4 ) )
870 Convert( BMP_CONVERSION_4BIT_COLORS
);
876 BitmapReadAccess
* pSrcAcc
= pSrc
->AcquireReadAccess();
877 BitmapWriteAccess
* pDstAcc
= AcquireWriteAccess();
879 if( pSrcAcc
&& pDstAcc
)
881 const long nSrcCount
= pDstAcc
->GetPaletteEntryCount();
882 const long nDstCount
= 1 << nDstBitCount
;
885 for( long i
= 0L; ( i
< nSrcCount
) && ( nNextIndex
< nSrcCount
); i
++ )
887 const BitmapColor
& rSrcCol
= pSrcAcc
->GetPaletteColor( (sal_uInt16
) i
);
891 for( long j
= 0L; j
< nDstCount
; j
++ )
893 if( rSrcCol
== pDstAcc
->GetPaletteColor( (sal_uInt16
) j
) )
901 pDstAcc
->SetPaletteColor( (sal_uInt16
) nNextIndex
++, rSrcCol
);
906 pSrc
->ReleaseAccess( pSrcAcc
);
909 ReleaseAccess( pDstAcc
);
913 aRectSrc
.Intersection( Rectangle( Point(), aCopySizePix
) );
915 if( !aRectSrc
.IsEmpty() )
917 BitmapReadAccess
* pReadAcc
= pSrc
->AcquireReadAccess();
921 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
925 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
926 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
927 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
928 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
929 long nDstY
= aRectDst
.Top();
931 if( pReadAcc
->HasPalette() && pWriteAcc
->HasPalette() )
933 const sal_uInt16 nCount
= pReadAcc
->GetPaletteEntryCount();
934 sal_uInt8
* pMap
= new sal_uInt8
[ nCount
];
936 // Create index map for the color table, as the bitmap should be copied
937 // retaining it's color information relatively well
938 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
939 pMap
[ i
] = (sal_uInt8
) pWriteAcc
->GetBestPaletteIndex( pReadAcc
->GetPaletteColor( i
) );
941 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
942 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
943 pWriteAcc
->SetPixelIndex( nDstY
, nDstX
, pMap
[ pReadAcc
->GetPixelIndex( nSrcY
, nSrcX
) ] );
947 else if( pReadAcc
->HasPalette() )
949 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
950 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
951 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPaletteColor( pReadAcc
->GetPixelIndex( nSrcY
, nSrcX
) ) );
954 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
955 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
956 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPixel( nSrcY
, nSrcX
) );
958 ReleaseAccess( pWriteAcc
);
959 bRet
= ( nWidth
> 0L ) && ( nHeight
> 0L );
962 pSrc
->ReleaseAccess( pReadAcc
);
968 Rectangle
aRectSrc( rRectSrc
);
970 aRectSrc
.Intersection( Rectangle( Point(), aSizePix
) );
972 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
974 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
978 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
979 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
980 const long nSrcX
= aRectSrc
.Left();
981 const long nSrcY
= aRectSrc
.Top();
982 const long nSrcEndX1
= nSrcX
+ nWidth
- 1L;
983 const long nSrcEndY1
= nSrcY
+ nHeight
- 1L;
984 const long nDstX
= aRectDst
.Left();
985 const long nDstY
= aRectDst
.Top();
986 const long nDstEndX1
= nDstX
+ nWidth
- 1L;
987 const long nDstEndY1
= nDstY
+ nHeight
- 1L;
989 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
991 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
992 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
993 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
995 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
997 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
998 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
999 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1001 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
1003 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
1004 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
1005 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1009 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
1010 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
1011 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1014 ReleaseAccess( pWriteAcc
);
1024 sal_Bool
Bitmap::Expand( sal_uLong nDX
, sal_uLong nDY
, const Color
* pInitColor
)
1026 sal_Bool bRet
= sal_False
;
1030 const Size
aSizePixel( GetSizePixel() );
1031 const long nWidth
= aSizePixel
.Width();
1032 const long nHeight
= aSizePixel
.Height();
1033 const Size
aNewSize( nWidth
+ nDX
, nHeight
+ nDY
);
1034 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1038 BitmapPalette
aBmpPal( pReadAcc
->GetPalette() );
1039 Bitmap
aNewBmp( aNewSize
, GetBitCount(), &aBmpPal
);
1040 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1045 const long nNewX
= nWidth
;
1046 const long nNewY
= nHeight
;
1047 const long nNewWidth
= pWriteAcc
->Width();
1048 const long nNewHeight
= pWriteAcc
->Height();
1053 aColor
= pWriteAcc
->GetBestMatchingColor( *pInitColor
);
1055 for( nY
= 0L; nY
< nHeight
; nY
++ )
1057 pWriteAcc
->CopyScanline( nY
, *pReadAcc
);
1059 if( pInitColor
&& nDX
)
1060 for( nX
= nNewX
; nX
< nNewWidth
; nX
++ )
1061 pWriteAcc
->SetPixel( nY
, nX
, aColor
);
1064 if( pInitColor
&& nDY
)
1065 for( nY
= nNewY
; nY
< nNewHeight
; nY
++ )
1066 for( nX
= 0; nX
< nNewWidth
; nX
++ )
1067 pWriteAcc
->SetPixel( nY
, nX
, aColor
);
1069 aNewBmp
.ReleaseAccess( pWriteAcc
);
1073 ReleaseAccess( pReadAcc
);
1076 ImplAssignWithSize( aNewBmp
);
1083 Bitmap
Bitmap::CreateMask( const Color
& rTransColor
, sal_uLong nTol
) const
1085 Bitmap
aNewBmp( GetSizePixel(), 1 );
1086 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1087 sal_Bool bRet
= sal_False
;
1091 BitmapReadAccess
* pReadAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
1095 const long nWidth
= pReadAcc
->Width();
1096 const long nHeight
= pReadAcc
->Height();
1097 const BitmapColor
aBlack( pWriteAcc
->GetBestMatchingColor( Color( COL_BLACK
) ) );
1098 const BitmapColor
aWhite( pWriteAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1102 const BitmapColor
aTest( pReadAcc
->GetBestMatchingColor( rTransColor
) );
1105 if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL
||
1106 pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL
)
1108 // optimized for 4Bit-MSN/LSN source palette
1109 const sal_uInt8 cTest
= aTest
.GetIndex();
1110 const long nShiftInit
= ( ( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL
) ? 4 : 0 );
1112 if( pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
&&
1113 aWhite
.GetIndex() == 1 )
1115 // optimized for 1Bit-MSB destination palette
1116 for( nY
= 0L; nY
< nHeight
; nY
++ )
1118 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1119 Scanline pDst
= pWriteAcc
->GetScanline( nY
);
1121 for( nX
= 0L, nShift
= nShiftInit
; nX
< nWidth
; nX
++, nShift
^= 4 )
1123 if( cTest
== ( ( pSrc
[ nX
>> 1 ] >> nShift
) & 0x0f ) )
1124 pDst
[ nX
>> 3 ] |= 1 << ( 7 - ( nX
& 7 ) );
1126 pDst
[ nX
>> 3 ] &= ~( 1 << ( 7 - ( nX
& 7 ) ) );
1132 for( nY
= 0L; nY
< nHeight
; nY
++ )
1134 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1136 for( nX
= 0L, nShift
= nShiftInit
; nX
< nWidth
; nX
++, nShift
^= 4 )
1138 if( cTest
== ( ( pSrc
[ nX
>> 1 ] >> nShift
) & 0x0f ) )
1139 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1141 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1146 else if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
)
1148 // optimized for 8Bit source palette
1149 const sal_uInt8 cTest
= aTest
.GetIndex();
1151 if( pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
&&
1152 aWhite
.GetIndex() == 1 )
1154 // optimized for 1Bit-MSB destination palette
1155 for( nY
= 0L; nY
< nHeight
; nY
++ )
1157 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1158 Scanline pDst
= pWriteAcc
->GetScanline( nY
);
1159 for( nX
= 0L; nX
< nWidth
; nX
++ )
1161 if( cTest
== pSrc
[ nX
] )
1162 pDst
[ nX
>> 3 ] |= 1 << ( 7 - ( nX
& 7 ) );
1164 pDst
[ nX
>> 3 ] &= ~( 1 << ( 7 - ( nX
& 7 ) ) );
1170 for( nY
= 0L; nY
< nHeight
; nY
++ )
1172 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1173 for( nX
= 0L; nX
< nWidth
; nX
++ )
1175 if( cTest
== pSrc
[ nX
] )
1176 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1178 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1186 for( nY
= 0L; nY
< nHeight
; nY
++ )
1188 for( nX
= 0L; nX
< nWidth
; nX
++ )
1190 if( aTest
== pReadAcc
->GetPixel( nY
, nX
) )
1191 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1193 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1202 const long nMinR
= MinMax( (long) rTransColor
.GetRed() - nTol
, 0, 255 );
1203 const long nMaxR
= MinMax( (long) rTransColor
.GetRed() + nTol
, 0, 255 );
1204 const long nMinG
= MinMax( (long) rTransColor
.GetGreen() - nTol
, 0, 255 );
1205 const long nMaxG
= MinMax( (long) rTransColor
.GetGreen() + nTol
, 0, 255 );
1206 const long nMinB
= MinMax( (long) rTransColor
.GetBlue() - nTol
, 0, 255 );
1207 const long nMaxB
= MinMax( (long) rTransColor
.GetBlue() + nTol
, 0, 255 );
1209 if( pReadAcc
->HasPalette() )
1211 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1213 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1215 aCol
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixelIndex( nY
, nX
) );
1217 nG
= aCol
.GetGreen();
1218 nB
= aCol
.GetBlue();
1220 if( nMinR
<= nR
&& nMaxR
>= nR
&&
1221 nMinG
<= nG
&& nMaxG
>= nG
&&
1222 nMinB
<= nB
&& nMaxB
>= nB
)
1224 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1227 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1233 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1235 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1237 aCol
= pReadAcc
->GetPixel( nY
, nX
);
1239 nG
= aCol
.GetGreen();
1240 nB
= aCol
.GetBlue();
1242 if( nMinR
<= nR
&& nMaxR
>= nR
&&
1243 nMinG
<= nG
&& nMaxG
>= nG
&&
1244 nMinB
<= nB
&& nMaxB
>= nB
)
1246 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1249 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1255 ( (Bitmap
*) this )->ReleaseAccess( pReadAcc
);
1259 aNewBmp
.ReleaseAccess( pWriteAcc
);
1264 aNewBmp
.maPrefSize
= maPrefSize
;
1265 aNewBmp
.maPrefMapMode
= maPrefMapMode
;
1273 Region
Bitmap::CreateRegion( const Color
& rColor
, const Rectangle
& rRect
) const
1276 Rectangle
aRect( rRect
);
1277 BitmapReadAccess
* pReadAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
1279 aRect
.Intersection( Rectangle( Point(), GetSizePixel() ) );
1285 const long nLeft
= aRect
.Left();
1286 const long nTop
= aRect
.Top();
1287 const long nRight
= aRect
.Right();
1288 const long nBottom
= aRect
.Bottom();
1289 const BitmapColor
aMatch( pReadAcc
->GetBestMatchingColor( rColor
) );
1291 aRegion
.ImplBeginAddRect();
1293 for( long nY
= nTop
; nY
<= nBottom
; nY
++ )
1295 aSubRect
.Top() = aSubRect
.Bottom() = nY
;
1297 for( long nX
= nLeft
; nX
<= nRight
; )
1299 while( ( nX
<= nRight
) && ( aMatch
!= pReadAcc
->GetPixel( nY
, nX
) ) )
1304 aSubRect
.Left() = nX
;
1306 while( ( nX
<= nRight
) && ( aMatch
== pReadAcc
->GetPixel( nY
, nX
) ) )
1309 aSubRect
.Right() = nX
- 1L;
1310 aRegion
.ImplAddRect( aSubRect
);
1315 aRegion
.ImplEndAddRect();
1316 ( (Bitmap
*) this )->ReleaseAccess( pReadAcc
);
1324 sal_Bool
Bitmap::Replace( const Bitmap
& rMask
, const Color
& rReplaceColor
)
1326 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
1327 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1328 sal_Bool bRet
= sal_False
;
1330 if( pMaskAcc
&& pAcc
)
1332 const long nWidth
= std::min( pMaskAcc
->Width(), pAcc
->Width() );
1333 const long nHeight
= std::min( pMaskAcc
->Height(), pAcc
->Height() );
1334 const BitmapColor
aMaskWhite( pMaskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1335 BitmapColor aReplace
;
1337 if( pAcc
->HasPalette() )
1339 const sal_uInt16 nActColors
= pAcc
->GetPaletteEntryCount();
1340 const sal_uInt16 nMaxColors
= 1 << pAcc
->GetBitCount();
1342 // default to the nearest color
1343 aReplace
= pAcc
->GetBestMatchingColor( rReplaceColor
);
1345 // for paletted images without a matching palette entry
1346 // look for an unused palette entry (NOTE: expensive!)
1347 if( pAcc
->GetPaletteColor( aReplace
.GetIndex() ) != BitmapColor( rReplaceColor
) )
1349 // if the palette has empty entries use the last one
1350 if( nActColors
< nMaxColors
)
1352 pAcc
->SetPaletteEntryCount( nActColors
+ 1 );
1353 pAcc
->SetPaletteColor( nActColors
, rReplaceColor
);
1354 aReplace
= BitmapColor( (sal_uInt8
) nActColors
);
1358 sal_Bool
* pFlags
= new sal_Bool
[ nMaxColors
];
1360 // Set all entries to 0
1361 memset( pFlags
, 0, nMaxColors
);
1363 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1364 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1365 pFlags
[ pAcc
->GetPixelIndex( nY
, nX
) ] = sal_True
;
1367 for( sal_uInt16 i
= 0UL; i
< nMaxColors
; i
++ )
1369 // Hurray, we do have an unsused entry
1372 pAcc
->SetPaletteColor( (sal_uInt16
) i
, rReplaceColor
);
1373 aReplace
= BitmapColor( (sal_uInt8
) i
);
1382 aReplace
= rReplaceColor
;
1384 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1385 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1386 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskWhite
)
1387 pAcc
->SetPixel( nY
, nX
, aReplace
);
1392 ( (Bitmap
&) rMask
).ReleaseAccess( pMaskAcc
);
1393 ReleaseAccess( pAcc
);
1398 sal_Bool
Bitmap::Replace( const AlphaMask
& rAlpha
, const Color
& rMergeColor
)
1400 Bitmap
aNewBmp( GetSizePixel(), 24 );
1401 BitmapReadAccess
* pAcc
= AcquireReadAccess();
1402 BitmapReadAccess
* pAlphaAcc
= ( (AlphaMask
&) rAlpha
).AcquireReadAccess();
1403 BitmapWriteAccess
* pNewAcc
= aNewBmp
.AcquireWriteAccess();
1404 sal_Bool bRet
= sal_False
;
1406 if( pAcc
&& pAlphaAcc
&& pNewAcc
)
1409 const long nWidth
= std::min( pAlphaAcc
->Width(), pAcc
->Width() );
1410 const long nHeight
= std::min( pAlphaAcc
->Height(), pAcc
->Height() );
1412 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1414 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1416 aCol
= pAcc
->GetColor( nY
, nX
);
1417 pNewAcc
->SetPixel( nY
, nX
, aCol
.Merge( rMergeColor
, 255 - pAlphaAcc
->GetPixelIndex( nY
, nX
) ) );
1424 ReleaseAccess( pAcc
);
1425 ( (AlphaMask
&) rAlpha
).ReleaseAccess( pAlphaAcc
);
1426 aNewBmp
.ReleaseAccess( pNewAcc
);
1430 const MapMode
aMap( maPrefMapMode
);
1431 const Size
aSize( maPrefSize
);
1435 maPrefMapMode
= aMap
;
1442 sal_Bool
Bitmap::Replace( const Color
& rSearchColor
, const Color
& rReplaceColor
, sal_uLong nTol
)
1444 // Bitmaps with 1 bit color depth can cause problems
1445 // if they have other entries than black/white in their palette
1446 if( 1 == GetBitCount() )
1447 Convert( BMP_CONVERSION_4BIT_COLORS
);
1449 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1450 sal_Bool bRet
= sal_False
;
1454 const long nMinR
= MinMax( (long) rSearchColor
.GetRed() - nTol
, 0, 255 );
1455 const long nMaxR
= MinMax( (long) rSearchColor
.GetRed() + nTol
, 0, 255 );
1456 const long nMinG
= MinMax( (long) rSearchColor
.GetGreen() - nTol
, 0, 255 );
1457 const long nMaxG
= MinMax( (long) rSearchColor
.GetGreen() + nTol
, 0, 255 );
1458 const long nMinB
= MinMax( (long) rSearchColor
.GetBlue() - nTol
, 0, 255 );
1459 const long nMaxB
= MinMax( (long) rSearchColor
.GetBlue() + nTol
, 0, 255 );
1461 if( pAcc
->HasPalette() )
1463 for( sal_uInt16 i
= 0, nPalCount
= pAcc
->GetPaletteEntryCount(); i
< nPalCount
; i
++ )
1465 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( i
);
1467 if( nMinR
<= rCol
.GetRed() && nMaxR
>= rCol
.GetRed() &&
1468 nMinG
<= rCol
.GetGreen() && nMaxG
>= rCol
.GetGreen() &&
1469 nMinB
<= rCol
.GetBlue() && nMaxB
>= rCol
.GetBlue() )
1471 pAcc
->SetPaletteColor( i
, rReplaceColor
);
1478 const BitmapColor
aReplace( pAcc
->GetBestMatchingColor( rReplaceColor
) );
1480 for( long nY
= 0L, nHeight
= pAcc
->Height(); nY
< nHeight
; nY
++ )
1482 for( long nX
= 0L, nWidth
= pAcc
->Width(); nX
< nWidth
; nX
++ )
1484 aCol
= pAcc
->GetPixel( nY
, nX
);
1486 if( nMinR
<= aCol
.GetRed() && nMaxR
>= aCol
.GetRed() &&
1487 nMinG
<= aCol
.GetGreen() && nMaxG
>= aCol
.GetGreen() &&
1488 nMinB
<= aCol
.GetBlue() && nMaxB
>= aCol
.GetBlue() )
1490 pAcc
->SetPixel( nY
, nX
, aReplace
);
1496 ReleaseAccess( pAcc
);
1503 sal_Bool
Bitmap::Replace( const Color
* pSearchColors
, const Color
* pReplaceColors
,
1504 sal_uLong nColorCount
, sal_uLong
* _pTols
)
1506 // Bitmaps with 1 bit color depth can cause problems
1507 // if they have other entries than black/white in their palette
1508 if( 1 == GetBitCount() )
1509 Convert( BMP_CONVERSION_4BIT_COLORS
);
1511 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1512 sal_Bool bRet
= sal_False
;
1516 long* pMinR
= new long[ nColorCount
];
1517 long* pMaxR
= new long[ nColorCount
];
1518 long* pMinG
= new long[ nColorCount
];
1519 long* pMaxG
= new long[ nColorCount
];
1520 long* pMinB
= new long[ nColorCount
];
1521 long* pMaxB
= new long[ nColorCount
];
1527 pTols
= new long[ nColorCount
];
1528 memset( pTols
, 0, nColorCount
* sizeof( long ) );
1531 pTols
= (long*) _pTols
;
1533 for( i
= 0UL; i
< nColorCount
; i
++ )
1535 const Color
& rCol
= pSearchColors
[ i
];
1536 const long nTol
= pTols
[ i
];
1538 pMinR
[ i
] = MinMax( (long) rCol
.GetRed() - nTol
, 0, 255 );
1539 pMaxR
[ i
] = MinMax( (long) rCol
.GetRed() + nTol
, 0, 255 );
1540 pMinG
[ i
] = MinMax( (long) rCol
.GetGreen() - nTol
, 0, 255 );
1541 pMaxG
[ i
] = MinMax( (long) rCol
.GetGreen() + nTol
, 0, 255 );
1542 pMinB
[ i
] = MinMax( (long) rCol
.GetBlue() - nTol
, 0, 255 );
1543 pMaxB
[ i
] = MinMax( (long) rCol
.GetBlue() + nTol
, 0, 255 );
1546 if( pAcc
->HasPalette() )
1548 for( sal_uInt16 nEntry
= 0, nPalCount
= pAcc
->GetPaletteEntryCount(); nEntry
< nPalCount
; nEntry
++ )
1550 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( nEntry
);
1552 for( i
= 0UL; i
< nColorCount
; i
++ )
1554 if( pMinR
[ i
] <= rCol
.GetRed() && pMaxR
[ i
] >= rCol
.GetRed() &&
1555 pMinG
[ i
] <= rCol
.GetGreen() && pMaxG
[ i
] >= rCol
.GetGreen() &&
1556 pMinB
[ i
] <= rCol
.GetBlue() && pMaxB
[ i
] >= rCol
.GetBlue() )
1558 pAcc
->SetPaletteColor( (sal_uInt16
)nEntry
, pReplaceColors
[ i
] );
1567 BitmapColor
* pReplaces
= new BitmapColor
[ nColorCount
];
1569 for( i
= 0UL; i
< nColorCount
; i
++ )
1570 pReplaces
[ i
] = pAcc
->GetBestMatchingColor( pReplaceColors
[ i
] );
1572 for( long nY
= 0L, nHeight
= pAcc
->Height(); nY
< nHeight
; nY
++ )
1574 for( long nX
= 0L, nWidth
= pAcc
->Width(); nX
< nWidth
; nX
++ )
1576 aCol
= pAcc
->GetPixel( nY
, nX
);
1578 for( i
= 0UL; i
< nColorCount
; i
++ )
1580 if( pMinR
[ i
] <= aCol
.GetRed() && pMaxR
[ i
] >= aCol
.GetRed() &&
1581 pMinG
[ i
] <= aCol
.GetGreen() && pMaxG
[ i
] >= aCol
.GetGreen() &&
1582 pMinB
[ i
] <= aCol
.GetBlue() && pMaxB
[ i
] >= aCol
.GetBlue() )
1584 pAcc
->SetPixel( nY
, nX
, pReplaces
[ i
] );
1603 ReleaseAccess( pAcc
);
1610 Bitmap
Bitmap::CreateDisplayBitmap( OutputDevice
* pDisplay
)
1612 Bitmap
aDispBmp( *this );
1614 if( mpImpBmp
&& ( pDisplay
->mpGraphics
|| pDisplay
->ImplGetGraphics() ) )
1616 ImpBitmap
* pImpDispBmp
= new ImpBitmap
;
1618 if( pImpDispBmp
->ImplCreate( *mpImpBmp
, pDisplay
->mpGraphics
) )
1619 aDispBmp
.ImplSetImpBitmap( pImpDispBmp
);
1627 sal_Bool
Bitmap::CombineSimple( const Bitmap
& rMask
, BmpCombine eCombine
)
1629 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
1630 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1631 sal_Bool bRet
= sal_False
;
1633 if( pMaskAcc
&& pAcc
)
1635 const long nWidth
= std::min( pMaskAcc
->Width(), pAcc
->Width() );
1636 const long nHeight
= std::min( pMaskAcc
->Height(), pAcc
->Height() );
1637 const Color
aColBlack( COL_BLACK
);
1639 BitmapColor aMaskPixel
;
1640 const BitmapColor
aWhite( pAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1641 const BitmapColor
aBlack( pAcc
->GetBestMatchingColor( aColBlack
) );
1642 const BitmapColor
aMaskBlack( pMaskAcc
->GetBestMatchingColor( aColBlack
) );
1646 case( BMP_COMBINE_COPY
):
1648 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1650 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskBlack
)
1651 pAcc
->SetPixel( nY
, nX
, aBlack
);
1653 pAcc
->SetPixel( nY
, nX
, aWhite
);
1658 case( BMP_COMBINE_INVERT
):
1660 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1662 if( pAcc
->GetPixel( nY
, nX
) == aBlack
)
1663 pAcc
->SetPixel( nY
, nX
, aWhite
);
1665 pAcc
->SetPixel( nY
, nX
, aBlack
);
1670 case( BMP_COMBINE_AND
):
1672 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1674 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
&& pAcc
->GetPixel( nY
, nX
) != aBlack
)
1675 pAcc
->SetPixel( nY
, nX
, aWhite
);
1677 pAcc
->SetPixel( nY
, nX
, aBlack
);
1682 case( BMP_COMBINE_NAND
):
1684 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1686 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
&& pAcc
->GetPixel( nY
, nX
) != aBlack
)
1687 pAcc
->SetPixel( nY
, nX
, aBlack
);
1689 pAcc
->SetPixel( nY
, nX
, aWhite
);
1694 case( BMP_COMBINE_OR
):
1696 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1698 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
|| pAcc
->GetPixel( nY
, nX
) != aBlack
)
1699 pAcc
->SetPixel( nY
, nX
, aWhite
);
1701 pAcc
->SetPixel( nY
, nX
, aBlack
);
1706 case( BMP_COMBINE_NOR
):
1708 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1710 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
|| pAcc
->GetPixel( nY
, nX
) != aBlack
)
1711 pAcc
->SetPixel( nY
, nX
, aBlack
);
1713 pAcc
->SetPixel( nY
, nX
, aWhite
);
1718 case( BMP_COMBINE_XOR
):
1720 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1722 aPixel
= pAcc
->GetPixel( nY
, nX
);
1723 aMaskPixel
= pMaskAcc
->GetPixel( nY
, nX
);
1725 if( ( aMaskPixel
!= aMaskBlack
&& aPixel
== aBlack
) ||
1726 ( aMaskPixel
== aMaskBlack
&& aPixel
!= aBlack
) )
1728 pAcc
->SetPixel( nY
, nX
, aWhite
);
1731 pAcc
->SetPixel( nY
, nX
, aBlack
);
1736 case( BMP_COMBINE_NXOR
):
1738 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1740 aPixel
= pAcc
->GetPixel( nY
, nX
);
1741 aMaskPixel
= pMaskAcc
->GetPixel( nY
, nX
);
1743 if( ( aMaskPixel
!= aMaskBlack
&& aPixel
== aBlack
) ||
1744 ( aMaskPixel
== aMaskBlack
&& aPixel
!= aBlack
) )
1746 pAcc
->SetPixel( nY
, nX
, aBlack
);
1749 pAcc
->SetPixel( nY
, nX
, aWhite
);
1758 ( (Bitmap
&) rMask
).ReleaseAccess( pMaskAcc
);
1759 ReleaseAccess( pAcc
);
1764 // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
1765 // optimizations. Might even consolidate the code here and there.
1766 sal_Bool
Bitmap::Blend( const AlphaMask
& rAlpha
, const Color
& rBackgroundColor
)
1768 // Convert to a truecolor bitmap, if we're a paletted one. There's
1769 // room for tradeoff decision here, maybe later for an overload (or a flag)
1770 if( GetBitCount() <= 8 )
1771 Convert( BMP_CONVERSION_24BIT
);
1773 BitmapReadAccess
* pAlphaAcc
= const_cast<AlphaMask
&>(rAlpha
).AcquireReadAccess();
1774 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1775 sal_Bool bRet
= sal_False
;
1777 if( pAlphaAcc
&& pAcc
)
1779 const long nWidth
= std::min( pAlphaAcc
->Width(), pAcc
->Width() );
1780 const long nHeight
= std::min( pAlphaAcc
->Height(), pAcc
->Height() );
1782 for( long nY
= 0L; nY
< nHeight
; ++nY
)
1783 for( long nX
= 0L; nX
< nWidth
; ++nX
)
1784 pAcc
->SetPixel( nY
, nX
,
1785 pAcc
->GetPixel( nY
, nX
).Merge( rBackgroundColor
,
1786 255 - pAlphaAcc
->GetPixelIndex( nY
, nX
) ) );
1791 const_cast<AlphaMask
&>(rAlpha
).ReleaseAccess( pAlphaAcc
);
1792 ReleaseAccess( pAcc
);
1797 sal_Bool
Bitmap::MakeMono( sal_uInt8 cThreshold
)
1799 return ImplMakeMono( cThreshold
);
1802 bool Bitmap::GetSystemData( BitmapSystemData
& rData
) const
1807 SalBitmap
* pSalBitmap
= mpImpBmp
->ImplGetSalBitmap();
1809 bRet
= pSalBitmap
->GetSystemData( rData
);
1815 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */