1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bitmap.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <vcl/salbtype.hxx>
35 #include <tools/stream.hxx>
36 #include <vcl/bmpacc.hxx>
37 #include <tools/poly.hxx>
38 #include <vcl/outdev.hxx>
39 #include <vcl/impbmp.hxx>
40 #include <vcl/salbmp.hxx>
44 #include <vcl/bitmap.hxx>
45 #include <vcl/bitmapex.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/image.hxx>
58 // ------------------------------------------------------------------
60 Bitmap::Bitmap( const ResId
& rResId
) :
63 const BitmapEx
aBmpEx( rResId
);
65 if( !aBmpEx
.IsEmpty() )
66 *this = aBmpEx
.GetBitmap();
69 // ------------------------------------------------------------------
71 Bitmap::Bitmap( const Bitmap
& rBitmap
) :
72 maPrefMapMode ( rBitmap
.maPrefMapMode
),
73 maPrefSize ( rBitmap
.maPrefSize
)
75 mpImpBmp
= rBitmap
.mpImpBmp
;
78 mpImpBmp
->ImplIncRefCount();
81 // ------------------------------------------------------------------
83 Bitmap::Bitmap( SalBitmap
* pSalBitmap
)
85 mpImpBmp
= new ImpBitmap();
86 mpImpBmp
->ImplSetSalBitmap( pSalBitmap
);
87 maPrefMapMode
= MapMode( MAP_PIXEL
);
88 maPrefSize
= mpImpBmp
->ImplGetSize();
91 // ------------------------------------------------------------------
93 Bitmap::Bitmap( const Size
& rSizePixel
, USHORT nBitCount
, const BitmapPalette
* pPal
)
95 if( rSizePixel
.Width() && rSizePixel
.Height() )
98 BitmapPalette
* pRealPal
= NULL
;
106 aPal
.SetEntryCount( 2 );
107 aPal
[ 0 ] = Color( COL_BLACK
);
108 aPal
[ 1 ] = Color( COL_WHITE
);
110 else if( ( 4 == nBitCount
) || ( 8 == nBitCount
) )
112 aPal
.SetEntryCount( 1 << nBitCount
);
113 aPal
[ 0 ] = Color( COL_BLACK
);
114 aPal
[ 1 ] = Color( COL_BLUE
);
115 aPal
[ 2 ] = Color( COL_GREEN
);
116 aPal
[ 3 ] = Color( COL_CYAN
);
117 aPal
[ 4 ] = Color( COL_RED
);
118 aPal
[ 5 ] = Color( COL_MAGENTA
);
119 aPal
[ 6 ] = Color( COL_BROWN
);
120 aPal
[ 7 ] = Color( COL_GRAY
);
121 aPal
[ 8 ] = Color( COL_LIGHTGRAY
);
122 aPal
[ 9 ] = Color( COL_LIGHTBLUE
);
123 aPal
[ 10 ] = Color( COL_LIGHTGREEN
);
124 aPal
[ 11 ] = Color( COL_LIGHTCYAN
);
125 aPal
[ 12 ] = Color( COL_LIGHTRED
);
126 aPal
[ 13 ] = Color( COL_LIGHTMAGENTA
);
127 aPal
[ 14 ] = Color( COL_YELLOW
);
128 aPal
[ 15 ] = Color( COL_WHITE
);
130 // Dither-Palette erzeugen
135 for( USHORT nB
= 0; nB
< 256; nB
+= 51 )
136 for( USHORT nG
= 0; nG
< 256; nG
+= 51 )
137 for( USHORT nR
= 0; nR
< 256; nR
+= 51 )
138 aPal
[ nActCol
++ ] = BitmapColor( (BYTE
) nR
, (BYTE
) nG
, (BYTE
) nB
);
140 // Standard-Office-Farbe setzen
141 aPal
[ nActCol
++ ] = BitmapColor( 0, 184, 255 );
146 pRealPal
= (BitmapPalette
*) pPal
;
149 mpImpBmp
= new ImpBitmap
;
150 mpImpBmp
->ImplCreate( rSizePixel
, nBitCount
, pRealPal
? *pRealPal
: aPal
);
156 // ------------------------------------------------------------------
163 // ------------------------------------------------------------------
165 const BitmapPalette
& Bitmap::GetGreyPalette( int nEntries
)
167 static BitmapPalette aGreyPalette2
;
168 static BitmapPalette aGreyPalette4
;
169 static BitmapPalette aGreyPalette16
;
170 static BitmapPalette aGreyPalette256
;
172 // create greyscale palette with 2, 4, 16 or 256 entries
173 if( 2 == nEntries
|| 4 == nEntries
|| 16 == nEntries
|| 256 == nEntries
)
177 if( !aGreyPalette2
.GetEntryCount() )
179 aGreyPalette2
.SetEntryCount( 2 );
180 aGreyPalette2
[ 0 ] = BitmapColor( 0, 0, 0 );
181 aGreyPalette2
[ 1 ] = BitmapColor( 255, 255, 255 );
184 return aGreyPalette2
;
186 else if( 4 == nEntries
)
188 if( !aGreyPalette4
.GetEntryCount() )
190 aGreyPalette4
.SetEntryCount( 4 );
191 aGreyPalette4
[ 0 ] = BitmapColor( 0, 0, 0 );
192 aGreyPalette4
[ 1 ] = BitmapColor( 85, 85, 85 );
193 aGreyPalette4
[ 2 ] = BitmapColor( 170, 170, 170 );
194 aGreyPalette4
[ 3 ] = BitmapColor( 255, 255, 255 );
197 return aGreyPalette4
;
199 else if( 16 == nEntries
)
201 if( !aGreyPalette16
.GetEntryCount() )
203 BYTE cGrey
= 0, cGreyInc
= 17;
205 aGreyPalette16
.SetEntryCount( 16 );
207 for( USHORT i
= 0; i
< 16; i
++, cGrey
= sal::static_int_cast
<BYTE
>(cGrey
+ cGreyInc
) )
208 aGreyPalette16
[ i
] = BitmapColor( cGrey
, cGrey
, cGrey
);
211 return aGreyPalette16
;
215 if( !aGreyPalette256
.GetEntryCount() )
217 aGreyPalette256
.SetEntryCount( 256 );
219 for( USHORT i
= 0; i
< 256; i
++ )
220 aGreyPalette256
[ i
] = BitmapColor( (BYTE
) i
, (BYTE
) i
, (BYTE
) i
);
223 return aGreyPalette256
;
228 DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
229 return aGreyPalette2
;
233 // ------------------------------------------------------------------
235 bool BitmapPalette::IsGreyPalette() const
237 // TODO: add an IsGreyPalette flag to BitmapPalette
238 // TODO: unless this causes problems binary compatibility
239 const int nEntryCount
= GetEntryCount();
240 if( !nEntryCount
) // NOTE: an empty palette means 1:1 mapping
242 const BitmapPalette
& rGreyPalette
= Bitmap::GetGreyPalette( nEntryCount
);
243 if( rGreyPalette
== *this )
245 // TODO: is it worth to compare the entries?
249 // ------------------------------------------------------------------
251 Bitmap
& Bitmap::operator=( const Bitmap
& rBitmap
)
253 maPrefSize
= rBitmap
.maPrefSize
;
254 maPrefMapMode
= rBitmap
.maPrefMapMode
;
256 if ( rBitmap
.mpImpBmp
)
257 rBitmap
.mpImpBmp
->ImplIncRefCount();
260 mpImpBmp
= rBitmap
.mpImpBmp
;
265 // ------------------------------------------------------------------
267 BOOL
Bitmap::IsEqual( const Bitmap
& rBmp
) const
269 return( IsSameInstance( rBmp
) ||
270 ( rBmp
.GetSizePixel() == GetSizePixel() &&
271 rBmp
.GetBitCount() == GetBitCount() &&
272 rBmp
.GetChecksum() == GetChecksum() ) );
275 // ------------------------------------------------------------------
277 void Bitmap::SetEmpty()
279 maPrefMapMode
= MapMode();
286 // ------------------------------------------------------------------
288 Size
Bitmap::GetSizePixel() const
290 return( mpImpBmp
? mpImpBmp
->ImplGetSize() : Size() );
292 // ------------------------------------------------------------------
294 void Bitmap::SetSizePixel( const Size
& rNewSize
)
299 // ------------------------------------------------------------------
301 Size
Bitmap::GetSourceSizePixel() const
303 return( mpImpBmp
? mpImpBmp
->ImplGetSourceSize() : Size() );
306 // ------------------------------------------------------------------
308 void Bitmap::SetSourceSizePixel( const Size
& rSize
)
311 mpImpBmp
->ImplSetSourceSize( rSize
);
314 // ------------------------------------------------------------------
316 USHORT
Bitmap::GetBitCount() const
318 return( mpImpBmp
? mpImpBmp
->ImplGetBitCount() : 0 );
321 // ------------------------------------------------------------------
323 BOOL
Bitmap::HasGreyPalette() const
325 const USHORT nBitCount
= GetBitCount();
330 else if( 4 == nBitCount
|| 8 == nBitCount
)
332 BitmapReadAccess
* pRAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
336 if( pRAcc
->HasPalette() && ( (BitmapPalette
&) pRAcc
->GetPalette() == GetGreyPalette( 1 << nBitCount
) ) )
339 ( (Bitmap
*) this )->ReleaseAccess( pRAcc
);
346 // ------------------------------------------------------------------
348 ULONG
Bitmap::GetChecksum() const
354 nRet
= mpImpBmp
->ImplGetChecksum();
358 BitmapReadAccess
* pRAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
360 if( pRAcc
&& pRAcc
->Width() && pRAcc
->Height() )
365 pRAcc
->ImplZeroInitUnusedBits();
367 UInt32ToSVBT32( pRAcc
->Width(), aBT32
);
368 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
370 UInt32ToSVBT32( pRAcc
->Height(), aBT32
);
371 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
373 UInt32ToSVBT32( pRAcc
->GetBitCount(), aBT32
);
374 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
376 UInt32ToSVBT32( pRAcc
->GetColorMask().GetRedMask(), aBT32
);
377 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
379 UInt32ToSVBT32( pRAcc
->GetColorMask().GetGreenMask(), aBT32
);
380 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
382 UInt32ToSVBT32( pRAcc
->GetColorMask().GetBlueMask(), aBT32
);
383 nCrc
= rtl_crc32( nCrc
, aBT32
, 4 );
385 if( pRAcc
->HasPalette() )
387 nCrc
= rtl_crc32( nCrc
, pRAcc
->GetPalette().ImplGetColorBuffer(),
388 pRAcc
->GetPaletteEntryCount() * sizeof( BitmapColor
) );
391 nCrc
= rtl_crc32( nCrc
, pRAcc
->GetBuffer(), pRAcc
->GetScanlineSize() * pRAcc
->Height() );
393 mpImpBmp
->ImplSetChecksum( nRet
= nCrc
);
396 if (pRAcc
) ( (Bitmap
*) this )->ReleaseAccess( pRAcc
);
403 // ------------------------------------------------------------------
405 void Bitmap::ImplReleaseRef()
409 if( mpImpBmp
->ImplGetRefCount() > 1UL )
410 mpImpBmp
->ImplDecRefCount();
419 // ------------------------------------------------------------------
421 void Bitmap::ImplMakeUnique()
423 if( mpImpBmp
&& mpImpBmp
->ImplGetRefCount() > 1UL )
425 ImpBitmap
* pOldImpBmp
= mpImpBmp
;
427 pOldImpBmp
->ImplDecRefCount();
429 mpImpBmp
= new ImpBitmap
;
430 mpImpBmp
->ImplCreate( *pOldImpBmp
);
434 // ------------------------------------------------------------------
436 void Bitmap::ImplAssignWithSize( const Bitmap
& rBitmap
)
438 const Size
aOldSizePix( GetSizePixel() );
439 const Size
aNewSizePix( rBitmap
.GetSizePixel() );
440 const MapMode
aOldMapMode( maPrefMapMode
);
443 if( ( aOldSizePix
!= aNewSizePix
) && aOldSizePix
.Width() && aOldSizePix
.Height() )
445 aNewPrefSize
.Width() = FRound( maPrefSize
.Width() * aNewSizePix
.Width() / aOldSizePix
.Width() );
446 aNewPrefSize
.Height() = FRound( maPrefSize
.Height() * aNewSizePix
.Height() / aOldSizePix
.Height() );
449 aNewPrefSize
= maPrefSize
;
453 maPrefSize
= aNewPrefSize
;
454 maPrefMapMode
= aOldMapMode
;
457 // ------------------------------------------------------------------
459 ImpBitmap
* Bitmap::ImplGetImpBitmap() const
464 // ------------------------------------------------------------------
466 void Bitmap::ImplSetImpBitmap( ImpBitmap
* pImpBmp
)
468 if( pImpBmp
!= mpImpBmp
)
475 // ------------------------------------------------------------------
477 BitmapReadAccess
* Bitmap::AcquireReadAccess()
479 BitmapReadAccess
* pReadAccess
= new BitmapReadAccess( *this );
490 // ------------------------------------------------------------------
492 BitmapWriteAccess
* Bitmap::AcquireWriteAccess()
494 BitmapWriteAccess
* pWriteAccess
= new BitmapWriteAccess( *this );
505 // ------------------------------------------------------------------
507 void Bitmap::ReleaseAccess( BitmapReadAccess
* pBitmapAccess
)
509 delete pBitmapAccess
;
512 // ------------------------------------------------------------------
514 BOOL
Bitmap::Erase( const Color
& rFillColor
)
519 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
524 const ULONG nFormat
= pWriteAcc
->GetScanlineFormat();
530 case( BMP_FORMAT_1BIT_MSB_PAL
):
531 case( BMP_FORMAT_1BIT_LSB_PAL
):
533 cIndex
= (BYTE
) pWriteAcc
->GetBestPaletteIndex( rFillColor
);
534 cIndex
= ( cIndex
? 255 : 0 );
539 case( BMP_FORMAT_4BIT_MSN_PAL
):
540 case( BMP_FORMAT_4BIT_LSN_PAL
):
542 cIndex
= (BYTE
) pWriteAcc
->GetBestPaletteIndex( rFillColor
);
543 cIndex
= cIndex
| ( cIndex
<< 4 );
548 case( BMP_FORMAT_8BIT_PAL
):
550 cIndex
= (BYTE
) pWriteAcc
->GetBestPaletteIndex( rFillColor
);
555 case( BMP_FORMAT_24BIT_TC_BGR
):
556 case( BMP_FORMAT_24BIT_TC_RGB
):
558 if( ( rFillColor
.GetRed() == rFillColor
.GetGreen() ) &&
559 ( rFillColor
.GetRed() == rFillColor
.GetBlue() ) )
561 cIndex
= rFillColor
.GetRed();
576 const ULONG nBufSize
= pWriteAcc
->GetScanlineSize() * pWriteAcc
->Height();
577 memset( pWriteAcc
->GetBuffer(), cIndex
, nBufSize
);
582 const Rectangle
aRect( aTmpPoint
, Size( pWriteAcc
->Width(), pWriteAcc
->Height() ) );
583 pWriteAcc
->SetFillColor( rFillColor
);
584 pWriteAcc
->FillRect( aRect
);
587 ReleaseAccess( pWriteAcc
);
594 // ------------------------------------------------------------------
596 BOOL
Bitmap::Invert()
598 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
603 if( pAcc
->HasPalette() )
605 BitmapPalette
aBmpPal( pAcc
->GetPalette() );
606 const USHORT nCount
= aBmpPal
.GetEntryCount();
608 for( USHORT i
= 0; i
< nCount
; i
++ )
609 aBmpPal
[ i
].Invert();
611 pAcc
->SetPalette( aBmpPal
);
615 const long nWidth
= pAcc
->Width();
616 const long nHeight
= pAcc
->Height();
618 for( long nX
= 0L; nX
< nWidth
; nX
++ )
619 for( long nY
= 0L; nY
< nHeight
; nY
++ )
620 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nY
, nX
).Invert() );
623 ReleaseAccess( pAcc
);
630 // ------------------------------------------------------------------
632 BOOL
Bitmap::Mirror( ULONG nMirrorFlags
)
634 BOOL bHorz
= ( ( nMirrorFlags
& BMP_MIRROR_HORZ
) == BMP_MIRROR_HORZ
);
635 BOOL bVert
= ( ( nMirrorFlags
& BMP_MIRROR_VERT
) == BMP_MIRROR_VERT
);
638 if( bHorz
&& !bVert
)
640 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
644 const long nWidth
= pAcc
->Width();
645 const long nHeight
= pAcc
->Height();
646 const long nWidth1
= nWidth
- 1L;
647 const long nWidth_2
= nWidth
>> 1L;
649 for( long nY
= 0L; nY
< nHeight
; nY
++ )
651 for( long nX
= 0L, nOther
= nWidth1
; nX
< nWidth_2
; nX
++, nOther
-- )
653 const BitmapColor
aTemp( pAcc
->GetPixel( nY
, nX
) );
655 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nY
, nOther
) );
656 pAcc
->SetPixel( nY
, nOther
, aTemp
);
660 ReleaseAccess( pAcc
);
664 else if( bVert
&& !bHorz
)
666 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
670 const long nScanSize
= pAcc
->GetScanlineSize();
671 BYTE
* pBuffer
= new BYTE
[ nScanSize
];
672 const long nHeight
= pAcc
->Height();
673 const long nHeight1
= nHeight
- 1L;
674 const long nHeight_2
= nHeight
>> 1L;
676 for( long nY
= 0L, nOther
= nHeight1
; nY
< nHeight_2
; nY
++, nOther
-- )
678 memcpy( pBuffer
, pAcc
->GetScanline( nY
), nScanSize
);
679 memcpy( pAcc
->GetScanline( nY
), pAcc
->GetScanline( nOther
), nScanSize
);
680 memcpy( pAcc
->GetScanline( nOther
), pBuffer
, nScanSize
);
684 ReleaseAccess( pAcc
);
688 else if( bHorz
&& bVert
)
690 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
694 const long nWidth
= pAcc
->Width();
695 const long nWidth1
= nWidth
- 1L;
696 const long nHeight
= pAcc
->Height();
697 long nHeight_2
= nHeight
>> 1;
699 for( long nY
= 0L, nOtherY
= nHeight
- 1L; nY
< nHeight_2
; nY
++, nOtherY
-- )
701 for( long nX
= 0L, nOtherX
= nWidth1
; nX
< nWidth
; nX
++, nOtherX
-- )
703 const BitmapColor
aTemp( pAcc
->GetPixel( nY
, nX
) );
705 pAcc
->SetPixel( nY
, nX
, pAcc
->GetPixel( nOtherY
, nOtherX
) );
706 pAcc
->SetPixel( nOtherY
, nOtherX
, aTemp
);
710 // ggf. noch mittlere Zeile horizontal spiegeln
713 for( long nX
= 0L, nOtherX
= nWidth1
, nWidth_2
= nWidth
>> 1; nX
< nWidth_2
; nX
++, nOtherX
-- )
715 const BitmapColor
aTemp( pAcc
->GetPixel( nHeight_2
, nX
) );
716 pAcc
->SetPixel( nHeight_2
, nX
, pAcc
->GetPixel( nHeight_2
, nOtherX
) );
717 pAcc
->SetPixel( nHeight_2
, nOtherX
, aTemp
);
721 ReleaseAccess( pAcc
);
731 // ------------------------------------------------------------------
733 BOOL
Bitmap::Rotate( long nAngle10
, const Color
& rFillColor
)
738 nAngle10
= ( nAngle10
< 0L ) ? ( 3599L + nAngle10
) : nAngle10
;
742 else if( 1800L == nAngle10
)
743 bRet
= Mirror( BMP_MIRROR_HORZ
| BMP_MIRROR_VERT
);
746 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
751 const Size
aSizePix( GetSizePixel() );
753 if( ( 900L == nAngle10
) || ( 2700L == nAngle10
) )
755 const Size
aNewSizePix( aSizePix
.Height(), aSizePix
.Width() );
756 Bitmap
aNewBmp( aNewSizePix
, GetBitCount(), &pReadAcc
->GetPalette() );
757 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
761 const long nWidth
= aSizePix
.Width();
762 const long nWidth1
= nWidth
- 1L;
763 const long nHeight
= aSizePix
.Height();
764 const long nHeight1
= nHeight
- 1L;
765 const long nNewWidth
= aNewSizePix
.Width();
766 const long nNewHeight
= aNewSizePix
.Height();
768 if( 900L == nAngle10
)
770 for( long nY
= 0L, nOtherX
= nWidth1
; nY
< nNewHeight
; nY
++, nOtherX
-- )
771 for( long nX
= 0L, nOtherY
= 0L; nX
< nNewWidth
; nX
++ )
772 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nOtherY
++, nOtherX
) );
774 else if( 2700L == nAngle10
)
776 for( long nY
= 0L, nOtherX
= 0L; nY
< nNewHeight
; nY
++, nOtherX
++ )
777 for( long nX
= 0L, nOtherY
= nHeight1
; nX
< nNewWidth
; nX
++ )
778 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nOtherY
--, nOtherX
) );
781 aNewBmp
.ReleaseAccess( pWriteAcc
);
784 aRotatedBmp
= aNewBmp
;
789 Rectangle
aTmpRectangle( aTmpPoint
, aSizePix
);
790 Polygon
aPoly( aTmpRectangle
);
791 aPoly
.Rotate( aTmpPoint
, (USHORT
) nAngle10
);
793 Rectangle
aNewBound( aPoly
.GetBoundRect() );
794 const Size
aNewSizePix( aNewBound
.GetSize() );
795 Bitmap
aNewBmp( aNewSizePix
, GetBitCount(), &pReadAcc
->GetPalette() );
796 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
800 const BitmapColor
aFillColor( pWriteAcc
->GetBestMatchingColor( rFillColor
) );
801 const double fCosAngle
= cos( nAngle10
* F_PI1800
);
802 const double fSinAngle
= sin( nAngle10
* F_PI1800
);
803 const double fXMin
= aNewBound
.Left();
804 const double fYMin
= aNewBound
.Top();
805 const long nWidth
= aSizePix
.Width();
806 const long nHeight
= aSizePix
.Height();
807 const long nNewWidth
= aNewSizePix
.Width();
808 const long nNewHeight
= aNewSizePix
.Height();
815 long* pCosX
= new long[ nNewWidth
];
816 long* pSinX
= new long[ nNewWidth
];
817 long* pCosY
= new long[ nNewHeight
];
818 long* pSinY
= new long[ nNewHeight
];
820 for ( nX
= 0; nX
< nNewWidth
; nX
++ )
822 const double fTmp
= ( fXMin
+ nX
) * 64.;
824 pCosX
[ nX
] = FRound( fCosAngle
* fTmp
);
825 pSinX
[ nX
] = FRound( fSinAngle
* fTmp
);
828 for ( nY
= 0; nY
< nNewHeight
; nY
++ )
830 const double fTmp
= ( fYMin
+ nY
) * 64.;
832 pCosY
[ nY
] = FRound( fCosAngle
* fTmp
);
833 pSinY
[ nY
] = FRound( fSinAngle
* fTmp
);
836 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
841 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
843 nRotX
= ( pCosX
[ nX
] - nSinY
) >> 6;
844 nRotY
= ( pSinX
[ nX
] + nCosY
) >> 6;
846 if ( ( nRotX
> -1L ) && ( nRotX
< nWidth
) && ( nRotY
> -1L ) && ( nRotY
< nHeight
) )
847 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nRotY
, nRotX
) );
849 pWriteAcc
->SetPixel( nY
, nX
, aFillColor
);
858 aNewBmp
.ReleaseAccess( pWriteAcc
);
861 aRotatedBmp
= aNewBmp
;
864 ReleaseAccess( pReadAcc
);
867 if( ( bRet
= !!aRotatedBmp
) == TRUE
)
868 ImplAssignWithSize( aRotatedBmp
);
874 // ------------------------------------------------------------------
876 BOOL
Bitmap::Crop( const Rectangle
& rRectPixel
)
878 const Size
aSizePix( GetSizePixel() );
879 Rectangle
aRect( rRectPixel
);
882 aRect
.Intersection( Rectangle( Point(), aSizePix
) );
884 if( !aRect
.IsEmpty() )
886 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
891 const Rectangle
aNewRect( aTmpPoint
, aRect
.GetSize() );
892 Bitmap
aNewBmp( aNewRect
.GetSize(), GetBitCount(), &pReadAcc
->GetPalette() );
893 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
897 const long nOldX
= aRect
.Left();
898 const long nOldY
= aRect
.Top();
899 const long nNewWidth
= aNewRect
.GetWidth();
900 const long nNewHeight
= aNewRect
.GetHeight();
902 for( long nY
= 0, nY2
= nOldY
; nY
< nNewHeight
; nY
++, nY2
++ )
903 for( long nX
= 0, nX2
= nOldX
; nX
< nNewWidth
; nX
++, nX2
++ )
904 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nY2
, nX2
) );
906 aNewBmp
.ReleaseAccess( pWriteAcc
);
910 ReleaseAccess( pReadAcc
);
913 ImplAssignWithSize( aNewBmp
);
920 // ------------------------------------------------------------------
922 BOOL
Bitmap::CopyPixel( const Rectangle
& rRectDst
,
923 const Rectangle
& rRectSrc
, const Bitmap
* pBmpSrc
)
925 const Size
aSizePix( GetSizePixel() );
926 Rectangle
aRectDst( rRectDst
);
929 aRectDst
.Intersection( Rectangle( Point(), aSizePix
) );
931 if( !aRectDst
.IsEmpty() )
933 if( pBmpSrc
&& ( *pBmpSrc
!= *this ) )
935 Bitmap
* pSrc
= (Bitmap
*) pBmpSrc
;
936 const Size
aCopySizePix( pSrc
->GetSizePixel() );
937 Rectangle
aRectSrc( rRectSrc
);
938 const USHORT nSrcBitCount
= pBmpSrc
->GetBitCount();
939 const USHORT nDstBitCount
= GetBitCount();
941 if( nSrcBitCount
> nDstBitCount
)
943 long nNextIndex
= 0L;
945 if( ( nSrcBitCount
== 24 ) && ( nDstBitCount
< 24 ) )
946 Convert( BMP_CONVERSION_24BIT
);
947 else if( ( nSrcBitCount
== 8 ) && ( nDstBitCount
< 8 ) )
949 Convert( BMP_CONVERSION_8BIT_COLORS
);
952 else if( ( nSrcBitCount
== 4 ) && ( nDstBitCount
< 4 ) )
954 Convert( BMP_CONVERSION_4BIT_COLORS
);
960 BitmapReadAccess
* pSrcAcc
= pSrc
->AcquireReadAccess();
961 BitmapWriteAccess
* pDstAcc
= AcquireWriteAccess();
963 if( pSrcAcc
&& pDstAcc
)
965 const long nSrcCount
= pDstAcc
->GetPaletteEntryCount();
966 const long nDstCount
= 1 << nDstBitCount
;
969 for( long i
= 0L; ( i
< nSrcCount
) && ( nNextIndex
< nSrcCount
); i
++ )
971 const BitmapColor
& rSrcCol
= pSrcAcc
->GetPaletteColor( (USHORT
) i
);
975 for( long j
= 0L; j
< nDstCount
; j
++ )
977 if( rSrcCol
== pDstAcc
->GetPaletteColor( (USHORT
) j
) )
985 pDstAcc
->SetPaletteColor( (USHORT
) nNextIndex
++, rSrcCol
);
990 pSrc
->ReleaseAccess( pSrcAcc
);
993 ReleaseAccess( pDstAcc
);
997 aRectSrc
.Intersection( Rectangle( Point(), aCopySizePix
) );
999 if( !aRectSrc
.IsEmpty() )
1001 BitmapReadAccess
* pReadAcc
= pSrc
->AcquireReadAccess();
1005 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
1009 const long nWidth
= Min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
1010 const long nHeight
= Min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
1011 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
1012 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
1013 long nDstY
= aRectDst
.Top();
1015 if( pReadAcc
->HasPalette() && pWriteAcc
->HasPalette() )
1017 const USHORT nCount
= pReadAcc
->GetPaletteEntryCount();
1018 BYTE
* pMap
= new BYTE
[ nCount
];
1020 // Index-Map fuer Farbtabelle
1021 // aufbauen, da das Bild ja (relativ) farbgenau
1022 // kopiert werden soll
1023 for( USHORT i
= 0; i
< nCount
; i
++ )
1024 pMap
[ i
] = (BYTE
) pWriteAcc
->GetBestPaletteIndex( pReadAcc
->GetPaletteColor( i
) );
1026 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
1027 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
1028 pWriteAcc
->SetPixel( nDstY
, nDstX
, pMap
[ pReadAcc
->GetPixel( nSrcY
, nSrcX
).GetIndex() ] );
1032 else if( pReadAcc
->HasPalette() )
1034 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
1035 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
1036 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nSrcY
, nSrcX
) ) );
1039 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
1040 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
1041 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPixel( nSrcY
, nSrcX
) );
1043 ReleaseAccess( pWriteAcc
);
1044 bRet
= ( nWidth
> 0L ) && ( nHeight
> 0L );
1047 pSrc
->ReleaseAccess( pReadAcc
);
1053 Rectangle
aRectSrc( rRectSrc
);
1055 aRectSrc
.Intersection( Rectangle( Point(), aSizePix
) );
1057 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
1059 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
1063 const long nWidth
= Min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
1064 const long nHeight
= Min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
1065 const long nSrcX
= aRectSrc
.Left();
1066 const long nSrcY
= aRectSrc
.Top();
1067 const long nSrcEndX1
= nSrcX
+ nWidth
- 1L;
1068 const long nSrcEndY1
= nSrcY
+ nHeight
- 1L;
1069 const long nDstX
= aRectDst
.Left();
1070 const long nDstY
= aRectDst
.Top();
1071 const long nDstEndX1
= nDstX
+ nWidth
- 1L;
1072 const long nDstEndY1
= nDstY
+ nHeight
- 1L;
1074 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
1076 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
1077 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
1078 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1080 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
1082 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
1083 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
1084 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1086 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
1088 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
1089 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
1090 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1094 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
1095 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
1096 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
1099 ReleaseAccess( pWriteAcc
);
1109 // ------------------------------------------------------------------
1111 BOOL
Bitmap::Expand( ULONG nDX
, ULONG nDY
, const Color
* pInitColor
)
1117 const Size
aSizePixel( GetSizePixel() );
1118 const long nWidth
= aSizePixel
.Width();
1119 const long nHeight
= aSizePixel
.Height();
1120 const Size
aNewSize( nWidth
+ nDX
, nHeight
+ nDY
);
1121 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1125 BitmapPalette
aBmpPal( pReadAcc
->GetPalette() );
1126 Bitmap
aNewBmp( aNewSize
, GetBitCount(), &aBmpPal
);
1127 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1132 const long nNewX
= nWidth
;
1133 const long nNewY
= nHeight
;
1134 const long nNewWidth
= pWriteAcc
->Width();
1135 const long nNewHeight
= pWriteAcc
->Height();
1140 aColor
= pWriteAcc
->GetBestMatchingColor( *pInitColor
);
1142 for( nY
= 0L; nY
< nHeight
; nY
++ )
1144 pWriteAcc
->CopyScanline( nY
, *pReadAcc
);
1146 if( pInitColor
&& nDX
)
1147 for( nX
= nNewX
; nX
< nNewWidth
; nX
++ )
1148 pWriteAcc
->SetPixel( nY
, nX
, aColor
);
1151 if( pInitColor
&& nDY
)
1152 for( nY
= nNewY
; nY
< nNewHeight
; nY
++ )
1153 for( nX
= 0; nX
< nNewWidth
; nX
++ )
1154 pWriteAcc
->SetPixel( nY
, nX
, aColor
);
1156 aNewBmp
.ReleaseAccess( pWriteAcc
);
1160 ReleaseAccess( pReadAcc
);
1163 ImplAssignWithSize( aNewBmp
);
1170 // ------------------------------------------------------------------
1172 Bitmap
Bitmap::CreateMask( const Color
& rTransColor
, ULONG nTol
) const
1174 Bitmap
aNewBmp( GetSizePixel(), 1 );
1175 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1180 BitmapReadAccess
* pReadAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
1184 const long nWidth
= pReadAcc
->Width();
1185 const long nHeight
= pReadAcc
->Height();
1186 const BitmapColor
aBlack( pWriteAcc
->GetBestMatchingColor( Color( COL_BLACK
) ) );
1187 const BitmapColor
aWhite( pWriteAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1191 const BitmapColor
aTest( pReadAcc
->GetBestMatchingColor( rTransColor
) );
1192 long nX
, nY
, nShift
;
1194 if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL
||
1195 pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL
)
1197 // optimized for 4Bit-MSN/LSN source palette
1198 const BYTE cTest
= aTest
.GetIndex();
1199 const long nShiftInit
= ( ( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL
) ? 4 : 0 );
1201 if( pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
&&
1202 aWhite
.GetIndex() == 1 )
1204 // optimized for 1Bit-MSB destination palette
1205 for( nY
= 0L; nY
< nHeight
; nY
++ )
1207 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1208 Scanline pDst
= pWriteAcc
->GetScanline( nY
);
1209 for( nX
= 0L, nShift
= nShiftInit
; nX
< nWidth
; nX
++, nShift
^= 4 )
1211 if( cTest
== ( ( pSrc
[ nX
>> 1 ] >> nShift
) & 0x0f ) )
1212 pDst
[ nX
>> 3 ] |= 1 << ( 7 - ( nX
& 7 ) );
1214 pDst
[ nX
>> 3 ] &= ~( 1 << ( 7 - ( nX
& 7 ) ) );
1220 for( nY
= 0L; nY
< nHeight
; nY
++ )
1222 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1223 for( nX
= 0L, nShift
= nShiftInit
; nX
< nWidth
; nX
++, nShift
^= 4 )
1225 if( cTest
== ( ( pSrc
[ nX
>> 1 ] >> nShift
) & 0x0f ) )
1226 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1228 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1233 else if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
)
1235 // optimized for 8Bit source palette
1236 const BYTE cTest
= aTest
.GetIndex();
1238 if( pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
&&
1239 aWhite
.GetIndex() == 1 )
1241 // optimized for 1Bit-MSB destination palette
1242 for( nY
= 0L; nY
< nHeight
; nY
++ )
1244 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1245 Scanline pDst
= pWriteAcc
->GetScanline( nY
);
1246 for( nX
= 0L; nX
< nWidth
; nX
++ )
1248 if( cTest
== pSrc
[ nX
] )
1249 pDst
[ nX
>> 3 ] |= 1 << ( 7 - ( nX
& 7 ) );
1251 pDst
[ nX
>> 3 ] &= ~( 1 << ( 7 - ( nX
& 7 ) ) );
1257 for( nY
= 0L; nY
< nHeight
; nY
++ )
1259 Scanline pSrc
= pReadAcc
->GetScanline( nY
);
1260 for( nX
= 0L; nX
< nWidth
; nX
++ )
1262 if( cTest
== pSrc
[ nX
] )
1263 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1265 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1273 for( nY
= 0L; nY
< nHeight
; nY
++ )
1275 for( nX
= 0L; nX
< nWidth
; nX
++ )
1277 if( aTest
== pReadAcc
->GetPixel( nY
, nX
) )
1278 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1280 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1289 const long nMinR
= MinMax( (long) rTransColor
.GetRed() - nTol
, 0, 255 );
1290 const long nMaxR
= MinMax( (long) rTransColor
.GetRed() + nTol
, 0, 255 );
1291 const long nMinG
= MinMax( (long) rTransColor
.GetGreen() - nTol
, 0, 255 );
1292 const long nMaxG
= MinMax( (long) rTransColor
.GetGreen() + nTol
, 0, 255 );
1293 const long nMinB
= MinMax( (long) rTransColor
.GetBlue() - nTol
, 0, 255 );
1294 const long nMaxB
= MinMax( (long) rTransColor
.GetBlue() + nTol
, 0, 255 );
1296 if( pReadAcc
->HasPalette() )
1298 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1300 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1302 aCol
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nX
) );
1304 nG
= aCol
.GetGreen();
1305 nB
= aCol
.GetBlue();
1307 if( nMinR
<= nR
&& nMaxR
>= nR
&&
1308 nMinG
<= nG
&& nMaxG
>= nG
&&
1309 nMinB
<= nB
&& nMaxB
>= nB
)
1311 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1314 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1320 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1322 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1324 aCol
= pReadAcc
->GetPixel( nY
, nX
);
1326 nG
= aCol
.GetGreen();
1327 nB
= aCol
.GetBlue();
1329 if( nMinR
<= nR
&& nMaxR
>= nR
&&
1330 nMinG
<= nG
&& nMaxG
>= nG
&&
1331 nMinB
<= nB
&& nMaxB
>= nB
)
1333 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
1336 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
1342 ( (Bitmap
*) this )->ReleaseAccess( pReadAcc
);
1346 aNewBmp
.ReleaseAccess( pWriteAcc
);
1351 aNewBmp
.maPrefSize
= maPrefSize
;
1352 aNewBmp
.maPrefMapMode
= maPrefMapMode
;
1360 // ------------------------------------------------------------------
1362 Region
Bitmap::CreateRegion( const Color
& rColor
, const Rectangle
& rRect
) const
1365 Rectangle
aRect( rRect
);
1366 BitmapReadAccess
* pReadAcc
= ( (Bitmap
*) this )->AcquireReadAccess();
1368 aRect
.Intersection( Rectangle( Point(), GetSizePixel() ) );
1374 const long nLeft
= aRect
.Left();
1375 const long nTop
= aRect
.Top();
1376 const long nRight
= aRect
.Right();
1377 const long nBottom
= aRect
.Bottom();
1378 const BitmapColor
aMatch( pReadAcc
->GetBestMatchingColor( rColor
) );
1380 aRegion
.ImplBeginAddRect();
1382 for( long nY
= nTop
; nY
<= nBottom
; nY
++ )
1384 aSubRect
.Top() = aSubRect
.Bottom() = nY
;
1386 for( long nX
= nLeft
; nX
<= nRight
; )
1388 while( ( nX
<= nRight
) && ( aMatch
!= pReadAcc
->GetPixel( nY
, nX
) ) )
1393 aSubRect
.Left() = nX
;
1395 while( ( nX
<= nRight
) && ( aMatch
== pReadAcc
->GetPixel( nY
, nX
) ) )
1398 aSubRect
.Right() = nX
- 1L;
1399 aRegion
.ImplAddRect( aSubRect
);
1404 aRegion
.ImplEndAddRect();
1405 ( (Bitmap
*) this )->ReleaseAccess( pReadAcc
);
1413 // ------------------------------------------------------------------
1415 BOOL
Bitmap::Replace( const Bitmap
& rMask
, const Color
& rReplaceColor
)
1417 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
1418 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1421 if( pMaskAcc
&& pAcc
)
1423 const long nWidth
= Min( pMaskAcc
->Width(), pAcc
->Width() );
1424 const long nHeight
= Min( pMaskAcc
->Height(), pAcc
->Height() );
1425 const BitmapColor
aMaskWhite( pMaskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1426 BitmapColor aReplace
;
1428 if( pAcc
->HasPalette() )
1430 const USHORT nActColors
= pAcc
->GetPaletteEntryCount();
1431 const USHORT nMaxColors
= 1 << pAcc
->GetBitCount();
1433 // erst einmal naechste Farbe nehmen
1434 aReplace
= pAcc
->GetBestMatchingColor( rReplaceColor
);
1436 // falls Palettenbild, und die zu setzende Farbe ist nicht
1437 // in der Palette, suchen wir nach freien Eintraegen (teuer)
1438 if( pAcc
->GetPaletteColor( (BYTE
) aReplace
) != BitmapColor( rReplaceColor
) )
1440 // erst einmal nachsehen, ob wir unsere ReplaceColor
1441 // nicht auf einen freien Platz am Ende der Palette
1443 if( nActColors
< nMaxColors
)
1445 pAcc
->SetPaletteEntryCount( nActColors
+ 1 );
1446 pAcc
->SetPaletteColor( nActColors
, rReplaceColor
);
1447 aReplace
= BitmapColor( (BYTE
) nActColors
);
1451 BOOL
* pFlags
= new BOOL
[ nMaxColors
];
1453 // alle Eintraege auf 0 setzen
1454 memset( pFlags
, 0, nMaxColors
);
1456 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1457 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1458 pFlags
[ (BYTE
) pAcc
->GetPixel( nY
, nX
) ] = TRUE
;
1460 for( USHORT i
= 0UL; i
< nMaxColors
; i
++ )
1462 // Hurra, wir haben einen unbenutzten Eintrag
1465 pAcc
->SetPaletteColor( (USHORT
) i
, rReplaceColor
);
1466 aReplace
= BitmapColor( (BYTE
) i
);
1475 aReplace
= rReplaceColor
;
1477 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1478 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1479 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskWhite
)
1480 pAcc
->SetPixel( nY
, nX
, aReplace
);
1485 ( (Bitmap
&) rMask
).ReleaseAccess( pMaskAcc
);
1486 ReleaseAccess( pAcc
);
1491 // ------------------------------------------------------------------
1493 BOOL
Bitmap::Replace( const AlphaMask
& rAlpha
, const Color
& rMergeColor
)
1495 Bitmap
aNewBmp( GetSizePixel(), 24 );
1496 BitmapReadAccess
* pAcc
= AcquireReadAccess();
1497 BitmapReadAccess
* pAlphaAcc
= ( (AlphaMask
&) rAlpha
).AcquireReadAccess();
1498 BitmapWriteAccess
* pNewAcc
= aNewBmp
.AcquireWriteAccess();
1501 if( pAcc
&& pAlphaAcc
&& pNewAcc
)
1504 const long nWidth
= Min( pAlphaAcc
->Width(), pAcc
->Width() );
1505 const long nHeight
= Min( pAlphaAcc
->Height(), pAcc
->Height() );
1507 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1509 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1511 aCol
= pAcc
->GetColor( nY
, nX
);
1512 pNewAcc
->SetPixel( nY
, nX
, aCol
.Merge( rMergeColor
, 255 - (BYTE
) pAlphaAcc
->GetPixel( nY
, nX
) ) );
1519 ReleaseAccess( pAcc
);
1520 ( (AlphaMask
&) rAlpha
).ReleaseAccess( pAlphaAcc
);
1521 aNewBmp
.ReleaseAccess( pNewAcc
);
1525 const MapMode
aMap( maPrefMapMode
);
1526 const Size
aSize( maPrefSize
);
1530 maPrefMapMode
= aMap
;
1537 // ------------------------------------------------------------------
1539 BOOL
Bitmap::Replace( const Color
& rSearchColor
, const Color
& rReplaceColor
, ULONG nTol
)
1541 // Bitmaps with 1 bit color depth can cause problems
1542 // if they have other entries than black/white in their palette
1543 if( 1 == GetBitCount() )
1544 Convert( BMP_CONVERSION_4BIT_COLORS
);
1546 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1551 const long nMinR
= MinMax( (long) rSearchColor
.GetRed() - nTol
, 0, 255 );
1552 const long nMaxR
= MinMax( (long) rSearchColor
.GetRed() + nTol
, 0, 255 );
1553 const long nMinG
= MinMax( (long) rSearchColor
.GetGreen() - nTol
, 0, 255 );
1554 const long nMaxG
= MinMax( (long) rSearchColor
.GetGreen() + nTol
, 0, 255 );
1555 const long nMinB
= MinMax( (long) rSearchColor
.GetBlue() - nTol
, 0, 255 );
1556 const long nMaxB
= MinMax( (long) rSearchColor
.GetBlue() + nTol
, 0, 255 );
1558 if( pAcc
->HasPalette() )
1560 for( USHORT i
= 0, nPalCount
= pAcc
->GetPaletteEntryCount(); i
< nPalCount
; i
++ )
1562 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( i
);
1564 if( nMinR
<= rCol
.GetRed() && nMaxR
>= rCol
.GetRed() &&
1565 nMinG
<= rCol
.GetGreen() && nMaxG
>= rCol
.GetGreen() &&
1566 nMinB
<= rCol
.GetBlue() && nMaxB
>= rCol
.GetBlue() )
1568 pAcc
->SetPaletteColor( i
, rReplaceColor
);
1575 const BitmapColor
aReplace( pAcc
->GetBestMatchingColor( rReplaceColor
) );
1577 for( long nY
= 0L, nHeight
= pAcc
->Height(); nY
< nHeight
; nY
++ )
1579 for( long nX
= 0L, nWidth
= pAcc
->Width(); nX
< nWidth
; nX
++ )
1581 aCol
= pAcc
->GetPixel( nY
, nX
);
1583 if( nMinR
<= aCol
.GetRed() && nMaxR
>= aCol
.GetRed() &&
1584 nMinG
<= aCol
.GetGreen() && nMaxG
>= aCol
.GetGreen() &&
1585 nMinB
<= aCol
.GetBlue() && nMaxB
>= aCol
.GetBlue() )
1587 pAcc
->SetPixel( nY
, nX
, aReplace
);
1593 ReleaseAccess( pAcc
);
1600 // ------------------------------------------------------------------
1602 BOOL
Bitmap::Replace( const Color
* pSearchColors
, const Color
* pReplaceColors
,
1603 ULONG nColorCount
, ULONG
* _pTols
)
1605 // Bitmaps with 1 bit color depth can cause problems
1606 // if they have other entries than black/white in their palette
1607 if( 1 == GetBitCount() )
1608 Convert( BMP_CONVERSION_4BIT_COLORS
);
1610 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1615 long* pMinR
= new long[ nColorCount
];
1616 long* pMaxR
= new long[ nColorCount
];
1617 long* pMinG
= new long[ nColorCount
];
1618 long* pMaxG
= new long[ nColorCount
];
1619 long* pMinB
= new long[ nColorCount
];
1620 long* pMaxB
= new long[ nColorCount
];
1626 pTols
= new long[ nColorCount
];
1627 memset( pTols
, 0, nColorCount
* sizeof( long ) );
1630 pTols
= (long*) _pTols
;
1632 for( i
= 0UL; i
< nColorCount
; i
++ )
1634 const Color
& rCol
= pSearchColors
[ i
];
1635 const long nTol
= pTols
[ i
];
1637 pMinR
[ i
] = MinMax( (long) rCol
.GetRed() - nTol
, 0, 255 );
1638 pMaxR
[ i
] = MinMax( (long) rCol
.GetRed() + nTol
, 0, 255 );
1639 pMinG
[ i
] = MinMax( (long) rCol
.GetGreen() - nTol
, 0, 255 );
1640 pMaxG
[ i
] = MinMax( (long) rCol
.GetGreen() + nTol
, 0, 255 );
1641 pMinB
[ i
] = MinMax( (long) rCol
.GetBlue() - nTol
, 0, 255 );
1642 pMaxB
[ i
] = MinMax( (long) rCol
.GetBlue() + nTol
, 0, 255 );
1645 if( pAcc
->HasPalette() )
1647 for( USHORT nEntry
= 0, nPalCount
= pAcc
->GetPaletteEntryCount(); nEntry
< nPalCount
; nEntry
++ )
1649 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( nEntry
);
1651 for( i
= 0UL; i
< nColorCount
; i
++ )
1653 if( pMinR
[ i
] <= rCol
.GetRed() && pMaxR
[ i
] >= rCol
.GetRed() &&
1654 pMinG
[ i
] <= rCol
.GetGreen() && pMaxG
[ i
] >= rCol
.GetGreen() &&
1655 pMinB
[ i
] <= rCol
.GetBlue() && pMaxB
[ i
] >= rCol
.GetBlue() )
1657 pAcc
->SetPaletteColor( (USHORT
)nEntry
, pReplaceColors
[ i
] );
1666 BitmapColor
* pReplaces
= new BitmapColor
[ nColorCount
];
1668 for( i
= 0UL; i
< nColorCount
; i
++ )
1669 pReplaces
[ i
] = pAcc
->GetBestMatchingColor( pReplaceColors
[ i
] );
1671 for( long nY
= 0L, nHeight
= pAcc
->Height(); nY
< nHeight
; nY
++ )
1673 for( long nX
= 0L, nWidth
= pAcc
->Width(); nX
< nWidth
; nX
++ )
1675 aCol
= pAcc
->GetPixel( nY
, nX
);
1677 for( i
= 0UL; i
< nColorCount
; i
++ )
1679 if( pMinR
[ i
] <= aCol
.GetRed() && pMaxR
[ i
] >= aCol
.GetRed() &&
1680 pMinG
[ i
] <= aCol
.GetGreen() && pMaxG
[ i
] >= aCol
.GetGreen() &&
1681 pMinB
[ i
] <= aCol
.GetBlue() && pMaxB
[ i
] >= aCol
.GetBlue() )
1683 pAcc
->SetPixel( nY
, nX
, pReplaces
[ i
] );
1702 ReleaseAccess( pAcc
);
1709 // ------------------------------------------------------------------
1711 Bitmap
Bitmap::CreateDisplayBitmap( OutputDevice
* pDisplay
)
1713 Bitmap
aDispBmp( *this );
1715 if( mpImpBmp
&& ( pDisplay
->mpGraphics
|| pDisplay
->ImplGetGraphics() ) )
1717 ImpBitmap
* pImpDispBmp
= new ImpBitmap
;
1719 if( pImpDispBmp
->ImplCreate( *mpImpBmp
, pDisplay
->mpGraphics
) )
1720 aDispBmp
.ImplSetImpBitmap( pImpDispBmp
);
1728 // ------------------------------------------------------------------
1730 Bitmap
Bitmap::GetColorTransformedBitmap( BmpColorMode eColorMode
) const
1734 if( BMP_COLOR_HIGHCONTRAST
== eColorMode
)
1736 Color
* pSrcColors
= NULL
;
1737 Color
* pDstColors
= NULL
;
1738 ULONG nColorCount
= 0;
1742 Image::GetColorTransformArrays( (ImageColorTransform
) eColorMode
, pSrcColors
, pDstColors
, nColorCount
);
1744 if( nColorCount
&& pSrcColors
&& pDstColors
)
1745 aRet
.Replace( pSrcColors
, pDstColors
, nColorCount
);
1747 delete[] pSrcColors
;
1748 delete[] pDstColors
;
1750 else if( BMP_COLOR_MONOCHROME_BLACK
== eColorMode
||
1751 BMP_COLOR_MONOCHROME_WHITE
== eColorMode
)
1754 aRet
.MakeMono( BMP_COLOR_MONOCHROME_THRESHOLD
);
1760 // ------------------------------------------------------------------
1762 BOOL
Bitmap::CombineSimple( const Bitmap
& rMask
, BmpCombine eCombine
)
1764 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
1765 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1768 if( pMaskAcc
&& pAcc
)
1770 const long nWidth
= Min( pMaskAcc
->Width(), pAcc
->Width() );
1771 const long nHeight
= Min( pMaskAcc
->Height(), pAcc
->Height() );
1772 const Color
aColBlack( COL_BLACK
);
1774 BitmapColor aMaskPixel
;
1775 const BitmapColor
aWhite( pAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
1776 const BitmapColor
aBlack( pAcc
->GetBestMatchingColor( aColBlack
) );
1777 const BitmapColor
aMaskBlack( pMaskAcc
->GetBestMatchingColor( aColBlack
) );
1781 case( BMP_COMBINE_COPY
):
1783 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1785 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskBlack
)
1786 pAcc
->SetPixel( nY
, nX
, aBlack
);
1788 pAcc
->SetPixel( nY
, nX
, aWhite
);
1793 case( BMP_COMBINE_INVERT
):
1795 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1797 if( pAcc
->GetPixel( nY
, nX
) == aBlack
)
1798 pAcc
->SetPixel( nY
, nX
, aWhite
);
1800 pAcc
->SetPixel( nY
, nX
, aBlack
);
1805 case( BMP_COMBINE_AND
):
1807 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1809 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
&& pAcc
->GetPixel( nY
, nX
) != aBlack
)
1810 pAcc
->SetPixel( nY
, nX
, aWhite
);
1812 pAcc
->SetPixel( nY
, nX
, aBlack
);
1817 case( BMP_COMBINE_NAND
):
1819 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1821 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
&& pAcc
->GetPixel( nY
, nX
) != aBlack
)
1822 pAcc
->SetPixel( nY
, nX
, aBlack
);
1824 pAcc
->SetPixel( nY
, nX
, aWhite
);
1829 case( BMP_COMBINE_OR
):
1831 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1833 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
|| pAcc
->GetPixel( nY
, nX
) != aBlack
)
1834 pAcc
->SetPixel( nY
, nX
, aWhite
);
1836 pAcc
->SetPixel( nY
, nX
, aBlack
);
1841 case( BMP_COMBINE_NOR
):
1843 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1845 if( pMaskAcc
->GetPixel( nY
, nX
) != aMaskBlack
|| pAcc
->GetPixel( nY
, nX
) != aBlack
)
1846 pAcc
->SetPixel( nY
, nX
, aBlack
);
1848 pAcc
->SetPixel( nY
, nX
, aWhite
);
1853 case( BMP_COMBINE_XOR
):
1855 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1857 aPixel
= pAcc
->GetPixel( nY
, nX
);
1858 aMaskPixel
= pMaskAcc
->GetPixel( nY
, nX
);
1860 if( ( aMaskPixel
!= aMaskBlack
&& aPixel
== aBlack
) ||
1861 ( aMaskPixel
== aMaskBlack
&& aPixel
!= aBlack
) )
1863 pAcc
->SetPixel( nY
, nX
, aWhite
);
1866 pAcc
->SetPixel( nY
, nX
, aBlack
);
1871 case( BMP_COMBINE_NXOR
):
1873 for( long nY
= 0L; nY
< nHeight
; nY
++ ) for( long nX
= 0L; nX
< nWidth
; nX
++ )
1875 aPixel
= pAcc
->GetPixel( nY
, nX
);
1876 aMaskPixel
= pMaskAcc
->GetPixel( nY
, nX
);
1878 if( ( aMaskPixel
!= aMaskBlack
&& aPixel
== aBlack
) ||
1879 ( aMaskPixel
== aMaskBlack
&& aPixel
!= aBlack
) )
1881 pAcc
->SetPixel( nY
, nX
, aBlack
);
1884 pAcc
->SetPixel( nY
, nX
, aWhite
);
1893 ( (Bitmap
&) rMask
).ReleaseAccess( pMaskAcc
);
1894 ReleaseAccess( pAcc
);
1899 // ------------------------------------------------------------------
1901 BOOL
Bitmap::Blend( const AlphaMask
& rAlpha
, const Color
& rBackgroundColor
)
1903 // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
1904 // optimizations. Might even consolidate the code here and there.
1906 // convert to a truecolor bitmap, if we're a paletted one. There's
1907 // room for tradeoff decision here, maybe later for an overload (or a flag)
1908 if( GetBitCount() <= 8 )
1909 Convert( BMP_CONVERSION_24BIT
);
1911 BitmapReadAccess
* pAlphaAcc
= const_cast<AlphaMask
&>(rAlpha
).AcquireReadAccess();
1912 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
1915 if( pAlphaAcc
&& pAcc
)
1917 const long nWidth
= Min( pAlphaAcc
->Width(), pAcc
->Width() );
1918 const long nHeight
= Min( pAlphaAcc
->Height(), pAcc
->Height() );
1920 for( long nY
= 0L; nY
< nHeight
; ++nY
)
1921 for( long nX
= 0L; nX
< nWidth
; ++nX
)
1922 pAcc
->SetPixel( nY
, nX
,
1923 pAcc
->GetPixel( nY
, nX
).Merge( rBackgroundColor
,
1924 255 - pAlphaAcc
->GetPixel( nY
, nX
) ) );
1929 const_cast<AlphaMask
&>(rAlpha
).ReleaseAccess( pAlphaAcc
);
1930 ReleaseAccess( pAcc
);
1935 // ------------------------------------------------------------------
1937 BOOL
Bitmap::MakeMono( BYTE cThreshold
)
1939 return ImplMakeMono( cThreshold
);
1942 // ------------------------------------------------------------------
1944 bool Bitmap::GetSystemData( BitmapSystemData
& rData
) const
1949 SalBitmap
* pSalBitmap
= mpImpBmp
->ImplGetSalBitmap();
1951 bRet
= pSalBitmap
->GetSystemData( rData
);