| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <rtl/crc.h> |
| #include <tools/stream.hxx> |
| #include <tools/poly.hxx> |
| #include <tools/rc.h> |
| |
| #include <vcl/salbtype.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <vcl/outdev.hxx> |
| #include <vcl/bitmap.hxx> |
| #include <vcl/bitmapex.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/image.hxx> |
| |
| #include <impbmp.hxx> |
| #include <salbmp.hxx> |
| |
| // ---------- |
| // - Bitmap - |
| // ---------- |
| |
| Bitmap::Bitmap() : |
| mpImpBmp( NULL ) |
| { |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap::Bitmap( const ResId& rResId ) : |
| mpImpBmp( NULL ) |
| { |
| const BitmapEx aBmpEx( rResId ); |
| |
| if( !aBmpEx.IsEmpty() ) |
| *this = aBmpEx.GetBitmap(); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap::Bitmap( const Bitmap& rBitmap ) : |
| maPrefMapMode ( rBitmap.maPrefMapMode ), |
| maPrefSize ( rBitmap.maPrefSize ) |
| { |
| mpImpBmp = rBitmap.mpImpBmp; |
| |
| if ( mpImpBmp ) |
| mpImpBmp->ImplIncRefCount(); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap::Bitmap( SalBitmap* pSalBitmap ) |
| { |
| mpImpBmp = new ImpBitmap(); |
| mpImpBmp->ImplSetSalBitmap( pSalBitmap ); |
| maPrefMapMode = MapMode( MAP_PIXEL ); |
| maPrefSize = mpImpBmp->ImplGetSize(); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap::Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal ) |
| { |
| if( rSizePixel.Width() && rSizePixel.Height() ) |
| { |
| BitmapPalette aPal; |
| BitmapPalette* pRealPal = NULL; |
| |
| if( nBitCount <= 8 ) |
| { |
| if( !pPal ) |
| { |
| if( 1 == nBitCount ) |
| { |
| aPal.SetEntryCount( 2 ); |
| aPal[ 0 ] = Color( COL_BLACK ); |
| aPal[ 1 ] = Color( COL_WHITE ); |
| } |
| else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) ) |
| { |
| aPal.SetEntryCount( 1 << nBitCount ); |
| aPal[ 0 ] = Color( COL_BLACK ); |
| aPal[ 1 ] = Color( COL_BLUE ); |
| aPal[ 2 ] = Color( COL_GREEN ); |
| aPal[ 3 ] = Color( COL_CYAN ); |
| aPal[ 4 ] = Color( COL_RED ); |
| aPal[ 5 ] = Color( COL_MAGENTA ); |
| aPal[ 6 ] = Color( COL_BROWN ); |
| aPal[ 7 ] = Color( COL_GRAY ); |
| aPal[ 8 ] = Color( COL_LIGHTGRAY ); |
| aPal[ 9 ] = Color( COL_LIGHTBLUE ); |
| aPal[ 10 ] = Color( COL_LIGHTGREEN ); |
| aPal[ 11 ] = Color( COL_LIGHTCYAN ); |
| aPal[ 12 ] = Color( COL_LIGHTRED ); |
| aPal[ 13 ] = Color( COL_LIGHTMAGENTA ); |
| aPal[ 14 ] = Color( COL_YELLOW ); |
| aPal[ 15 ] = Color( COL_WHITE ); |
| |
| // Dither-Palette erzeugen |
| if( 8 == nBitCount ) |
| { |
| sal_uInt16 nActCol = 16; |
| |
| for( sal_uInt16 nB = 0; nB < 256; nB += 51 ) |
| for( sal_uInt16 nG = 0; nG < 256; nG += 51 ) |
| for( sal_uInt16 nR = 0; nR < 256; nR += 51 ) |
| aPal[ nActCol++ ] = BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ); |
| |
| // Standard-Office-Farbe setzen |
| aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 ); |
| } |
| } |
| } |
| else |
| pRealPal = (BitmapPalette*) pPal; |
| } |
| |
| mpImpBmp = new ImpBitmap; |
| mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal ); |
| } |
| else |
| mpImpBmp = NULL; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap::~Bitmap() |
| { |
| ImplReleaseRef(); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| const BitmapPalette& Bitmap::GetGreyPalette( int nEntries ) |
| { |
| static BitmapPalette aGreyPalette2; |
| static BitmapPalette aGreyPalette4; |
| static BitmapPalette aGreyPalette16; |
| static BitmapPalette aGreyPalette256; |
| |
| // create greyscale palette with 2, 4, 16 or 256 entries |
| if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries ) |
| { |
| if( 2 == nEntries ) |
| { |
| if( !aGreyPalette2.GetEntryCount() ) |
| { |
| aGreyPalette2.SetEntryCount( 2 ); |
| aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 ); |
| aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 ); |
| } |
| |
| return aGreyPalette2; |
| } |
| else if( 4 == nEntries ) |
| { |
| if( !aGreyPalette4.GetEntryCount() ) |
| { |
| aGreyPalette4.SetEntryCount( 4 ); |
| aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 ); |
| aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 ); |
| aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 ); |
| aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 ); |
| } |
| |
| return aGreyPalette4; |
| } |
| else if( 16 == nEntries ) |
| { |
| if( !aGreyPalette16.GetEntryCount() ) |
| { |
| sal_uInt8 cGrey = 0, cGreyInc = 17; |
| |
| aGreyPalette16.SetEntryCount( 16 ); |
| |
| for( sal_uInt16 i = 0; i < 16; i++, cGrey = sal::static_int_cast<sal_uInt8>(cGrey + cGreyInc) ) |
| aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey ); |
| } |
| |
| return aGreyPalette16; |
| } |
| else |
| { |
| if( !aGreyPalette256.GetEntryCount() ) |
| { |
| aGreyPalette256.SetEntryCount( 256 ); |
| |
| for( sal_uInt16 i = 0; i < 256; i++ ) |
| aGreyPalette256[ i ] = BitmapColor( (sal_uInt8) i, (sal_uInt8) i, (sal_uInt8) i ); |
| } |
| |
| return aGreyPalette256; |
| } |
| } |
| else |
| { |
| DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" ); |
| return aGreyPalette2; |
| } |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| bool BitmapPalette::IsGreyPalette() const |
| { |
| // TODO: add an IsGreyPalette flag to BitmapPalette |
| // TODO: unless this causes problems binary compatibility |
| const int nEntryCount = GetEntryCount(); |
| if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping |
| return true; |
| // see above: only certain entry values will result in a valid call to GetGreyPalette |
| if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 ) |
| { |
| const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount ); |
| if( rGreyPalette == *this ) |
| return true; |
| } |
| // TODO: is it worth to compare the entries? |
| return false; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap& Bitmap::operator=( const Bitmap& rBitmap ) |
| { |
| maPrefSize = rBitmap.maPrefSize; |
| maPrefMapMode = rBitmap.maPrefMapMode; |
| |
| if ( rBitmap.mpImpBmp ) |
| rBitmap.mpImpBmp->ImplIncRefCount(); |
| |
| ImplReleaseRef(); |
| mpImpBmp = rBitmap.mpImpBmp; |
| |
| return *this; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::IsEqual( const Bitmap& rBmp ) const |
| { |
| return( IsSameInstance( rBmp ) || |
| ( rBmp.GetSizePixel() == GetSizePixel() && |
| rBmp.GetBitCount() == GetBitCount() && |
| rBmp.GetChecksum() == GetChecksum() ) ); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::SetEmpty() |
| { |
| maPrefMapMode = MapMode(); |
| maPrefSize = Size(); |
| |
| ImplReleaseRef(); |
| mpImpBmp = NULL; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Size Bitmap::GetSizePixel() const |
| { |
| return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() ); |
| } |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::SetSizePixel( const Size& rNewSize, sal_uInt32 nScaleFlag ) |
| { |
| if(GetSizePixel() != rNewSize) |
| { |
| Scale( rNewSize, nScaleFlag ); |
| } |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Size Bitmap::GetSourceSizePixel() const |
| { |
| return( mpImpBmp ? mpImpBmp->ImplGetSourceSize() : Size() ); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::SetSourceSizePixel( const Size& rSize) |
| { |
| if( mpImpBmp ) |
| mpImpBmp->ImplSetSourceSize( rSize); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_uInt16 Bitmap::GetBitCount() const |
| { |
| return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 ); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::HasGreyPalette() const |
| { |
| const sal_uInt16 nBitCount = GetBitCount(); |
| sal_Bool bRet = sal_False; |
| |
| if( 1 == nBitCount ) |
| { |
| BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess(); |
| |
| if( pRAcc ) |
| { |
| const BitmapColor& rCol0( pRAcc->GetPaletteColor( 0 ) ); |
| const BitmapColor& rCol1( pRAcc->GetPaletteColor( 1 ) ); |
| if( rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() && |
| rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue() ) |
| { |
| bRet = sal_True; |
| } |
| ( (Bitmap*) this )->ReleaseAccess( pRAcc ); |
| } |
| else |
| bRet = sal_True; |
| } |
| else if( 4 == nBitCount || 8 == nBitCount ) |
| { |
| BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess(); |
| |
| if( pRAcc ) |
| { |
| if( pRAcc->HasPalette() && ( (BitmapPalette&) pRAcc->GetPalette() == GetGreyPalette( 1 << nBitCount ) ) ) |
| bRet = sal_True; |
| |
| ( (Bitmap*) this )->ReleaseAccess( pRAcc ); |
| } |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_uLong Bitmap::GetChecksum() const |
| { |
| sal_uLong nRet = 0UL; |
| |
| if( mpImpBmp ) |
| { |
| nRet = mpImpBmp->ImplGetChecksum(); |
| |
| if( !nRet ) |
| { |
| BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess(); |
| |
| if( pRAcc && pRAcc->Width() && pRAcc->Height() ) |
| { |
| sal_uInt32 nCrc = 0; |
| SVBT32 aBT32; |
| |
| pRAcc->ImplZeroInitUnusedBits(); |
| |
| UInt32ToSVBT32( pRAcc->Width(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( pRAcc->Height(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( pRAcc->GetBitCount(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| if( pRAcc->HasPalette() ) |
| { |
| nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(), |
| pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) ); |
| } |
| |
| nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() ); |
| |
| mpImpBmp->ImplSetChecksum( nRet = nCrc ); |
| } |
| |
| if (pRAcc) ( (Bitmap*) this )->ReleaseAccess( pRAcc ); |
| } |
| } |
| |
| return nRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::ImplReleaseRef() |
| { |
| if( mpImpBmp ) |
| { |
| if( mpImpBmp->ImplGetRefCount() > 1UL ) |
| mpImpBmp->ImplDecRefCount(); |
| else |
| { |
| delete mpImpBmp; |
| mpImpBmp = NULL; |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::ImplMakeUnique() |
| { |
| if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL ) |
| { |
| ImpBitmap* pOldImpBmp = mpImpBmp; |
| |
| pOldImpBmp->ImplDecRefCount(); |
| |
| mpImpBmp = new ImpBitmap; |
| mpImpBmp->ImplCreate( *pOldImpBmp ); |
| } |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap ) |
| { |
| const Size aOldSizePix( GetSizePixel() ); |
| const Size aNewSizePix( rBitmap.GetSizePixel() ); |
| const MapMode aOldMapMode( maPrefMapMode ); |
| Size aNewPrefSize; |
| |
| if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() ) |
| { |
| aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() ); |
| aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() ); |
| } |
| else |
| aNewPrefSize = maPrefSize; |
| |
| *this = rBitmap; |
| |
| maPrefSize = aNewPrefSize; |
| maPrefMapMode = aOldMapMode; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| ImpBitmap* Bitmap::ImplGetImpBitmap() const |
| { |
| return mpImpBmp; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp ) |
| { |
| if( pImpBmp != mpImpBmp ) |
| { |
| ImplReleaseRef(); |
| mpImpBmp = pImpBmp; |
| } |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| BitmapReadAccess* Bitmap::AcquireReadAccess() |
| { |
| BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this ); |
| |
| if( !*pReadAccess ) |
| { |
| delete pReadAccess; |
| pReadAccess = NULL; |
| } |
| |
| return pReadAccess; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| BitmapWriteAccess* Bitmap::AcquireWriteAccess() |
| { |
| BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this ); |
| |
| if( !*pWriteAccess ) |
| { |
| delete pWriteAccess; |
| pWriteAccess = NULL; |
| } |
| |
| return pWriteAccess; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess ) |
| { |
| delete pBitmapAccess; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Erase( const Color& rFillColor ) |
| { |
| if( !(*this) ) |
| return sal_True; |
| |
| BitmapWriteAccess* pWriteAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pWriteAcc ) |
| { |
| const sal_uLong nFormat = pWriteAcc->GetScanlineFormat(); |
| sal_uInt8 cIndex = 0; |
| sal_Bool bFast = sal_False; |
| |
| switch( nFormat ) |
| { |
| case( BMP_FORMAT_1BIT_MSB_PAL ): |
| case( BMP_FORMAT_1BIT_LSB_PAL ): |
| { |
| cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor ); |
| cIndex = ( cIndex ? 255 : 0 ); |
| bFast = sal_True; |
| } |
| break; |
| |
| case( BMP_FORMAT_4BIT_MSN_PAL ): |
| case( BMP_FORMAT_4BIT_LSN_PAL ): |
| { |
| cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor ); |
| cIndex = cIndex | ( cIndex << 4 ); |
| bFast = sal_True; |
| } |
| break; |
| |
| case( BMP_FORMAT_8BIT_PAL ): |
| { |
| cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor ); |
| bFast = sal_True; |
| } |
| break; |
| |
| case( BMP_FORMAT_24BIT_TC_BGR ): |
| case( BMP_FORMAT_24BIT_TC_RGB ): |
| { |
| if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) && |
| ( rFillColor.GetRed() == rFillColor.GetBlue() ) ) |
| { |
| cIndex = rFillColor.GetRed(); |
| bFast = sal_True; |
| } |
| else |
| bFast = sal_False; |
| } |
| break; |
| |
| default: |
| bFast = sal_False; |
| break; |
| } |
| |
| if( bFast ) |
| { |
| const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height(); |
| memset( pWriteAcc->GetBuffer(), cIndex, nBufSize ); |
| } |
| else |
| { |
| Point aTmpPoint; |
| const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) ); |
| pWriteAcc->SetFillColor( rFillColor ); |
| pWriteAcc->FillRect( aRect ); |
| } |
| |
| ReleaseAccess( pWriteAcc ); |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Invert() |
| { |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pAcc ) |
| { |
| if( pAcc->HasPalette() ) |
| { |
| BitmapPalette aBmpPal( pAcc->GetPalette() ); |
| const sal_uInt16 nCount = aBmpPal.GetEntryCount(); |
| |
| for( sal_uInt16 i = 0; i < nCount; i++ ) |
| aBmpPal[ i ].Invert(); |
| |
| pAcc->SetPalette( aBmpPal ); |
| } |
| else |
| { |
| const long nWidth = pAcc->Width(); |
| const long nHeight = pAcc->Height(); |
| |
| for( long nX = 0L; nX < nWidth; nX++ ) |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() ); |
| } |
| |
| ReleaseAccess( pAcc ); |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Mirror( sal_uLong nMirrorFlags ) |
| { |
| sal_Bool bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ ); |
| sal_Bool bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT ); |
| sal_Bool bRet = sal_False; |
| |
| if( bHorz && !bVert ) |
| { |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| |
| if( pAcc ) |
| { |
| const long nWidth = pAcc->Width(); |
| const long nHeight = pAcc->Height(); |
| const long nWidth1 = nWidth - 1L; |
| const long nWidth_2 = nWidth >> 1L; |
| |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| { |
| for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- ) |
| { |
| const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) ); |
| |
| pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) ); |
| pAcc->SetPixel( nY, nOther, aTemp ); |
| } |
| } |
| |
| ReleaseAccess( pAcc ); |
| bRet = sal_True; |
| } |
| } |
| else if( bVert && !bHorz ) |
| { |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| |
| if( pAcc ) |
| { |
| const long nScanSize = pAcc->GetScanlineSize(); |
| sal_uInt8* pBuffer = new sal_uInt8[ nScanSize ]; |
| const long nHeight = pAcc->Height(); |
| const long nHeight1 = nHeight - 1L; |
| const long nHeight_2 = nHeight >> 1L; |
| |
| for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- ) |
| { |
| memcpy( pBuffer, pAcc->GetScanline( nY ), nScanSize ); |
| memcpy( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize ); |
| memcpy( pAcc->GetScanline( nOther ), pBuffer, nScanSize ); |
| } |
| |
| delete[] pBuffer; |
| ReleaseAccess( pAcc ); |
| bRet = sal_True; |
| } |
| } |
| else if( bHorz && bVert ) |
| { |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| |
| if( pAcc ) |
| { |
| const long nWidth = pAcc->Width(); |
| const long nWidth1 = nWidth - 1L; |
| const long nHeight = pAcc->Height(); |
| long nHeight_2 = nHeight >> 1; |
| |
| for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- ) |
| { |
| for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- ) |
| { |
| const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) ); |
| |
| pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) ); |
| pAcc->SetPixel( nOtherY, nOtherX, aTemp ); |
| } |
| } |
| |
| // ggf. noch mittlere Zeile horizontal spiegeln |
| if( nHeight & 1 ) |
| { |
| for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- ) |
| { |
| const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) ); |
| pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) ); |
| pAcc->SetPixel( nHeight_2, nOtherX, aTemp ); |
| } |
| } |
| |
| ReleaseAccess( pAcc ); |
| bRet = sal_True; |
| } |
| } |
| else |
| bRet = sal_True; |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Rotate( long nAngle10, const Color& rFillColor ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| nAngle10 %= 3600L; |
| nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10; |
| |
| if( !nAngle10 ) |
| bRet = sal_True; |
| else if( 1800L == nAngle10 ) |
| bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT ); |
| else |
| { |
| BitmapReadAccess* pReadAcc = AcquireReadAccess(); |
| Bitmap aRotatedBmp; |
| |
| if( pReadAcc ) |
| { |
| const Size aSizePix( GetSizePixel() ); |
| |
| if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) ) |
| { |
| const Size aNewSizePix( aSizePix.Height(), aSizePix.Width() ); |
| Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() ); |
| BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); |
| |
| if( pWriteAcc ) |
| { |
| const long nWidth = aSizePix.Width(); |
| const long nWidth1 = nWidth - 1L; |
| const long nHeight = aSizePix.Height(); |
| const long nHeight1 = nHeight - 1L; |
| const long nNewWidth = aNewSizePix.Width(); |
| const long nNewHeight = aNewSizePix.Height(); |
| |
| if( 900L == nAngle10 ) |
| { |
| for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- ) |
| for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ ) |
| pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) ); |
| } |
| else if( 2700L == nAngle10 ) |
| { |
| for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ ) |
| for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ ) |
| pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) ); |
| } |
| |
| aNewBmp.ReleaseAccess( pWriteAcc ); |
| } |
| |
| aRotatedBmp = aNewBmp; |
| } |
| else |
| { |
| Point aTmpPoint; |
| Rectangle aTmpRectangle( aTmpPoint, aSizePix ); |
| Polygon aPoly( aTmpRectangle ); |
| aPoly.Rotate( aTmpPoint, (sal_uInt16) nAngle10 ); |
| |
| Rectangle aNewBound( aPoly.GetBoundRect() ); |
| const Size aNewSizePix( aNewBound.GetSize() ); |
| Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() ); |
| BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); |
| |
| if( pWriteAcc ) |
| { |
| const BitmapColor aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) ); |
| const double fCosAngle = cos( nAngle10 * F_PI1800 ); |
| const double fSinAngle = sin( nAngle10 * F_PI1800 ); |
| const double fXMin = aNewBound.Left(); |
| const double fYMin = aNewBound.Top(); |
| const long nWidth = aSizePix.Width(); |
| const long nHeight = aSizePix.Height(); |
| const long nNewWidth = aNewSizePix.Width(); |
| const long nNewHeight = aNewSizePix.Height(); |
| long nX; |
| long nY; |
| long nRotX; |
| long nRotY; |
| long nSinY; |
| long nCosY; |
| long* pCosX = new long[ nNewWidth ]; |
| long* pSinX = new long[ nNewWidth ]; |
| long* pCosY = new long[ nNewHeight ]; |
| long* pSinY = new long[ nNewHeight ]; |
| |
| for ( nX = 0; nX < nNewWidth; nX++ ) |
| { |
| const double fTmp = ( fXMin + nX ) * 64.; |
| |
| pCosX[ nX ] = FRound( fCosAngle * fTmp ); |
| pSinX[ nX ] = FRound( fSinAngle * fTmp ); |
| } |
| |
| for ( nY = 0; nY < nNewHeight; nY++ ) |
| { |
| const double fTmp = ( fYMin + nY ) * 64.; |
| |
| pCosY[ nY ] = FRound( fCosAngle * fTmp ); |
| pSinY[ nY ] = FRound( fSinAngle * fTmp ); |
| } |
| |
| for( nY = 0L; nY < nNewHeight; nY++ ) |
| { |
| nSinY = pSinY[ nY ]; |
| nCosY = pCosY[ nY ]; |
| |
| for( nX = 0L; nX < nNewWidth; nX++ ) |
| { |
| nRotX = ( pCosX[ nX ] - nSinY ) >> 6; |
| nRotY = ( pSinX[ nX ] + nCosY ) >> 6; |
| |
| if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) ) |
| pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) ); |
| else |
| pWriteAcc->SetPixel( nY, nX, aFillColor ); |
| } |
| } |
| |
| delete[] pSinX; |
| delete[] pCosX; |
| delete[] pSinY; |
| delete[] pCosY; |
| |
| aNewBmp.ReleaseAccess( pWriteAcc ); |
| } |
| |
| aRotatedBmp = aNewBmp; |
| } |
| |
| ReleaseAccess( pReadAcc ); |
| } |
| |
| if( ( bRet = !!aRotatedBmp ) == sal_True ) |
| ImplAssignWithSize( aRotatedBmp ); |
| } |
| |
| return bRet; |
| }; |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Crop( const Rectangle& rRectPixel ) |
| { |
| const Size aSizePix( GetSizePixel() ); |
| Rectangle aRect( rRectPixel ); |
| sal_Bool bRet = sal_False; |
| |
| aRect.Intersection( Rectangle( Point(), aSizePix ) ); |
| |
| if( !aRect.IsEmpty() ) |
| { |
| BitmapReadAccess* pReadAcc = AcquireReadAccess(); |
| |
| if( pReadAcc ) |
| { |
| Point aTmpPoint; |
| const Rectangle aNewRect( aTmpPoint, aRect.GetSize() ); |
| Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() ); |
| BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); |
| |
| if( pWriteAcc ) |
| { |
| const long nOldX = aRect.Left(); |
| const long nOldY = aRect.Top(); |
| const long nNewWidth = aNewRect.GetWidth(); |
| const long nNewHeight = aNewRect.GetHeight(); |
| |
| for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ ) |
| for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ ) |
| pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) ); |
| |
| aNewBmp.ReleaseAccess( pWriteAcc ); |
| bRet = sal_True; |
| } |
| |
| ReleaseAccess( pReadAcc ); |
| |
| if( bRet ) |
| ImplAssignWithSize( aNewBmp ); |
| } |
| } |
| |
| return bRet; |
| }; |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::CopyPixel( const Rectangle& rRectDst, |
| const Rectangle& rRectSrc, const Bitmap* pBmpSrc ) |
| { |
| const Size aSizePix( GetSizePixel() ); |
| Rectangle aRectDst( rRectDst ); |
| sal_Bool bRet = sal_False; |
| |
| aRectDst.Intersection( Rectangle( Point(), aSizePix ) ); |
| |
| if( !aRectDst.IsEmpty() ) |
| { |
| if( pBmpSrc && ( *pBmpSrc != *this ) ) |
| { |
| Bitmap* pSrc = (Bitmap*) pBmpSrc; |
| const Size aCopySizePix( pSrc->GetSizePixel() ); |
| Rectangle aRectSrc( rRectSrc ); |
| const sal_uInt16 nSrcBitCount = pBmpSrc->GetBitCount(); |
| const sal_uInt16 nDstBitCount = GetBitCount(); |
| |
| if( nSrcBitCount > nDstBitCount ) |
| { |
| long nNextIndex = 0L; |
| |
| if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) ) |
| Convert( BMP_CONVERSION_24BIT ); |
| else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) ) |
| { |
| Convert( BMP_CONVERSION_8BIT_COLORS ); |
| nNextIndex = 16; |
| } |
| else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) ) |
| { |
| Convert( BMP_CONVERSION_4BIT_COLORS ); |
| nNextIndex = 2; |
| } |
| |
| if( nNextIndex ) |
| { |
| BitmapReadAccess* pSrcAcc = pSrc->AcquireReadAccess(); |
| BitmapWriteAccess* pDstAcc = AcquireWriteAccess(); |
| |
| if( pSrcAcc && pDstAcc ) |
| { |
| const long nSrcCount = pDstAcc->GetPaletteEntryCount(); |
| const long nDstCount = 1 << nDstBitCount; |
| sal_Bool bFound; |
| |
| for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ ) |
| { |
| const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (sal_uInt16) i ); |
| |
| bFound = sal_False; |
| |
| for( long j = 0L; j < nDstCount; j++ ) |
| { |
| if( rSrcCol == pDstAcc->GetPaletteColor( (sal_uInt16) j ) ) |
| { |
| bFound = sal_True; |
| break; |
| } |
| } |
| |
| if( !bFound ) |
| pDstAcc->SetPaletteColor( (sal_uInt16) nNextIndex++, rSrcCol ); |
| } |
| } |
| |
| if( pSrcAcc ) |
| pSrc->ReleaseAccess( pSrcAcc ); |
| |
| if( pDstAcc ) |
| ReleaseAccess( pDstAcc ); |
| } |
| } |
| |
| aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) ); |
| |
| if( !aRectSrc.IsEmpty() ) |
| { |
| BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess(); |
| |
| if( pReadAcc ) |
| { |
| BitmapWriteAccess* pWriteAcc = AcquireWriteAccess(); |
| |
| if( pWriteAcc ) |
| { |
| const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() ); |
| const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() ); |
| const long nSrcEndX = aRectSrc.Left() + nWidth; |
| const long nSrcEndY = aRectSrc.Top() + nHeight; |
| long nDstY = aRectDst.Top(); |
| |
| if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() ) |
| { |
| const sal_uInt16 nCount = pReadAcc->GetPaletteEntryCount(); |
| sal_uInt8* pMap = new sal_uInt8[ nCount ]; |
| |
| // Index-Map fuer Farbtabelle |
| // aufbauen, da das Bild ja (relativ) farbgenau |
| // kopiert werden soll |
| for( sal_uInt16 i = 0; i < nCount; i++ ) |
| pMap[ i ] = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) ); |
| |
| for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ ) |
| for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ ) |
| pWriteAcc->SetPixelIndex( nDstY, nDstX, pMap[ pReadAcc->GetPixelIndex( nSrcY, nSrcX ) ] ); |
| |
| delete[] pMap; |
| } |
| else if( pReadAcc->HasPalette() ) |
| { |
| for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ ) |
| for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ ) |
| pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nSrcY, nSrcX ) ) ); |
| } |
| else |
| for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ ) |
| for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ ) |
| pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) ); |
| |
| ReleaseAccess( pWriteAcc ); |
| bRet = ( nWidth > 0L ) && ( nHeight > 0L ); |
| } |
| |
| pSrc->ReleaseAccess( pReadAcc ); |
| } |
| } |
| } |
| else |
| { |
| Rectangle aRectSrc( rRectSrc ); |
| |
| aRectSrc.Intersection( Rectangle( Point(), aSizePix ) ); |
| |
| if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) ) |
| { |
| BitmapWriteAccess* pWriteAcc = AcquireWriteAccess(); |
| |
| if( pWriteAcc ) |
| { |
| const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() ); |
| const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() ); |
| const long nSrcX = aRectSrc.Left(); |
| const long nSrcY = aRectSrc.Top(); |
| const long nSrcEndX1 = nSrcX + nWidth - 1L; |
| const long nSrcEndY1 = nSrcY + nHeight - 1L; |
| const long nDstX = aRectDst.Left(); |
| const long nDstY = aRectDst.Top(); |
| const long nDstEndX1 = nDstX + nWidth - 1L; |
| const long nDstEndY1 = nDstY + nHeight - 1L; |
| |
| if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) ) |
| { |
| for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ ) |
| for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ ) |
| pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); |
| } |
| else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) ) |
| { |
| for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- ) |
| for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ ) |
| pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); |
| } |
| else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) ) |
| { |
| for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ ) |
| for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- ) |
| pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); |
| } |
| else |
| { |
| for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- ) |
| for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- ) |
| pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); |
| } |
| |
| ReleaseAccess( pWriteAcc ); |
| bRet = sal_True; |
| } |
| } |
| } |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| if( nDX || nDY ) |
| { |
| const Size aSizePixel( GetSizePixel() ); |
| const long nWidth = aSizePixel.Width(); |
| const long nHeight = aSizePixel.Height(); |
| const Size aNewSize( nWidth + nDX, nHeight + nDY ); |
| BitmapReadAccess* pReadAcc = AcquireReadAccess(); |
| |
| if( pReadAcc ) |
| { |
| BitmapPalette aBmpPal( pReadAcc->GetPalette() ); |
| Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal ); |
| BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); |
| |
| if( pWriteAcc ) |
| { |
| BitmapColor aColor; |
| const long nNewX = nWidth; |
| const long nNewY = nHeight; |
| const long nNewWidth = pWriteAcc->Width(); |
| const long nNewHeight = pWriteAcc->Height(); |
| long nX; |
| long nY; |
| |
| if( pInitColor ) |
| aColor = pWriteAcc->GetBestMatchingColor( *pInitColor ); |
| |
| for( nY = 0L; nY < nHeight; nY++ ) |
| { |
| pWriteAcc->CopyScanline( nY, *pReadAcc ); |
| |
| if( pInitColor && nDX ) |
| for( nX = nNewX; nX < nNewWidth; nX++ ) |
| pWriteAcc->SetPixel( nY, nX, aColor ); |
| } |
| |
| if( pInitColor && nDY ) |
| for( nY = nNewY; nY < nNewHeight; nY++ ) |
| for( nX = 0; nX < nNewWidth; nX++ ) |
| pWriteAcc->SetPixel( nY, nX, aColor ); |
| |
| aNewBmp.ReleaseAccess( pWriteAcc ); |
| bRet = sal_True; |
| } |
| |
| ReleaseAccess( pReadAcc ); |
| |
| if( bRet ) |
| ImplAssignWithSize( aNewBmp ); |
| } |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap Bitmap::CreateMask( const Color& rTransColor, sal_uLong nTol ) const |
| { |
| Bitmap aNewBmp( GetSizePixel(), 1 ); |
| BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pWriteAcc ) |
| { |
| BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess(); |
| |
| if( pReadAcc ) |
| { |
| const long nWidth = pReadAcc->Width(); |
| const long nHeight = pReadAcc->Height(); |
| const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); |
| const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); |
| |
| if( !nTol ) |
| { |
| const BitmapColor aTest( pReadAcc->GetBestMatchingColor( rTransColor ) ); |
| long nX, nY, nShift; |
| |
| if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL || |
| pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL ) |
| { |
| // optimized for 4Bit-MSN/LSN source palette |
| const sal_uInt8 cTest = aTest.GetIndex(); |
| const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 ); |
| |
| if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && |
| aWhite.GetIndex() == 1 ) |
| { |
| // optimized for 1Bit-MSB destination palette |
| for( nY = 0L; nY < nHeight; nY++ ) |
| { |
| Scanline pSrc = pReadAcc->GetScanline( nY ); |
| Scanline pDst = pWriteAcc->GetScanline( nY ); |
| for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 ) |
| { |
| if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) ) |
| pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) ); |
| else |
| pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) ); |
| } |
| } |
| } |
| else |
| { |
| for( nY = 0L; nY < nHeight; nY++ ) |
| { |
| Scanline pSrc = pReadAcc->GetScanline( nY ); |
| for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 ) |
| { |
| if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) ) |
| pWriteAcc->SetPixel( nY, nX, aWhite ); |
| else |
| pWriteAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| } |
| } |
| else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) |
| { |
| // optimized for 8Bit source palette |
| const sal_uInt8 cTest = aTest.GetIndex(); |
| |
| if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && |
| aWhite.GetIndex() == 1 ) |
| { |
| // optimized for 1Bit-MSB destination palette |
| for( nY = 0L; nY < nHeight; nY++ ) |
| { |
| Scanline pSrc = pReadAcc->GetScanline( nY ); |
| Scanline pDst = pWriteAcc->GetScanline( nY ); |
| for( nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( cTest == pSrc[ nX ] ) |
| pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) ); |
| else |
| pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) ); |
| } |
| } |
| } |
| else |
| { |
| for( nY = 0L; nY < nHeight; nY++ ) |
| { |
| Scanline pSrc = pReadAcc->GetScanline( nY ); |
| for( nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( cTest == pSrc[ nX ] ) |
| pWriteAcc->SetPixel( nY, nX, aWhite ); |
| else |
| pWriteAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| } |
| } |
| else |
| { |
| // not optimized |
| for( nY = 0L; nY < nHeight; nY++ ) |
| { |
| for( nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( aTest == pReadAcc->GetPixel( nY, nX ) ) |
| pWriteAcc->SetPixel( nY, nX, aWhite ); |
| else |
| pWriteAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| } |
| } |
| else |
| { |
| BitmapColor aCol; |
| long nR, nG, nB; |
| const long nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 ); |
| const long nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 ); |
| const long nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 ); |
| const long nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 ); |
| const long nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 ); |
| const long nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 ); |
| |
| if( pReadAcc->HasPalette() ) |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| { |
| for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ); |
| nR = aCol.GetRed(); |
| nG = aCol.GetGreen(); |
| nB = aCol.GetBlue(); |
| |
| if( nMinR <= nR && nMaxR >= nR && |
| nMinG <= nG && nMaxG >= nG && |
| nMinB <= nB && nMaxB >= nB ) |
| { |
| pWriteAcc->SetPixel( nY, nX, aWhite ); |
| } |
| else |
| pWriteAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| } |
| else |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| { |
| for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| aCol = pReadAcc->GetPixel( nY, nX ); |
| nR = aCol.GetRed(); |
| nG = aCol.GetGreen(); |
| nB = aCol.GetBlue(); |
| |
| if( nMinR <= nR && nMaxR >= nR && |
| nMinG <= nG && nMaxG >= nG && |
| nMinB <= nB && nMaxB >= nB ) |
| { |
| pWriteAcc->SetPixel( nY, nX, aWhite ); |
| } |
| else |
| pWriteAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| } |
| } |
| |
| ( (Bitmap*) this )->ReleaseAccess( pReadAcc ); |
| bRet = sal_True; |
| } |
| |
| aNewBmp.ReleaseAccess( pWriteAcc ); |
| } |
| |
| if( bRet ) |
| { |
| aNewBmp.maPrefSize = maPrefSize; |
| aNewBmp.maPrefMapMode = maPrefMapMode; |
| } |
| else |
| aNewBmp = Bitmap(); |
| |
| return aNewBmp; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const |
| { |
| Region aRegion; |
| Rectangle aRect( rRect ); |
| BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess(); |
| |
| aRect.Intersection( Rectangle( Point(), GetSizePixel() ) ); |
| aRect.Justify(); |
| |
| if( pReadAcc ) |
| { |
| //Rectangle aSubRect; |
| const long nLeft = aRect.Left(); |
| const long nTop = aRect.Top(); |
| const long nRight = aRect.Right(); |
| const long nBottom = aRect.Bottom(); |
| const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) ); |
| |
| //RectangleVector aRectangles; |
| //aRegion.ImplBeginAddRect(); |
| std::vector< long > aLine; |
| long nYStart(nTop); |
| long nY(nTop); |
| |
| for( ; nY <= nBottom; nY++ ) |
| { |
| //aSubRect.Top() = aSubRect.Bottom() = nY; |
| std::vector< long > aNewLine; |
| long nX(nLeft); |
| |
| for( ; nX <= nRight; ) |
| { |
| while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) ) |
| nX++; |
| |
| if( nX <= nRight ) |
| { |
| aNewLine.push_back(nX); |
| //aSubRect.Left() = nX; |
| |
| while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) ) |
| nX++; |
| |
| //aSubRect.Right() = nX - 1L; |
| aNewLine.push_back(nX - 1); |
| |
| //aRegion.ImplAddRect( aSubRect ); |
| //aRectangles.push_back(aSubRect); |
| //aRegion.Union(aSubRect); |
| } |
| } |
| |
| if(aNewLine != aLine) |
| { |
| // need to write aLine, it's different from the next line |
| if(aLine.size()) |
| { |
| Rectangle aSubRect; |
| |
| // enter y values and proceed ystart |
| aSubRect.Top() = nYStart; |
| aSubRect.Bottom() = nY ? nY - 1 : 0; |
| |
| for(sal_uInt32 a(0); a < aLine.size();) |
| { |
| aSubRect.Left() = aLine[a++]; |
| aSubRect.Right() = aLine[a++]; |
| aRegion.Union(aSubRect); |
| } |
| } |
| |
| // copy line as new line |
| aLine = aNewLine; |
| nYStart = nY; |
| } |
| } |
| |
| // write last line if used |
| if(aLine.size()) |
| { |
| Rectangle aSubRect; |
| |
| // enter y values |
| aSubRect.Top() = nYStart; |
| aSubRect.Bottom() = nY ? nY - 1 : 0; |
| |
| for(sal_uInt32 a(0); a < aLine.size();) |
| { |
| aSubRect.Left() = aLine[a++]; |
| aSubRect.Right() = aLine[a++]; |
| aRegion.Union(aSubRect); |
| } |
| } |
| |
| //aRegion.ImplEndAddRect(); |
| //aRegion.SetRegionRectangles(aRectangles); |
| |
| ( (Bitmap*) this )->ReleaseAccess( pReadAcc ); |
| } |
| else |
| aRegion = aRect; |
| |
| return aRegion; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor ) |
| { |
| BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess(); |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pMaskAcc && pAcc ) |
| { |
| const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() ); |
| const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() ); |
| const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); |
| BitmapColor aReplace; |
| |
| if( pAcc->HasPalette() ) |
| { |
| const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount(); |
| const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount(); |
| |
| // default to the nearest color |
| aReplace = pAcc->GetBestMatchingColor( rReplaceColor ); |
| |
| // for paletted images without a matching palette entry |
| // look for an unused palette entry (NOTE: expensive!) |
| if( pAcc->GetPaletteColor( aReplace.GetIndex() ) != BitmapColor( rReplaceColor ) ) |
| { |
| // if the palette has empty entries use the last one |
| if( nActColors < nMaxColors ) |
| { |
| pAcc->SetPaletteEntryCount( nActColors + 1 ); |
| pAcc->SetPaletteColor( nActColors, rReplaceColor ); |
| aReplace = BitmapColor( (sal_uInt8) nActColors ); |
| } |
| else |
| { |
| sal_Bool* pFlags = new sal_Bool[ nMaxColors ]; |
| |
| // alle Eintraege auf 0 setzen |
| memset( pFlags, 0, nMaxColors ); |
| |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| for( long nX = 0L; nX < nWidth; nX++ ) |
| pFlags[ pAcc->GetPixelIndex( nY, nX ) ] = sal_True; |
| |
| for( sal_uInt16 i = 0UL; i < nMaxColors; i++ ) |
| { |
| // Hurra, wir haben einen unbenutzten Eintrag |
| if( !pFlags[ i ] ) |
| { |
| pAcc->SetPaletteColor( (sal_uInt16) i, rReplaceColor ); |
| aReplace = BitmapColor( (sal_uInt8) i ); |
| } |
| } |
| |
| delete[] pFlags; |
| } |
| } |
| } |
| else |
| aReplace = rReplaceColor; |
| |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| for( long nX = 0L; nX < nWidth; nX++ ) |
| if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite ) |
| pAcc->SetPixel( nY, nX, aReplace ); |
| |
| bRet = sal_True; |
| } |
| |
| ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc ); |
| ReleaseAccess( pAcc ); |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor ) |
| { |
| Bitmap aNewBmp( GetSizePixel(), 24 ); |
| BitmapReadAccess* pAcc = AcquireReadAccess(); |
| BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); |
| BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pAcc && pAlphaAcc && pNewAcc ) |
| { |
| BitmapColor aCol; |
| const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() ); |
| const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() ); |
| |
| for( long nY = 0L; nY < nHeight; nY++ ) |
| { |
| for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| aCol = pAcc->GetColor( nY, nX ); |
| pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - pAlphaAcc->GetPixelIndex( nY, nX ) ) ); |
| } |
| } |
| |
| bRet = sal_True; |
| } |
| |
| ReleaseAccess( pAcc ); |
| ( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc ); |
| aNewBmp.ReleaseAccess( pNewAcc ); |
| |
| if( bRet ) |
| { |
| const MapMode aMap( maPrefMapMode ); |
| const Size aSize( maPrefSize ); |
| |
| *this = aNewBmp; |
| |
| maPrefMapMode = aMap; |
| maPrefSize = aSize; |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) |
| { |
| // Bitmaps with 1 bit color depth can cause problems |
| // if they have other entries than black/white in their palette |
| if( 1 == GetBitCount() ) |
| Convert( BMP_CONVERSION_4BIT_COLORS ); |
| |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pAcc ) |
| { |
| const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 ); |
| const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 ); |
| const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 ); |
| const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 ); |
| const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 ); |
| const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 ); |
| |
| if( pAcc->HasPalette() ) |
| { |
| for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ ) |
| { |
| const BitmapColor& rCol = pAcc->GetPaletteColor( i ); |
| |
| if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() && |
| nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() && |
| nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() ) |
| { |
| pAcc->SetPaletteColor( i, rReplaceColor ); |
| } |
| } |
| } |
| else |
| { |
| BitmapColor aCol; |
| const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) ); |
| |
| for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ ) |
| { |
| for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ ) |
| { |
| aCol = pAcc->GetPixel( nY, nX ); |
| |
| if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() && |
| nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() && |
| nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() ) |
| { |
| pAcc->SetPixel( nY, nX, aReplace ); |
| } |
| } |
| } |
| } |
| |
| ReleaseAccess( pAcc ); |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors, |
| sal_uLong nColorCount, sal_uLong* _pTols ) |
| { |
| // Bitmaps with 1 bit color depth can cause problems |
| // if they have other entries than black/white in their palette |
| if( 1 == GetBitCount() ) |
| Convert( BMP_CONVERSION_4BIT_COLORS ); |
| |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pAcc ) |
| { |
| long* pMinR = new long[ nColorCount ]; |
| long* pMaxR = new long[ nColorCount ]; |
| long* pMinG = new long[ nColorCount ]; |
| long* pMaxG = new long[ nColorCount ]; |
| long* pMinB = new long[ nColorCount ]; |
| long* pMaxB = new long[ nColorCount ]; |
| long* pTols; |
| sal_uLong i; |
| |
| if( !_pTols ) |
| { |
| pTols = new long[ nColorCount ]; |
| memset( pTols, 0, nColorCount * sizeof( long ) ); |
| } |
| else |
| pTols = (long*) _pTols; |
| |
| for( i = 0UL; i < nColorCount; i++ ) |
| { |
| const Color& rCol = pSearchColors[ i ]; |
| const long nTol = pTols[ i ]; |
| |
| pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 ); |
| pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 ); |
| pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 ); |
| pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 ); |
| pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 ); |
| pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 ); |
| } |
| |
| if( pAcc->HasPalette() ) |
| { |
| for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ ) |
| { |
| const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry ); |
| |
| for( i = 0UL; i < nColorCount; i++ ) |
| { |
| if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() && |
| pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() && |
| pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() ) |
| { |
| pAcc->SetPaletteColor( (sal_uInt16)nEntry, pReplaceColors[ i ] ); |
| break; |
| } |
| } |
| } |
| } |
| else |
| { |
| BitmapColor aCol; |
| BitmapColor* pReplaces = new BitmapColor[ nColorCount ]; |
| |
| for( i = 0UL; i < nColorCount; i++ ) |
| pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] ); |
| |
| for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ ) |
| { |
| for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ ) |
| { |
| aCol = pAcc->GetPixel( nY, nX ); |
| |
| for( i = 0UL; i < nColorCount; i++ ) |
| { |
| if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() && |
| pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() && |
| pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() ) |
| { |
| pAcc->SetPixel( nY, nX, pReplaces[ i ] ); |
| break; |
| } |
| } |
| } |
| } |
| |
| delete[] pReplaces; |
| } |
| |
| if( !_pTols ) |
| delete[] pTols; |
| |
| delete[] pMinR; |
| delete[] pMaxR; |
| delete[] pMinG; |
| delete[] pMaxG; |
| delete[] pMinB; |
| delete[] pMaxB; |
| ReleaseAccess( pAcc ); |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay ) |
| { |
| Bitmap aDispBmp( *this ); |
| |
| if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) ) |
| { |
| ImpBitmap* pImpDispBmp = new ImpBitmap; |
| |
| if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) ) |
| aDispBmp.ImplSetImpBitmap( pImpDispBmp ); |
| else |
| delete pImpDispBmp; |
| } |
| |
| return aDispBmp; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| Bitmap Bitmap::GetColorTransformedBitmap( BmpColorMode eColorMode ) const |
| { |
| Bitmap aRet; |
| |
| if( BMP_COLOR_HIGHCONTRAST == eColorMode ) |
| { |
| Color* pSrcColors = NULL; |
| Color* pDstColors = NULL; |
| sal_uLong nColorCount = 0; |
| |
| aRet = *this; |
| |
| Image::GetColorTransformArrays( (ImageColorTransform) eColorMode, pSrcColors, pDstColors, nColorCount ); |
| |
| if( nColorCount && pSrcColors && pDstColors ) |
| aRet.Replace( pSrcColors, pDstColors, nColorCount ); |
| |
| delete[] pSrcColors; |
| delete[] pDstColors; |
| } |
| else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode || |
| BMP_COLOR_MONOCHROME_WHITE == eColorMode ) |
| { |
| aRet = *this; |
| aRet.MakeMono( BMP_COLOR_MONOCHROME_THRESHOLD ); |
| } |
| |
| return aRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine ) |
| { |
| BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess(); |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pMaskAcc && pAcc ) |
| { |
| const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() ); |
| const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() ); |
| const Color aColBlack( COL_BLACK ); |
| BitmapColor aPixel; |
| BitmapColor aMaskPixel; |
| const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); |
| const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) ); |
| const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) ); |
| |
| switch( eCombine ) |
| { |
| case( BMP_COMBINE_COPY ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack ) |
| pAcc->SetPixel( nY, nX, aBlack ); |
| else |
| pAcc->SetPixel( nY, nX, aWhite ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_INVERT ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( pAcc->GetPixel( nY, nX ) == aBlack ) |
| pAcc->SetPixel( nY, nX, aWhite ); |
| else |
| pAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_AND ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack ) |
| pAcc->SetPixel( nY, nX, aWhite ); |
| else |
| pAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_NAND ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack ) |
| pAcc->SetPixel( nY, nX, aBlack ); |
| else |
| pAcc->SetPixel( nY, nX, aWhite ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_OR ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack ) |
| pAcc->SetPixel( nY, nX, aWhite ); |
| else |
| pAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_NOR ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack ) |
| pAcc->SetPixel( nY, nX, aBlack ); |
| else |
| pAcc->SetPixel( nY, nX, aWhite ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_XOR ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| aPixel = pAcc->GetPixel( nY, nX ); |
| aMaskPixel = pMaskAcc->GetPixel( nY, nX ); |
| |
| if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) || |
| ( aMaskPixel == aMaskBlack && aPixel != aBlack ) ) |
| { |
| pAcc->SetPixel( nY, nX, aWhite ); |
| } |
| else |
| pAcc->SetPixel( nY, nX, aBlack ); |
| } |
| } |
| break; |
| |
| case( BMP_COMBINE_NXOR ): |
| { |
| for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ ) |
| { |
| aPixel = pAcc->GetPixel( nY, nX ); |
| aMaskPixel = pMaskAcc->GetPixel( nY, nX ); |
| |
| if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) || |
| ( aMaskPixel == aMaskBlack && aPixel != aBlack ) ) |
| { |
| pAcc->SetPixel( nY, nX, aBlack ); |
| } |
| else |
| pAcc->SetPixel( nY, nX, aWhite ); |
| } |
| } |
| break; |
| } |
| |
| bRet = sal_True; |
| } |
| |
| ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc ); |
| ReleaseAccess( pAcc ); |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor ) |
| { |
| // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some |
| // optimizations. Might even consolidate the code here and there. |
| |
| // convert to a truecolor bitmap, if we're a paletted one. There's |
| // room for tradeoff decision here, maybe later for an overload (or a flag) |
| if( GetBitCount() <= 8 ) |
| Convert( BMP_CONVERSION_24BIT ); |
| |
| BitmapReadAccess* pAlphaAcc = const_cast<AlphaMask&>(rAlpha).AcquireReadAccess(); |
| BitmapWriteAccess* pAcc = AcquireWriteAccess(); |
| sal_Bool bRet = sal_False; |
| |
| if( pAlphaAcc && pAcc ) |
| { |
| const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() ); |
| const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() ); |
| |
| for( long nY = 0L; nY < nHeight; ++nY ) |
| for( long nX = 0L; nX < nWidth; ++nX ) |
| pAcc->SetPixel( nY, nX, |
| pAcc->GetPixel( nY, nX ).Merge( rBackgroundColor, |
| 255 - pAlphaAcc->GetPixelIndex( nY, nX ) ) ); |
| |
| bRet = sal_True; |
| } |
| |
| const_cast<AlphaMask&>(rAlpha).ReleaseAccess( pAlphaAcc ); |
| ReleaseAccess( pAcc ); |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold ) |
| { |
| return ImplMakeMono( cThreshold ); |
| } |
| |
| // ------------------------------------------------------------------ |
| |
| bool Bitmap::GetSystemData( BitmapSystemData& rData ) const |
| { |
| bool bRet = false; |
| if( mpImpBmp ) |
| { |
| SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap(); |
| if( pSalBitmap ) |
| bRet = pSalBitmap->GetSystemData( rData ); |
| } |
| |
| return bRet; |
| } |