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>
35 #include <boost/scoped_array.hpp>
42 Bitmap::Bitmap( const ResId
& rResId
) :
45 const BitmapEx
aBmpEx( rResId
);
47 if( !aBmpEx
.IsEmpty() )
48 *this = aBmpEx
.GetBitmap();
51 Bitmap::Bitmap( const Bitmap
& rBitmap
) :
52 maPrefMapMode ( rBitmap
.maPrefMapMode
),
53 maPrefSize ( rBitmap
.maPrefSize
)
55 mpImpBmp
= rBitmap
.mpImpBmp
;
58 mpImpBmp
->ImplIncRefCount();
61 Bitmap::Bitmap( SalBitmap
* pSalBitmap
)
63 mpImpBmp
= new ImpBitmap(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
= const_cast<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 if (this == &rBitmap
)
234 maPrefSize
= rBitmap
.maPrefSize
;
235 maPrefMapMode
= rBitmap
.maPrefMapMode
;
237 if ( rBitmap
.mpImpBmp
)
238 rBitmap
.mpImpBmp
->ImplIncRefCount();
241 mpImpBmp
= rBitmap
.mpImpBmp
;
246 bool Bitmap::IsEqual( const Bitmap
& rBmp
) const
248 return(IsSameInstance(rBmp
) || // Includes both are nullptr
249 (rBmp
.mpImpBmp
&& mpImpBmp
&& mpImpBmp
->ImplIsEqual(*rBmp
.mpImpBmp
)));
252 void Bitmap::SetEmpty()
254 maPrefMapMode
= MapMode();
261 Size
Bitmap::GetSizePixel() const
263 return( mpImpBmp
? mpImpBmp
->ImplGetSize() : Size() );
266 sal_uInt16
Bitmap::GetBitCount() const
268 return( mpImpBmp
? mpImpBmp
->ImplGetBitCount() : 0 );
271 bool Bitmap::HasGreyPalette() const
273 const sal_uInt16 nBitCount
= GetBitCount();
274 bool bRet
= nBitCount
== 1;
276 BitmapInfoAccess
* pIAcc
= const_cast<Bitmap
*>(this)->AcquireInfoAccess();
280 bRet
= pIAcc
->HasPalette() && pIAcc
->GetPalette().IsGreyPalette();
281 ReleaseAccess( pIAcc
);
287 BitmapChecksum
Bitmap::GetChecksum() const
289 BitmapChecksum nRet
= 0;
293 nRet
= mpImpBmp
->ImplGetChecksum();
299 void Bitmap::ImplReleaseRef()
303 if( mpImpBmp
->ImplGetRefCount() > 1UL )
304 mpImpBmp
->ImplDecRefCount();
313 void Bitmap::ImplMakeUnique()
315 if( mpImpBmp
&& mpImpBmp
->ImplGetRefCount() > 1UL )
317 ImpBitmap
* pOldImpBmp
= mpImpBmp
;
319 pOldImpBmp
->ImplDecRefCount();
321 mpImpBmp
= new ImpBitmap
;
322 mpImpBmp
->ImplCreate( *pOldImpBmp
);
326 void Bitmap::ImplAssignWithSize( const Bitmap
& rBitmap
)
328 const Size
aOldSizePix( GetSizePixel() );
329 const Size
aNewSizePix( rBitmap
.GetSizePixel() );
330 const MapMode
aOldMapMode( maPrefMapMode
);
333 if( ( aOldSizePix
!= aNewSizePix
) && aOldSizePix
.Width() && aOldSizePix
.Height() )
335 aNewPrefSize
.Width() = FRound( maPrefSize
.Width() * aNewSizePix
.Width() / aOldSizePix
.Width() );
336 aNewPrefSize
.Height() = FRound( maPrefSize
.Height() * aNewSizePix
.Height() / aOldSizePix
.Height() );
339 aNewPrefSize
= maPrefSize
;
343 maPrefSize
= aNewPrefSize
;
344 maPrefMapMode
= aOldMapMode
;
348 void Bitmap::ImplSetImpBitmap( ImpBitmap
* pImpBmp
)
350 if( pImpBmp
!= mpImpBmp
)
357 BitmapInfoAccess
* Bitmap::AcquireInfoAccess()
359 BitmapInfoAccess
* pInfoAccess
= new BitmapInfoAccess( *this );
370 BitmapReadAccess
* Bitmap::AcquireReadAccess()
372 BitmapReadAccess
* pReadAccess
= new BitmapReadAccess( *this );
383 BitmapWriteAccess
* Bitmap::AcquireWriteAccess()
385 BitmapWriteAccess
* pWriteAccess
= new BitmapWriteAccess( *this );
396 void Bitmap::ReleaseAccess( BitmapInfoAccess
* pBitmapAccess
)
398 delete pBitmapAccess
;
401 bool Bitmap::Erase(const Color
& rFillColor
)
406 Bitmap::ScopedWriteAccess
pWriteAcc(*this);
411 const sal_uLong nFormat
= pWriteAcc
->GetScanlineFormat();
412 sal_uInt8 cIndex
= 0;
417 case BMP_FORMAT_1BIT_MSB_PAL
:
418 case BMP_FORMAT_1BIT_LSB_PAL
:
420 cIndex
= static_cast<sal_uInt8
>(pWriteAcc
->GetBestPaletteIndex(rFillColor
));
421 cIndex
= (cIndex
? 255 : 0);
426 case BMP_FORMAT_4BIT_MSN_PAL
:
427 case BMP_FORMAT_4BIT_LSN_PAL
:
429 cIndex
= static_cast<sal_uInt8
>(pWriteAcc
->GetBestPaletteIndex(rFillColor
));
430 cIndex
= cIndex
| ( cIndex
<< 4 );
435 case BMP_FORMAT_8BIT_PAL
:
437 cIndex
= static_cast<sal_uInt8
>(pWriteAcc
->GetBestPaletteIndex(rFillColor
));
442 case BMP_FORMAT_24BIT_TC_BGR
:
443 case BMP_FORMAT_24BIT_TC_RGB
:
445 if (rFillColor
.GetRed() == rFillColor
.GetGreen() &&
446 rFillColor
.GetRed() == rFillColor
.GetBlue())
448 cIndex
= rFillColor
.GetRed();
463 const sal_uLong nBufSize
= pWriteAcc
->GetScanlineSize() * pWriteAcc
->Height();
464 memset( pWriteAcc
->GetBuffer(), cIndex
, nBufSize
);
469 const Rectangle
aRect( aTmpPoint
, Size( pWriteAcc
->Width(), pWriteAcc
->Height() ) );
470 pWriteAcc
->SetFillColor( rFillColor
);
471 pWriteAcc
->FillRect( aRect
);
480 bool Bitmap::Invert()
482 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
487 if( pAcc
->HasPalette() )
489 BitmapPalette
aBmpPal( pAcc
->GetPalette() );
490 const sal_uInt16 nCount
= aBmpPal
.GetEntryCount();
492 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
493 aBmpPal
[ i
].Invert();
495 pAcc
->SetPalette( aBmpPal
);
499 const long nWidth
= pAcc
->Width();
500 const long nHeight
= pAcc
->Height();
502 for( long nX
= 0L; nX
< nWidth
; nX
++ )
503 for( long nY
= 0L; nY
< nHeight
; nY
++ )
504 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nY
, nX
).Invert() );
507 mpImpBmp
->ImplInvalidateChecksum();
508 ReleaseAccess( pAcc
);
515 bool Bitmap::Mirror( BmpMirrorFlags nMirrorFlags
)
517 bool bHorz( nMirrorFlags
& BmpMirrorFlags::Horizontal
);
518 bool bVert( nMirrorFlags
& BmpMirrorFlags::Vertical
);
521 if( bHorz
&& !bVert
)
523 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
527 const long nWidth
= pAcc
->Width();
528 const long nHeight
= pAcc
->Height();
529 const long nWidth1
= nWidth
- 1L;
530 const long nWidth_2
= nWidth
>> 1L;
532 for( long nY
= 0L; nY
< nHeight
; nY
++ )
534 for( long nX
= 0L, nOther
= nWidth1
; nX
< nWidth_2
; nX
++, nOther
-- )
536 const BitmapColor
aTemp( pAcc
->GetPixel( nY
, nX
) );
538 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nY
, nOther
) );
539 pAcc
->SetPixel( nY
, nOther
, aTemp
);
543 ReleaseAccess( pAcc
);
547 else if( bVert
&& !bHorz
)
549 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
553 const long nScanSize
= pAcc
->GetScanlineSize();
554 boost::scoped_array
<sal_uInt8
> pBuffer(new sal_uInt8
[ nScanSize
]);
555 const long nHeight
= pAcc
->Height();
556 const long nHeight1
= nHeight
- 1L;
557 const long nHeight_2
= nHeight
>> 1L;
559 for( long nY
= 0L, nOther
= nHeight1
; nY
< nHeight_2
; nY
++, nOther
-- )
561 memcpy( pBuffer
.get(), pAcc
->GetScanline( nY
), nScanSize
);
562 memcpy( pAcc
->GetScanline( nY
), pAcc
->GetScanline( nOther
), nScanSize
);
563 memcpy( pAcc
->GetScanline( nOther
), pBuffer
.get(), nScanSize
);
566 ReleaseAccess( pAcc
);
570 else if( bHorz
&& bVert
)
572 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
576 const long nWidth
= pAcc
->Width();
577 const long nWidth1
= nWidth
- 1L;
578 const long nHeight
= pAcc
->Height();
579 long nHeight_2
= nHeight
>> 1;
581 for( long nY
= 0L, nOtherY
= nHeight
- 1L; nY
< nHeight_2
; nY
++, nOtherY
-- )
583 for( long nX
= 0L, nOtherX
= nWidth1
; nX
< nWidth
; nX
++, nOtherX
-- )
585 const BitmapColor
aTemp( pAcc
->GetPixel( nY
, nX
) );
587 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nOtherY
, nOtherX
) );
588 pAcc
->SetPixel( nOtherY
, nOtherX
, aTemp
);
592 // ggf. noch mittlere Zeile horizontal spiegeln
595 for( long nX
= 0L, nOtherX
= nWidth1
, nWidth_2
= nWidth
>> 1; nX
< nWidth_2
; nX
++, nOtherX
-- )
597 const BitmapColor
aTemp( pAcc
->GetPixel( nHeight_2
, nX
) );
598 pAcc
->SetPixel( nHeight_2
, nX
, pAcc
->GetPixel( nHeight_2
, nOtherX
) );
599 pAcc
->SetPixel( nHeight_2
, nOtherX
, aTemp
);
603 ReleaseAccess( pAcc
);
613 bool Bitmap::Rotate( long nAngle10
, const Color
& rFillColor
)
618 nAngle10
= ( nAngle10
< 0L ) ? ( 3599L + nAngle10
) : nAngle10
;
622 else if( 1800L == nAngle10
)
623 bRet
= Mirror( BmpMirrorFlags::Horizontal
| BmpMirrorFlags::Vertical
);
626 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
631 const Size
aSizePix( GetSizePixel() );
633 if( ( 900L == nAngle10
) || ( 2700L == nAngle10
) )
635 const Size
aNewSizePix( aSizePix
.Height(), aSizePix
.Width() );
636 Bitmap
aNewBmp( aNewSizePix
, GetBitCount(), &pReadAcc
->GetPalette() );
637 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
641 const long nWidth
= aSizePix
.Width();
642 const long nWidth1
= nWidth
- 1L;
643 const long nHeight
= aSizePix
.Height();
644 const long nHeight1
= nHeight
- 1L;
645 const long nNewWidth
= aNewSizePix
.Width();
646 const long nNewHeight
= aNewSizePix
.Height();
648 if( 900L == nAngle10
)
650 for( long nY
= 0L, nOtherX
= nWidth1
; nY
< nNewHeight
; nY
++, nOtherX
-- )
651 for( long nX
= 0L, nOtherY
= 0L; nX
< nNewWidth
; nX
++ )
652 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nOtherY
++, nOtherX
) );
654 else if( 2700L == nAngle10
)
656 for( long nY
= 0L, nOtherX
= 0L; nY
< nNewHeight
; nY
++, nOtherX
++ )
657 for( long nX
= 0L, nOtherY
= nHeight1
; nX
< nNewWidth
; nX
++ )
658 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nOtherY
--, nOtherX
) );
661 ReleaseAccess( pWriteAcc
);
664 aRotatedBmp
= aNewBmp
;
669 Rectangle
aTmpRectangle( aTmpPoint
, aSizePix
);
670 Polygon
aPoly( aTmpRectangle
);
671 aPoly
.Rotate( aTmpPoint
, (sal_uInt16
) nAngle10
);
673 Rectangle
aNewBound( aPoly
.GetBoundRect() );
674 const Size
aNewSizePix( aNewBound
.GetSize() );
675 Bitmap
aNewBmp( aNewSizePix
, GetBitCount(), &pReadAcc
->GetPalette() );
676 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
680 const BitmapColor
aFillColor( pWriteAcc
->GetBestMatchingColor( rFillColor
) );
681 const double fCosAngle
= cos( nAngle10
* F_PI1800
);
682 const double fSinAngle
= sin( nAngle10
* F_PI1800
);
683 const double fXMin
= aNewBound
.Left();
684 const double fYMin
= aNewBound
.Top();
685 const long nWidth
= aSizePix
.Width();
686 const long nHeight
= aSizePix
.Height();
687 const long nNewWidth
= aNewSizePix
.Width();
688 const long nNewHeight
= aNewSizePix
.Height();
693 boost::scoped_array
<long> pCosX(new long[ nNewWidth
]);
694 boost::scoped_array
<long> pSinX(new long[ nNewWidth
]);
695 boost::scoped_array
<long> pCosY(new long[ nNewHeight
]);
696 boost::scoped_array
<long> pSinY(new long[ nNewHeight
]);
698 for ( nX
= 0; nX
< nNewWidth
; nX
++ )
700 const double fTmp
= ( fXMin
+ nX
) * 64.;
702 pCosX
[ nX
] = FRound( fCosAngle
* fTmp
);
703 pSinX
[ nX
] = FRound( fSinAngle
* fTmp
);
706 for ( nY
= 0; nY
< nNewHeight
; nY
++ )
708 const double fTmp
= ( fYMin
+ nY
) * 64.;
710 pCosY
[ nY
] = FRound( fCosAngle
* fTmp
);
711 pSinY
[ nY
] = FRound( fSinAngle
* fTmp
);
714 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
716 long nSinY
= pSinY
[ nY
];
717 long nCosY
= pCosY
[ nY
];
719 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
721 nRotX
= ( pCosX
[ nX
] - nSinY
) >> 6;
722 nRotY
= ( pSinX
[ nX
] + nCosY
) >> 6;
724 if ( ( nRotX
> -1L ) && ( nRotX
< nWidth
) && ( nRotY
> -1L ) && ( nRotY
< nHeight
) )
725 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nRotY
, nRotX
) );
727 pWriteAcc
->SetPixel( nY
, nX
, aFillColor
);
731 ReleaseAccess( pWriteAcc
);
734 aRotatedBmp
= aNewBmp
;
737 ReleaseAccess( pReadAcc
);
740 if( ( bRet
= !!aRotatedBmp
) )
741 ImplAssignWithSize( aRotatedBmp
);
747 bool Bitmap::Crop( const Rectangle
& rRectPixel
)
749 const Size
aSizePix( GetSizePixel() );
750 Rectangle
aRect( rRectPixel
);
753 aRect
.Intersection( Rectangle( Point(), aSizePix
) );
755 if( !aRect
.IsEmpty() && aSizePix
!= aRect
.GetSize())
757 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
762 const Rectangle
aNewRect( aTmpPoint
, aRect
.GetSize() );
763 Bitmap
aNewBmp( aNewRect
.GetSize(), GetBitCount(), &pReadAcc
->GetPalette() );
764 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
768 const long nOldX
= aRect
.Left();
769 const long nOldY
= aRect
.Top();
770 const long nNewWidth
= aNewRect
.GetWidth();
771 const long nNewHeight
= aNewRect
.GetHeight();
773 for( long nY
= 0, nY2
= nOldY
; nY
< nNewHeight
; nY
++, nY2
++ )
774 for( long nX
= 0, nX2
= nOldX
; nX
< nNewWidth
; nX
++, nX2
++ )
775 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nY2
, nX2
) );
777 ReleaseAccess( pWriteAcc
);
781 ReleaseAccess( pReadAcc
);
784 ImplAssignWithSize( aNewBmp
);
791 bool Bitmap::CopyPixel( const Rectangle
& rRectDst
,
792 const Rectangle
& rRectSrc
, const Bitmap
* pBmpSrc
)
794 const Size
aSizePix( GetSizePixel() );
795 Rectangle
aRectDst( rRectDst
);
798 aRectDst
.Intersection( Rectangle( Point(), aSizePix
) );
800 if( !aRectDst
.IsEmpty() )
802 if( pBmpSrc
&& ( *pBmpSrc
!= *this ) )
804 Bitmap
* pSrc
= const_cast<Bitmap
*>(pBmpSrc
);
805 const Size
aCopySizePix( pSrc
->GetSizePixel() );
806 Rectangle
aRectSrc( rRectSrc
);
807 const sal_uInt16 nSrcBitCount
= pBmpSrc
->GetBitCount();
808 const sal_uInt16 nDstBitCount
= GetBitCount();
810 if( nSrcBitCount
> nDstBitCount
)
812 long nNextIndex
= 0L;
814 if( ( nSrcBitCount
== 24 ) && ( nDstBitCount
< 24 ) )
815 Convert( BMP_CONVERSION_24BIT
);
816 else if( ( nSrcBitCount
== 8 ) && ( nDstBitCount
< 8 ) )
818 Convert( BMP_CONVERSION_8BIT_COLORS
);
821 else if( ( nSrcBitCount
== 4 ) && ( nDstBitCount
< 4 ) )
823 Convert( BMP_CONVERSION_4BIT_COLORS
);
829 BitmapReadAccess
* pSrcAcc
= pSrc
->AcquireReadAccess();
830 BitmapWriteAccess
* pDstAcc
= AcquireWriteAccess();
832 if( pSrcAcc
&& pDstAcc
)
834 const long nSrcCount
= pDstAcc
->GetPaletteEntryCount();
835 const long nDstCount
= 1 << nDstBitCount
;
837 for( long i
= 0L; ( i
< nSrcCount
) && ( nNextIndex
< nSrcCount
); i
++ )
839 const BitmapColor
& rSrcCol
= pSrcAcc
->GetPaletteColor( (sal_uInt16
) i
);
843 for( long j
= 0L; j
< nDstCount
; j
++ )
845 if( rSrcCol
== pDstAcc
->GetPaletteColor( (sal_uInt16
) j
) )
853 pDstAcc
->SetPaletteColor( (sal_uInt16
) nNextIndex
++, rSrcCol
);
858 ReleaseAccess( pSrcAcc
);
861 ReleaseAccess( pDstAcc
);
865 aRectSrc
.Intersection( Rectangle( Point(), aCopySizePix
) );
867 if( !aRectSrc
.IsEmpty() )
869 BitmapReadAccess
* pReadAcc
= pSrc
->AcquireReadAccess();
873 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
877 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
878 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
879 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
880 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
881 long nDstY
= aRectDst
.Top();
883 if( pReadAcc
->HasPalette() && pWriteAcc
->HasPalette() )
885 const sal_uInt16 nCount
= pReadAcc
->GetPaletteEntryCount();
886 boost::scoped_array
<sal_uInt8
> pMap(new sal_uInt8
[ nCount
]);
888 // Create index map for the color table, as the bitmap should be copied
889 // retaining it's color information relatively well
890 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
891 pMap
[ i
] = (sal_uInt8
) pWriteAcc
->GetBestPaletteIndex( pReadAcc
->GetPaletteColor( i
) );
893 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
894 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
895 pWriteAcc
->SetPixelIndex( nDstY
, nDstX
, pMap
[ pReadAcc
->GetPixelIndex( nSrcY
, nSrcX
) ] );
897 else if( pReadAcc
->HasPalette() )
899 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
900 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
901 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPaletteColor( pReadAcc
->GetPixelIndex( nSrcY
, nSrcX
) ) );
904 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
905 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
906 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPixel( nSrcY
, nSrcX
) );
908 ReleaseAccess( pWriteAcc
);
909 bRet
= ( nWidth
> 0L ) && ( nHeight
> 0L );
912 ReleaseAccess( pReadAcc
);
918 Rectangle
aRectSrc( rRectSrc
);
920 aRectSrc
.Intersection( Rectangle( Point(), aSizePix
) );
922 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
924 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
928 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
929 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
930 const long nSrcX
= aRectSrc
.Left();
931 const long nSrcY
= aRectSrc
.Top();
932 const long nSrcEndX1
= nSrcX
+ nWidth
- 1L;
933 const long nSrcEndY1
= nSrcY
+ nHeight
- 1L;
934 const long nDstX
= aRectDst
.Left();
935 const long nDstY
= aRectDst
.Top();
936 const long nDstEndX1
= nDstX
+ nWidth
- 1L;
937 const long nDstEndY1
= nDstY
+ nHeight
- 1L;
939 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
941 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
942 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
943 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
945 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
947 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
948 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
949 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
951 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
953 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
954 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
955 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
959 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
960 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
961 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
964 ReleaseAccess( pWriteAcc
);
974 bool Bitmap::CopyPixel_AlphaOptimized( const Rectangle
& rRectDst
, const Rectangle
& rRectSrc
,
975 const Bitmap
* pBmpSrc
)
977 // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
978 // This optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
979 const Size
aSizePix( GetSizePixel() );
980 Rectangle
aRectDst( rRectDst
);
983 aRectDst
.Intersection( Rectangle( Point(), aSizePix
) );
985 if( !aRectDst
.IsEmpty() )
987 if( pBmpSrc
&& ( *pBmpSrc
!= *this ) )
989 Bitmap
* pSrc
= const_cast<Bitmap
*>(pBmpSrc
);
990 const Size
aCopySizePix( pSrc
->GetSizePixel() );
991 Rectangle
aRectSrc( rRectSrc
);
993 aRectSrc
.Intersection( Rectangle( Point(), aCopySizePix
) );
995 if( !aRectSrc
.IsEmpty() )
997 BitmapReadAccess
* pReadAcc
= pSrc
->AcquireReadAccess();
1001 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
1005 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
1006 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
1007 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
1008 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
1009 long nDstY
= aRectDst
.Top();
1011 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
1012 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
1013 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPixel( nSrcY
, nSrcX
) );
1015 ReleaseAccess( pWriteAcc
);
1016 bRet
= ( nWidth
> 0L ) && ( nHeight
> 0L );
1019 ReleaseAccess( pReadAcc
);
1025 Rectangle
aRectSrc( rRectSrc
);
1027 aRectSrc
.Intersection( Rectangle( Point(), aSizePix
) );
1029 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
1031 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
1035 const long nWidth
= std::min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
1036 const long nHeight
= std::min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
1037 const long nSrcX
= aRectSrc
.Left();
1038 const long nSrcY
= aRectSrc
.Top();
1039 const long nSrcEndX1
= nSrcX
+ nWidth
- 1L;
1040 const long nSrcEndY1
= nSrcY
+ nHeight
- 1L;
1041 const long nDstX
= aRectDst
.Left();
1042 const long nDstY
= aRectDst
.Top();
1043 const long nDstEndX1
= nDstX
+ nWidth
- 1L;
1044 const long nDstEndY1
= nDstY
+ nHeight
- 1L;
1046 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
1048 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
1049 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
1050 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1052 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
1054 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
1055 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
1056 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1058 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
1060 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
1061 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
1062 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1066 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
1067 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
1068 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1071 ReleaseAccess( pWriteAcc
);
1082 bool Bitmap::Expand( sal_uLong nDX
, sal_uLong nDY
, const Color
* pInitColor
)
1088 const Size
aSizePixel( GetSizePixel() );
1089 const long nWidth
= aSizePixel
.Width();
1090 const long nHeight
= aSizePixel
.Height();
1091 const Size
aNewSize( nWidth
+ nDX
, nHeight
+ nDY
);
1092 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1096 BitmapPalette
aBmpPal( pReadAcc
->GetPalette() );
1097 Bitmap
aNewBmp( aNewSize
, GetBitCount(), &aBmpPal
);
1098 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1103 const long nNewX
= nWidth
;
1104 const long nNewY
= nHeight
;
1105 const long nNewWidth
= pWriteAcc
->Width();
1106 const long nNewHeight
= pWriteAcc
->Height();
1111 aColor
= pWriteAcc
->GetBestMatchingColor( *pInitColor
);
1113 for( nY
= 0L; nY
< nHeight
; nY
++ )
1115 pWriteAcc
->CopyScanline( nY
, *pReadAcc
);
1117 if( pInitColor
&& nDX
)
1118 for( nX
= nNewX
; nX
< nNewWidth
; nX
++ )
1119 pWriteAcc
->SetPixel( nY
, nX
, aColor
);
1122 if( pInitColor
&& nDY
)
1123 for( nY
= nNewY
; nY
< nNewHeight
; nY
++ )
1124 for( nX
= 0; nX
< nNewWidth
; nX
++ )
1125 pWriteAcc
->SetPixel( nY
, nX
, aColor
);
1127 ReleaseAccess( pWriteAcc
);
1131 ReleaseAccess( pReadAcc
);
1134 ImplAssignWithSize( aNewBmp
);
1141 Bitmap
Bitmap::CreateMask( const Color
& rTransColor
, sal_uLong nTol
) const
1143 Bitmap
aNewBmp( GetSizePixel(), 1 );
1144 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1149 BitmapReadAccess
* pReadAcc
= const_cast<Bitmap
*>(this)->AcquireReadAccess();
1153 const long nWidth
= pReadAcc
->Width();
1154 const long nHeight
= pReadAcc
->Height();
1155 const BitmapColor
aBlack( pWriteAcc
->GetBestMatchingColor( Color( COL_BLACK
) ) );
1156 const BitmapColor
aWhite( pWriteAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1160 const BitmapColor
aTest( pReadAcc
->GetBestMatchingColor( rTransColor
) );
1163 if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL
||
1164 pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL
)
1166 // optimized for 4Bit-MSN/LSN source palette
1167 const sal_uInt8 cTest
= aTest
.GetIndex();
1168 const long nShiftInit
= ( ( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL
) ? 4 : 0 );
1170 if( pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
&&
1171 aWhite
.GetIndex() == 1 )
1173 // optimized for 1Bit-MSB destination palette
1174 for( nY
= 0L; nY
< nHeight
; nY
++ )
1176 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1177 Scanline pDst
= pWriteAcc
->GetScanline( nY
);
1179 for( nX
= 0L, nShift
= nShiftInit
; nX
< nWidth
; nX
++, nShift
^= 4 )
1181 if( cTest
== ( ( pSrc
[ nX
>> 1 ] >> nShift
) & 0x0f ) )
1182 pDst
[ nX
>> 3 ] |= 1 << ( 7 - ( nX
& 7 ) );
1184 pDst
[ nX
>> 3 ] &= ~( 1 << ( 7 - ( nX
& 7 ) ) );
1190 for( nY
= 0L; nY
< nHeight
; nY
++ )
1192 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1194 for( nX
= 0L, nShift
= nShiftInit
; nX
< nWidth
; nX
++, nShift
^= 4 )
1196 if( cTest
== ( ( pSrc
[ nX
>> 1 ] >> nShift
) & 0x0f ) )
1197 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1199 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1204 else if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
)
1206 // optimized for 8Bit source palette
1207 const sal_uInt8 cTest
= aTest
.GetIndex();
1209 if( pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
&&
1210 aWhite
.GetIndex() == 1 )
1212 // optimized for 1Bit-MSB destination palette
1213 for( nY
= 0L; nY
< nHeight
; nY
++ )
1215 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1216 Scanline pDst
= pWriteAcc
->GetScanline( nY
);
1217 for( nX
= 0L; nX
< nWidth
; nX
++ )
1219 if( cTest
== pSrc
[ nX
] )
1220 pDst
[ nX
>> 3 ] |= 1 << ( 7 - ( nX
& 7 ) );
1222 pDst
[ nX
>> 3 ] &= ~( 1 << ( 7 - ( nX
& 7 ) ) );
1228 for( nY
= 0L; nY
< nHeight
; nY
++ )
1230 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1231 for( nX
= 0L; nX
< nWidth
; nX
++ )
1233 if( cTest
== pSrc
[ nX
] )
1234 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1236 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1244 for( nY
= 0L; nY
< nHeight
; nY
++ )
1246 for( nX
= 0L; nX
< nWidth
; nX
++ )
1248 if( aTest
== pReadAcc
->GetPixel( nY
, nX
) )
1249 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1251 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1260 const long nMinR
= MinMax( (long) rTransColor
.GetRed() - nTol
, 0, 255 );
1261 const long nMaxR
= MinMax( (long) rTransColor
.GetRed() + nTol
, 0, 255 );
1262 const long nMinG
= MinMax( (long) rTransColor
.GetGreen() - nTol
, 0, 255 );
1263 const long nMaxG
= MinMax( (long) rTransColor
.GetGreen() + nTol
, 0, 255 );
1264 const long nMinB
= MinMax( (long) rTransColor
.GetBlue() - nTol
, 0, 255 );
1265 const long nMaxB
= MinMax( (long) rTransColor
.GetBlue() + nTol
, 0, 255 );
1267 if( pReadAcc
->HasPalette() )
1269 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1271 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1273 aCol
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixelIndex( nY
, nX
) );
1275 nG
= aCol
.GetGreen();
1276 nB
= aCol
.GetBlue();
1278 if( nMinR
<= nR
&& nMaxR
>= nR
&&
1279 nMinG
<= nG
&& nMaxG
>= nG
&&
1280 nMinB
<= nB
&& nMaxB
>= nB
)
1282 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1285 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1291 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1293 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1295 aCol
= pReadAcc
->GetPixel( nY
, nX
);
1297 nG
= aCol
.GetGreen();
1298 nB
= aCol
.GetBlue();
1300 if( nMinR
<= nR
&& nMaxR
>= nR
&&
1301 nMinG
<= nG
&& nMaxG
>= nG
&&
1302 nMinB
<= nB
&& nMaxB
>= nB
)
1304 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1307 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1313 ReleaseAccess( pReadAcc
);
1317 ReleaseAccess( pWriteAcc
);
1322 aNewBmp
.maPrefSize
= maPrefSize
;
1323 aNewBmp
.maPrefMapMode
= maPrefMapMode
;
1331 vcl::Region
Bitmap::CreateRegion( const Color
& rColor
, const Rectangle
& rRect
) const
1333 vcl::Region aRegion
;
1334 Rectangle
aRect( rRect
);
1335 BitmapReadAccess
* pReadAcc
= const_cast<Bitmap
*>(this)->AcquireReadAccess();
1337 aRect
.Intersection( Rectangle( Point(), GetSizePixel() ) );
1342 //Rectangle aSubRect;
1343 const long nLeft
= aRect
.Left();
1344 const long nTop
= aRect
.Top();
1345 const long nRight
= aRect
.Right();
1346 const long nBottom
= aRect
.Bottom();
1347 const BitmapColor
aMatch( pReadAcc
->GetBestMatchingColor( rColor
) );
1349 //RectangleVector aRectangles;
1350 //aRegion.ImplBeginAddRect();
1351 std::vector
< long > aLine
;
1355 for( ; nY
<= nBottom
; nY
++ )
1357 //aSubRect.Top() = aSubRect.Bottom() = nY;
1358 std::vector
< long > aNewLine
;
1361 for( ; nX
<= nRight
; )
1363 while( ( nX
<= nRight
) && ( aMatch
!= pReadAcc
->GetPixel( nY
, nX
) ) )
1368 aNewLine
.push_back(nX
);
1369 //aSubRect.Left() = nX;
1371 while( ( nX
<= nRight
) && ( aMatch
== pReadAcc
->GetPixel( nY
, nX
) ) )
1374 //aSubRect.Right() = nX - 1L;
1375 aNewLine
.push_back(nX
- 1);
1377 //aRegion.ImplAddRect( aSubRect );
1378 //aRectangles.push_back(aSubRect);
1379 //aRegion.Union(aSubRect);
1383 if(aNewLine
!= aLine
)
1385 // need to write aLine, it's different from the next line
1390 // enter y values and proceed ystart
1391 aSubRect
.Top() = nYStart
;
1392 aSubRect
.Bottom() = nY
? nY
- 1 : 0;
1394 for(sal_uInt32
a(0); a
< aLine
.size();)
1396 aSubRect
.Left() = aLine
[a
++];
1397 aSubRect
.Right() = aLine
[a
++];
1398 aRegion
.Union(aSubRect
);
1402 // copy line as new line
1408 // write last line if used
1414 aSubRect
.Top() = nYStart
;
1415 aSubRect
.Bottom() = nY
? nY
- 1 : 0;
1417 for(sal_uInt32
a(0); a
< aLine
.size();)
1419 aSubRect
.Left() = aLine
[a
++];
1420 aSubRect
.Right() = aLine
[a
++];
1421 aRegion
.Union(aSubRect
);
1425 //aRegion.ImplEndAddRect();
1426 //aRegion.SetRegionRectangles(aRectangles);
1428 ReleaseAccess( pReadAcc
);
1436 bool Bitmap::Replace( const Bitmap
& rMask
, const Color
& rReplaceColor
)
1438 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
1439 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1442 if( pMaskAcc
&& pAcc
)
1444 const long nWidth
= std::min( pMaskAcc
->Width(), pAcc
->Width() );
1445 const long nHeight
= std::min( pMaskAcc
->Height(), pAcc
->Height() );
1446 const BitmapColor
aMaskWhite( pMaskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1447 BitmapColor aReplace
;
1449 if( pAcc
->HasPalette() )
1451 const sal_uInt16 nActColors
= pAcc
->GetPaletteEntryCount();
1452 const sal_uInt16 nMaxColors
= 1 << pAcc
->GetBitCount();
1454 // default to the nearest color
1455 aReplace
= pAcc
->GetBestMatchingColor( rReplaceColor
);
1457 // for paletted images without a matching palette entry
1458 // look for an unused palette entry (NOTE: expensive!)
1459 if( pAcc
->GetPaletteColor( aReplace
.GetIndex() ) != BitmapColor( rReplaceColor
) )
1461 // if the palette has empty entries use the last one
1462 if( nActColors
< nMaxColors
)
1464 pAcc
->SetPaletteEntryCount( nActColors
+ 1 );
1465 pAcc
->SetPaletteColor( nActColors
, rReplaceColor
);
1466 aReplace
= BitmapColor( (sal_uInt8
) nActColors
);
1470 boost::scoped_array
<bool> pFlags(new bool[ nMaxColors
]);
1472 // Set all entries to false
1473 std::fill( pFlags
.get(), pFlags
.get()+nMaxColors
, false );
1475 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1476 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1477 pFlags
[ pAcc
->GetPixelIndex( nY
, nX
) ] = true;
1479 for( sal_uInt16 i
= 0UL; i
< nMaxColors
; i
++ )
1481 // Hurray, we do have an unsused entry
1484 pAcc
->SetPaletteColor( (sal_uInt16
) i
, rReplaceColor
);
1485 aReplace
= BitmapColor( (sal_uInt8
) i
);
1492 aReplace
= rReplaceColor
;
1494 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1495 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1496 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskWhite
)
1497 pAcc
->SetPixel( nY
, nX
, aReplace
);
1502 ReleaseAccess( pMaskAcc
);
1503 ReleaseAccess( pAcc
);
1508 bool Bitmap::Replace( const AlphaMask
& rAlpha
, const Color
& rMergeColor
)
1510 Bitmap
aNewBmp( GetSizePixel(), 24 );
1511 BitmapReadAccess
* pAcc
= AcquireReadAccess();
1512 BitmapReadAccess
* pAlphaAcc
= ( (AlphaMask
&) rAlpha
).AcquireReadAccess();
1513 BitmapWriteAccess
* pNewAcc
= aNewBmp
.AcquireWriteAccess();
1516 if( pAcc
&& pAlphaAcc
&& pNewAcc
)
1519 const long nWidth
= std::min( pAlphaAcc
->Width(), pAcc
->Width() );
1520 const long nHeight
= std::min( pAlphaAcc
->Height(), pAcc
->Height() );
1522 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1524 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1526 aCol
= pAcc
->GetColor( nY
, nX
);
1527 pNewAcc
->SetPixel( nY
, nX
, aCol
.Merge( rMergeColor
, 255 - pAlphaAcc
->GetPixelIndex( nY
, nX
) ) );
1534 ReleaseAccess( pAcc
);
1535 ReleaseAccess( pAlphaAcc
);
1536 ReleaseAccess( pNewAcc
);
1540 const MapMode
aMap( maPrefMapMode
);
1541 const Size
aSize( maPrefSize
);
1545 maPrefMapMode
= aMap
;
1552 bool Bitmap::Replace( const Color
& rSearchColor
, const Color
& rReplaceColor
, sal_uLong nTol
)
1556 // implementation specific replace
1557 ImpBitmap
* pImpBmp
= new ImpBitmap
;
1559 if( pImpBmp
->ImplCreate( *mpImpBmp
) && pImpBmp
->ImplReplace( rSearchColor
, rReplaceColor
, nTol
) )
1561 ImplSetImpBitmap( pImpBmp
);
1562 maPrefMapMode
= MapMode( MAP_PIXEL
);
1563 maPrefSize
= pImpBmp
->ImplGetSize();
1572 // Bitmaps with 1 bit color depth can cause problems
1573 // if they have other entries than black/white in their palette
1574 if( 1 == GetBitCount() )
1575 Convert( BMP_CONVERSION_4BIT_COLORS
);
1577 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1582 const long nMinR
= MinMax( (long) rSearchColor
.GetRed() - nTol
, 0, 255 );
1583 const long nMaxR
= MinMax( (long) rSearchColor
.GetRed() + nTol
, 0, 255 );
1584 const long nMinG
= MinMax( (long) rSearchColor
.GetGreen() - nTol
, 0, 255 );
1585 const long nMaxG
= MinMax( (long) rSearchColor
.GetGreen() + nTol
, 0, 255 );
1586 const long nMinB
= MinMax( (long) rSearchColor
.GetBlue() - nTol
, 0, 255 );
1587 const long nMaxB
= MinMax( (long) rSearchColor
.GetBlue() + nTol
, 0, 255 );
1589 if( pAcc
->HasPalette() )
1591 for( sal_uInt16 i
= 0, nPalCount
= pAcc
->GetPaletteEntryCount(); i
< nPalCount
; i
++ )
1593 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( i
);
1595 if( nMinR
<= rCol
.GetRed() && nMaxR
>= rCol
.GetRed() &&
1596 nMinG
<= rCol
.GetGreen() && nMaxG
>= rCol
.GetGreen() &&
1597 nMinB
<= rCol
.GetBlue() && nMaxB
>= rCol
.GetBlue() )
1599 pAcc
->SetPaletteColor( i
, rReplaceColor
);
1606 const BitmapColor
aReplace( pAcc
->GetBestMatchingColor( rReplaceColor
) );
1608 for( long nY
= 0L, nHeight
= pAcc
->Height(); nY
< nHeight
; nY
++ )
1610 for( long nX
= 0L, nWidth
= pAcc
->Width(); nX
< nWidth
; nX
++ )
1612 aCol
= pAcc
->GetPixel( nY
, nX
);
1614 if( nMinR
<= aCol
.GetRed() && nMaxR
>= aCol
.GetRed() &&
1615 nMinG
<= aCol
.GetGreen() && nMaxG
>= aCol
.GetGreen() &&
1616 nMinB
<= aCol
.GetBlue() && nMaxB
>= aCol
.GetBlue() )
1618 pAcc
->SetPixel( nY
, nX
, aReplace
);
1624 ReleaseAccess( pAcc
);
1631 bool Bitmap::Replace( const Color
* pSearchColors
, const Color
* pReplaceColors
,
1632 sal_uLong nColorCount
, sal_uLong
* _pTols
)
1634 // Bitmaps with 1 bit color depth can cause problems
1635 // if they have other entries than black/white in their palette
1636 if( 1 == GetBitCount() )
1637 Convert( BMP_CONVERSION_4BIT_COLORS
);
1639 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1644 boost::scoped_array
<long> pMinR(new long[ nColorCount
]);
1645 boost::scoped_array
<long> pMaxR(new long[ nColorCount
]);
1646 boost::scoped_array
<long> pMinG(new long[ nColorCount
]);
1647 boost::scoped_array
<long> pMaxG(new long[ nColorCount
]);
1648 boost::scoped_array
<long> pMinB(new long[ nColorCount
]);
1649 boost::scoped_array
<long> pMaxB(new long[ nColorCount
]);
1655 pTols
= new long[ nColorCount
];
1656 memset( pTols
, 0, nColorCount
* sizeof( long ) );
1659 pTols
= reinterpret_cast<long*>(_pTols
);
1661 for( i
= 0UL; i
< nColorCount
; i
++ )
1663 const Color
& rCol
= pSearchColors
[ i
];
1664 const long nTol
= pTols
[ i
];
1666 pMinR
[ i
] = MinMax( (long) rCol
.GetRed() - nTol
, 0, 255 );
1667 pMaxR
[ i
] = MinMax( (long) rCol
.GetRed() + nTol
, 0, 255 );
1668 pMinG
[ i
] = MinMax( (long) rCol
.GetGreen() - nTol
, 0, 255 );
1669 pMaxG
[ i
] = MinMax( (long) rCol
.GetGreen() + nTol
, 0, 255 );
1670 pMinB
[ i
] = MinMax( (long) rCol
.GetBlue() - nTol
, 0, 255 );
1671 pMaxB
[ i
] = MinMax( (long) rCol
.GetBlue() + nTol
, 0, 255 );
1674 if( pAcc
->HasPalette() )
1676 for( sal_uInt16 nEntry
= 0, nPalCount
= pAcc
->GetPaletteEntryCount(); nEntry
< nPalCount
; nEntry
++ )
1678 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( nEntry
);
1680 for( i
= 0UL; i
< nColorCount
; i
++ )
1682 if( pMinR
[ i
] <= rCol
.GetRed() && pMaxR
[ i
] >= rCol
.GetRed() &&
1683 pMinG
[ i
] <= rCol
.GetGreen() && pMaxG
[ i
] >= rCol
.GetGreen() &&
1684 pMinB
[ i
] <= rCol
.GetBlue() && pMaxB
[ i
] >= rCol
.GetBlue() )
1686 pAcc
->SetPaletteColor( (sal_uInt16
)nEntry
, pReplaceColors
[ i
] );
1695 boost::scoped_array
<BitmapColor
> pReplaces(new BitmapColor
[ nColorCount
]);
1697 for( i
= 0UL; i
< nColorCount
; i
++ )
1698 pReplaces
[ i
] = pAcc
->GetBestMatchingColor( pReplaceColors
[ i
] );
1700 for( long nY
= 0L, nHeight
= pAcc
->Height(); nY
< nHeight
; nY
++ )
1702 for( long nX
= 0L, nWidth
= pAcc
->Width(); nX
< nWidth
; nX
++ )
1704 aCol
= pAcc
->GetPixel( nY
, nX
);
1706 for( i
= 0UL; i
< nColorCount
; i
++ )
1708 if( pMinR
[ i
] <= aCol
.GetRed() && pMaxR
[ i
] >= aCol
.GetRed() &&
1709 pMinG
[ i
] <= aCol
.GetGreen() && pMaxG
[ i
] >= aCol
.GetGreen() &&
1710 pMinB
[ i
] <= aCol
.GetBlue() && pMaxB
[ i
] >= aCol
.GetBlue() )
1712 pAcc
->SetPixel( nY
, nX
, pReplaces
[ i
] );
1723 ReleaseAccess( pAcc
);
1730 Bitmap
Bitmap::CreateDisplayBitmap( OutputDevice
* pDisplay
)
1732 Bitmap
aDispBmp( *this );
1734 SalGraphics
* pDispGraphics
= pDisplay
->GetGraphics();
1736 if( mpImpBmp
&& pDispGraphics
)
1738 ImpBitmap
* pImpDispBmp
= new ImpBitmap
;
1740 if( pImpDispBmp
->ImplCreate( *mpImpBmp
, pDispGraphics
) )
1741 aDispBmp
.ImplSetImpBitmap( pImpDispBmp
);
1749 bool Bitmap::CombineSimple( const Bitmap
& rMask
, BmpCombine eCombine
)
1751 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
1752 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1755 if( pMaskAcc
&& pAcc
)
1757 const long nWidth
= std::min( pMaskAcc
->Width(), pAcc
->Width() );
1758 const long nHeight
= std::min( pMaskAcc
->Height(), pAcc
->Height() );
1759 const Color
aColBlack( COL_BLACK
);
1761 BitmapColor aMaskPixel
;
1762 const BitmapColor
aWhite( pAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1763 const BitmapColor
aBlack( pAcc
->GetBestMatchingColor( aColBlack
) );
1764 const BitmapColor
aMaskBlack( pMaskAcc
->GetBestMatchingColor( aColBlack
) );
1768 case( BMP_COMBINE_COPY
):
1770 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1772 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskBlack
)
1773 pAcc
->SetPixel( nY
, nX
, aBlack
);
1775 pAcc
->SetPixel( nY
, nX
, aWhite
);
1780 case( BMP_COMBINE_INVERT
):
1782 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1784 if( pAcc
->GetPixel( nY
, nX
) == aBlack
)
1785 pAcc
->SetPixel( nY
, nX
, aWhite
);
1787 pAcc
->SetPixel( nY
, nX
, aBlack
);
1792 case( BMP_COMBINE_AND
):
1794 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1796 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
&& pAcc
->GetPixel( nY
, nX
) != aBlack
)
1797 pAcc
->SetPixel( nY
, nX
, aWhite
);
1799 pAcc
->SetPixel( nY
, nX
, aBlack
);
1804 case( BMP_COMBINE_NAND
):
1806 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1808 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
&& pAcc
->GetPixel( nY
, nX
) != aBlack
)
1809 pAcc
->SetPixel( nY
, nX
, aBlack
);
1811 pAcc
->SetPixel( nY
, nX
, aWhite
);
1816 case( BMP_COMBINE_OR
):
1818 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1820 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
|| pAcc
->GetPixel( nY
, nX
) != aBlack
)
1821 pAcc
->SetPixel( nY
, nX
, aWhite
);
1823 pAcc
->SetPixel( nY
, nX
, aBlack
);
1828 case( BMP_COMBINE_NOR
):
1830 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1832 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
|| pAcc
->GetPixel( nY
, nX
) != aBlack
)
1833 pAcc
->SetPixel( nY
, nX
, aBlack
);
1835 pAcc
->SetPixel( nY
, nX
, aWhite
);
1840 case( BMP_COMBINE_XOR
):
1842 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1844 aPixel
= pAcc
->GetPixel( nY
, nX
);
1845 aMaskPixel
= pMaskAcc
->GetPixel( nY
, nX
);
1847 if( ( aMaskPixel
!= aMaskBlack
&& aPixel
== aBlack
) ||
1848 ( aMaskPixel
== aMaskBlack
&& aPixel
!= aBlack
) )
1850 pAcc
->SetPixel( nY
, nX
, aWhite
);
1853 pAcc
->SetPixel( nY
, nX
, aBlack
);
1858 case( BMP_COMBINE_NXOR
):
1860 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1862 aPixel
= pAcc
->GetPixel( nY
, nX
);
1863 aMaskPixel
= pMaskAcc
->GetPixel( nY
, nX
);
1865 if( ( aMaskPixel
!= aMaskBlack
&& aPixel
== aBlack
) ||
1866 ( aMaskPixel
== aMaskBlack
&& aPixel
!= aBlack
) )
1868 pAcc
->SetPixel( nY
, nX
, aBlack
);
1871 pAcc
->SetPixel( nY
, nX
, aWhite
);
1880 ReleaseAccess( pMaskAcc
);
1881 ReleaseAccess( pAcc
);
1886 // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
1887 // optimizations. Might even consolidate the code here and there.
1888 bool Bitmap::Blend( const AlphaMask
& rAlpha
, const Color
& rBackgroundColor
)
1890 // Convert to a truecolor bitmap, if we're a paletted one. There's
1891 // room for tradeoff decision here, maybe later for an overload (or a flag)
1892 if( GetBitCount() <= 8 )
1893 Convert( BMP_CONVERSION_24BIT
);
1895 BitmapReadAccess
* pAlphaAcc
= const_cast<AlphaMask
&>(rAlpha
).AcquireReadAccess();
1896 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1899 if( pAlphaAcc
&& pAcc
)
1901 const long nWidth
= std::min( pAlphaAcc
->Width(), pAcc
->Width() );
1902 const long nHeight
= std::min( pAlphaAcc
->Height(), pAcc
->Height() );
1904 for( long nY
= 0L; nY
< nHeight
; ++nY
)
1905 for( long nX
= 0L; nX
< nWidth
; ++nX
)
1906 pAcc
->SetPixel( nY
, nX
,
1907 pAcc
->GetPixel( nY
, nX
).Merge( rBackgroundColor
,
1908 255 - pAlphaAcc
->GetPixelIndex( nY
, nX
) ) );
1913 ReleaseAccess( pAlphaAcc
);
1914 ReleaseAccess( pAcc
);
1919 bool Bitmap::MakeMono( sal_uInt8 cThreshold
)
1921 return ImplMakeMono( cThreshold
);
1924 bool Bitmap::GetSystemData( BitmapSystemData
& rData
) const
1929 SalBitmap
* pSalBitmap
= mpImpBmp
->ImplGetSalBitmap();
1931 bRet
= pSalBitmap
->GetSystemData( rData
);
1937 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */