vcl/source/bitmap/bitmap.cxx | 257 ++++++++++++------------- vcl/source/bitmap/bitmappaint.cxx | 387 ++++++++++++++++++-------------------- vcl/source/outdev/bitmap.cxx | 167 ++++++++-------- 3 files changed, 396 insertions(+), 415 deletions(-)
New commits: commit 8bc077c961a84f8a3186bc1bdc7b417c112b825e Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Thu Jul 6 11:05:20 2023 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Thu Jul 6 16:11:04 2023 +0200 flatten some bitmap code Change-Id: I0f4435899e3002c152767aaa68ffa1629b4a172d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154098 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx index 8214b266b640..1759787d05fc 100644 --- a/vcl/source/bitmap/bitmap.cxx +++ b/vcl/source/bitmap/bitmap.cxx @@ -300,25 +300,22 @@ bool Bitmap::HasGreyPalette8Bit() const BitmapChecksum Bitmap::GetChecksum() const { - BitmapChecksum nRet = 0; + if( !mxSalBmp ) + return 0; - if( mxSalBmp ) + BitmapChecksum nRet = mxSalBmp->GetChecksum(); + if (!nRet) { - nRet = mxSalBmp->GetChecksum(); - - if (!nRet) + // nRet == 0 => probably, we were not able to acquire + // the buffer in SalBitmap::updateChecksum; + // so, we need to update the imp bitmap for this bitmap instance + // as we do in BitmapInfoAccess::ImplCreate + std::shared_ptr<SalBitmap> xNewImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap()); + if (xNewImpBmp->Create(*mxSalBmp, getPixelFormat())) { - // nRet == 0 => probably, we were not able to acquire - // the buffer in SalBitmap::updateChecksum; - // so, we need to update the imp bitmap for this bitmap instance - // as we do in BitmapInfoAccess::ImplCreate - std::shared_ptr<SalBitmap> xNewImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap()); - if (xNewImpBmp->Create(*mxSalBmp, getPixelFormat())) - { - Bitmap* pThis = const_cast<Bitmap*>(this); - pThis->mxSalBmp = xNewImpBmp; - nRet = mxSalBmp->GetChecksum(); - } + Bitmap* pThis = const_cast<Bitmap*>(this); + pThis->mxSalBmp = xNewImpBmp; + nRet = mxSalBmp->GetChecksum(); } } @@ -1500,147 +1497,141 @@ bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness ) { - bool bRet = false; - // nothing to do => return quickly if( !nLuminancePercent && !nContrastPercent && !nChannelRPercent && !nChannelGPercent && !nChannelBPercent && ( fGamma == 1.0 ) && !bInvert ) { - bRet = true; + return true; } + + BitmapScopedWriteAccess pAcc(*this); + if( !pAcc ) + return false; + + BitmapColor aCol; + const tools::Long nW = pAcc->Width(); + const tools::Long nH = pAcc->Height(); + std::unique_ptr<sal_uInt8[]> cMapR(new sal_uInt8[ 256 ]); + std::unique_ptr<sal_uInt8[]> cMapG(new sal_uInt8[ 256 ]); + std::unique_ptr<sal_uInt8[]> cMapB(new sal_uInt8[ 256 ]); + double fM, fROff, fGOff, fBOff, fOff; + + // calculate slope + if( nContrastPercent >= 0 ) + fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) ); else - { - BitmapScopedWriteAccess pAcc(*this); + fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0; - if( pAcc ) - { - BitmapColor aCol; - const tools::Long nW = pAcc->Width(); - const tools::Long nH = pAcc->Height(); - std::unique_ptr<sal_uInt8[]> cMapR(new sal_uInt8[ 256 ]); - std::unique_ptr<sal_uInt8[]> cMapG(new sal_uInt8[ 256 ]); - std::unique_ptr<sal_uInt8[]> cMapB(new sal_uInt8[ 256 ]); - double fM, fROff, fGOff, fBOff, fOff; - - // calculate slope - if( nContrastPercent >= 0 ) - fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) ); - else - fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0; + if(!msoBrightness) + // total offset = luminance offset + contrast offset + fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0; + else + fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55; - if(!msoBrightness) - // total offset = luminance offset + contrast offset - fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0; - else - fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55; + // channel offset = channel offset + total offset + fROff = nChannelRPercent * 2.55 + fOff; + fGOff = nChannelGPercent * 2.55 + fOff; + fBOff = nChannelBPercent * 2.55 + fOff; - // channel offset = channel offset + total offset - fROff = nChannelRPercent * 2.55 + fOff; - fGOff = nChannelGPercent * 2.55 + fOff; - fBOff = nChannelBPercent * 2.55 + fOff; + // calculate gamma value + fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma ); + const bool bGamma = ( fGamma != 1.0 ); - // calculate gamma value - fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma ); - const bool bGamma = ( fGamma != 1.0 ); + // create mapping table + for( tools::Long nX = 0; nX < 256; nX++ ) + { + if(!msoBrightness) + { + cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 )); + cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 )); + cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 )); + } + else + { + // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128" + // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason, + // use neither first, but apparently it applies half of brightness before contrast and half afterwards. + cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 )); + cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 )); + cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 )); + } + if( bGamma ) + { + cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma ); + cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma ); + cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma ); + } - // create mapping table - for( tools::Long nX = 0; nX < 256; nX++ ) - { - if(!msoBrightness) - { - cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 )); - cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 )); - cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 )); - } - else - { - // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128" - // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason, - // use neither first, but apparently it applies half of brightness before contrast and half afterwards. - cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 )); - cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 )); - cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 )); - } - if( bGamma ) - { - cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma ); - cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma ); - cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma ); - } + if( bInvert ) + { + cMapR[ nX ] = ~cMapR[ nX ]; + cMapG[ nX ] = ~cMapG[ nX ]; + cMapB[ nX ] = ~cMapB[ nX ]; + } + } - if( bInvert ) - { - cMapR[ nX ] = ~cMapR[ nX ]; - cMapG[ nX ] = ~cMapG[ nX ]; - cMapB[ nX ] = ~cMapB[ nX ]; - } - } + // do modifying + if( pAcc->HasPalette() ) + { + BitmapColor aNewCol; - // do modifying - if( pAcc->HasPalette() ) - { - BitmapColor aNewCol; + for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ ) + { + const BitmapColor& rCol = pAcc->GetPaletteColor( i ); + aNewCol.SetRed( cMapR[ rCol.GetRed() ] ); + aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] ); + aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] ); + pAcc->SetPaletteColor( i, aNewCol ); + } + } + else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr ) + { + for( tools::Long nY = 0; nY < nH; nY++ ) + { + Scanline pScan = pAcc->GetScanline( nY ); - for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ ) - { - const BitmapColor& rCol = pAcc->GetPaletteColor( i ); - aNewCol.SetRed( cMapR[ rCol.GetRed() ] ); - aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] ); - aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] ); - pAcc->SetPaletteColor( i, aNewCol ); - } - } - else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr ) + for( tools::Long nX = 0; nX < nW; nX++ ) { - for( tools::Long nY = 0; nY < nH; nY++ ) - { - Scanline pScan = pAcc->GetScanline( nY ); - - for( tools::Long nX = 0; nX < nW; nX++ ) - { - *pScan = cMapB[ *pScan ]; pScan++; - *pScan = cMapG[ *pScan ]; pScan++; - *pScan = cMapR[ *pScan ]; pScan++; - } - } + *pScan = cMapB[ *pScan ]; pScan++; + *pScan = cMapG[ *pScan ]; pScan++; + *pScan = cMapR[ *pScan ]; pScan++; } - else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb ) - { - for( tools::Long nY = 0; nY < nH; nY++ ) - { - Scanline pScan = pAcc->GetScanline( nY ); + } + } + else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb ) + { + for( tools::Long nY = 0; nY < nH; nY++ ) + { + Scanline pScan = pAcc->GetScanline( nY ); - for( tools::Long nX = 0; nX < nW; nX++ ) - { - *pScan = cMapR[ *pScan ]; pScan++; - *pScan = cMapG[ *pScan ]; pScan++; - *pScan = cMapB[ *pScan ]; pScan++; - } - } + for( tools::Long nX = 0; nX < nW; nX++ ) + { + *pScan = cMapR[ *pScan ]; pScan++; + *pScan = cMapG[ *pScan ]; pScan++; + *pScan = cMapB[ *pScan ]; pScan++; } - else + } + } + else + { + for( tools::Long nY = 0; nY < nH; nY++ ) + { + Scanline pScanline = pAcc->GetScanline(nY); + for( tools::Long nX = 0; nX < nW; nX++ ) { - for( tools::Long nY = 0; nY < nH; nY++ ) - { - Scanline pScanline = pAcc->GetScanline(nY); - for( tools::Long nX = 0; nX < nW; nX++ ) - { - aCol = pAcc->GetPixelFromData( pScanline, nX ); - aCol.SetRed( cMapR[ aCol.GetRed() ] ); - aCol.SetGreen( cMapG[ aCol.GetGreen() ] ); - aCol.SetBlue( cMapB[ aCol.GetBlue() ] ); - pAcc->SetPixelOnData( pScanline, nX, aCol ); - } - } + aCol = pAcc->GetPixelFromData( pScanline, nX ); + aCol.SetRed( cMapR[ aCol.GetRed() ] ); + aCol.SetGreen( cMapG[ aCol.GetGreen() ] ); + aCol.SetBlue( cMapB[ aCol.GetBlue() ] ); + pAcc->SetPixelOnData( pScanline, nX, aCol ); } - - pAcc.reset(); - bRet = true; } } - return bRet; + pAcc.reset(); + + return true; } namespace diff --git a/vcl/source/bitmap/bitmappaint.cxx b/vcl/source/bitmap/bitmappaint.cxx index 4811d14e3eea..0207bb813fe8 100644 --- a/vcl/source/bitmap/bitmappaint.cxx +++ b/vcl/source/bitmap/bitmappaint.cxx @@ -291,134 +291,132 @@ bool Bitmap::Rotate(Degree10 nAngle10, const Color& rFillColor) return Mirror(BmpMirrorFlags::Horizontal | BmpMirrorFlags::Vertical); ScopedReadAccess pReadAcc(*this); + if (!pReadAcc) + return false; + Bitmap aRotatedBmp; bool bRet = false; + const Size aSizePix(GetSizePixel()); - if (pReadAcc) + if (nAngle10 == 900_deg10 || nAngle10 == 2700_deg10) { - const Size aSizePix(GetSizePixel()); + const Size aNewSizePix(aSizePix.Height(), aSizePix.Width()); + Bitmap aNewBmp(aNewSizePix, getPixelFormat(), &pReadAcc->GetPalette()); + BitmapScopedWriteAccess pWriteAcc(aNewBmp); - if (nAngle10 == 900_deg10 || nAngle10 == 2700_deg10) + if (pWriteAcc) { - const Size aNewSizePix(aSizePix.Height(), aSizePix.Width()); - Bitmap aNewBmp(aNewSizePix, getPixelFormat(), &pReadAcc->GetPalette()); - BitmapScopedWriteAccess pWriteAcc(aNewBmp); + const tools::Long nWidth = aSizePix.Width(); + const tools::Long nWidth1 = nWidth - 1; + const tools::Long nHeight = aSizePix.Height(); + const tools::Long nHeight1 = nHeight - 1; + const tools::Long nNewWidth = aNewSizePix.Width(); + const tools::Long nNewHeight = aNewSizePix.Height(); - if (pWriteAcc) + if (nAngle10 == 900_deg10) { - const tools::Long nWidth = aSizePix.Width(); - const tools::Long nWidth1 = nWidth - 1; - const tools::Long nHeight = aSizePix.Height(); - const tools::Long nHeight1 = nHeight - 1; - const tools::Long nNewWidth = aNewSizePix.Width(); - const tools::Long nNewHeight = aNewSizePix.Height(); - - if (nAngle10 == 900_deg10) + for (tools::Long nY = 0, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX--) { - for (tools::Long nY = 0, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX--) + Scanline pScanline = pWriteAcc->GetScanline(nY); + for (tools::Long nX = 0, nOtherY = 0; nX < nNewWidth; nX++) { - Scanline pScanline = pWriteAcc->GetScanline(nY); - for (tools::Long nX = 0, nOtherY = 0; nX < nNewWidth; nX++) - { - pWriteAcc->SetPixelOnData(pScanline, nX, - pReadAcc->GetPixel(nOtherY++, nOtherX)); - } + pWriteAcc->SetPixelOnData(pScanline, nX, + pReadAcc->GetPixel(nOtherY++, nOtherX)); } } - else if (nAngle10 == 2700_deg10) + } + else if (nAngle10 == 2700_deg10) + { + for (tools::Long nY = 0, nOtherX = 0; nY < nNewHeight; nY++, nOtherX++) { - for (tools::Long nY = 0, nOtherX = 0; nY < nNewHeight; nY++, nOtherX++) + Scanline pScanline = pWriteAcc->GetScanline(nY); + for (tools::Long nX = 0, nOtherY = nHeight1; nX < nNewWidth; nX++) { - Scanline pScanline = pWriteAcc->GetScanline(nY); - for (tools::Long nX = 0, nOtherY = nHeight1; nX < nNewWidth; nX++) - { - pWriteAcc->SetPixelOnData(pScanline, nX, - pReadAcc->GetPixel(nOtherY--, nOtherX)); - } + pWriteAcc->SetPixelOnData(pScanline, nX, + pReadAcc->GetPixel(nOtherY--, nOtherX)); } } - - pWriteAcc.reset(); } - aRotatedBmp = aNewBmp; + pWriteAcc.reset(); } - else - { - Point aTmpPoint; - tools::Rectangle aTmpRectangle(aTmpPoint, aSizePix); - tools::Polygon aPoly(aTmpRectangle); - aPoly.Rotate(aTmpPoint, nAngle10); - tools::Rectangle aNewBound(aPoly.GetBoundRect()); - const Size aNewSizePix(aNewBound.GetSize()); - Bitmap aNewBmp(aNewSizePix, getPixelFormat(), &pReadAcc->GetPalette()); - BitmapScopedWriteAccess pWriteAcc(aNewBmp); + aRotatedBmp = aNewBmp; + } + else + { + Point aTmpPoint; + tools::Rectangle aTmpRectangle(aTmpPoint, aSizePix); + tools::Polygon aPoly(aTmpRectangle); + aPoly.Rotate(aTmpPoint, nAngle10); + + tools::Rectangle aNewBound(aPoly.GetBoundRect()); + const Size aNewSizePix(aNewBound.GetSize()); + Bitmap aNewBmp(aNewSizePix, getPixelFormat(), &pReadAcc->GetPalette()); + BitmapScopedWriteAccess pWriteAcc(aNewBmp); - if (pWriteAcc) + if (pWriteAcc) + { + const BitmapColor aFillColor(pWriteAcc->GetBestMatchingColor(rFillColor)); + const double fCosAngle = cos(toRadians(nAngle10)); + const double fSinAngle = sin(toRadians(nAngle10)); + const double fXMin = aNewBound.Left(); + const double fYMin = aNewBound.Top(); + const sal_Int32 nWidth = aSizePix.Width(); + const sal_Int32 nHeight = aSizePix.Height(); + const sal_Int32 nNewWidth = aNewSizePix.Width(); + const sal_Int32 nNewHeight = aNewSizePix.Height(); + // we store alternating values of cos/sin. We do this instead of + // separate arrays to improve cache hit. + std::unique_ptr<sal_Int32[]> pCosSinX(new sal_Int32[nNewWidth * 2]); + std::unique_ptr<sal_Int32[]> pCosSinY(new sal_Int32[nNewHeight * 2]); + + for (sal_Int32 nIdx = 0, nX = 0; nX < nNewWidth; nX++) { - const BitmapColor aFillColor(pWriteAcc->GetBestMatchingColor(rFillColor)); - const double fCosAngle = cos(toRadians(nAngle10)); - const double fSinAngle = sin(toRadians(nAngle10)); - const double fXMin = aNewBound.Left(); - const double fYMin = aNewBound.Top(); - const sal_Int32 nWidth = aSizePix.Width(); - const sal_Int32 nHeight = aSizePix.Height(); - const sal_Int32 nNewWidth = aNewSizePix.Width(); - const sal_Int32 nNewHeight = aNewSizePix.Height(); - // we store alternating values of cos/sin. We do this instead of - // separate arrays to improve cache hit. - std::unique_ptr<sal_Int32[]> pCosSinX(new sal_Int32[nNewWidth * 2]); - std::unique_ptr<sal_Int32[]> pCosSinY(new sal_Int32[nNewHeight * 2]); - - for (sal_Int32 nIdx = 0, nX = 0; nX < nNewWidth; nX++) - { - const double fTmp = (fXMin + nX) * 64; + const double fTmp = (fXMin + nX) * 64; - pCosSinX[nIdx++] = std::round(fCosAngle * fTmp); - pCosSinX[nIdx++] = std::round(fSinAngle * fTmp); - } + pCosSinX[nIdx++] = std::round(fCosAngle * fTmp); + pCosSinX[nIdx++] = std::round(fSinAngle * fTmp); + } - for (sal_Int32 nIdx = 0, nY = 0; nY < nNewHeight; nY++) - { - const double fTmp = (fYMin + nY) * 64; + for (sal_Int32 nIdx = 0, nY = 0; nY < nNewHeight; nY++) + { + const double fTmp = (fYMin + nY) * 64; - pCosSinY[nIdx++] = std::round(fCosAngle * fTmp); - pCosSinY[nIdx++] = std::round(fSinAngle * fTmp); - } + pCosSinY[nIdx++] = std::round(fCosAngle * fTmp); + pCosSinY[nIdx++] = std::round(fSinAngle * fTmp); + } + + for (sal_Int32 nCosSinYIdx = 0, nY = 0; nY < nNewHeight; nY++) + { + sal_Int32 nCosY = pCosSinY[nCosSinYIdx++]; + sal_Int32 nSinY = pCosSinY[nCosSinYIdx++]; + Scanline pScanline = pWriteAcc->GetScanline(nY); - for (sal_Int32 nCosSinYIdx = 0, nY = 0; nY < nNewHeight; nY++) + for (sal_Int32 nCosSinXIdx = 0, nX = 0; nX < nNewWidth; nX++) { - sal_Int32 nCosY = pCosSinY[nCosSinYIdx++]; - sal_Int32 nSinY = pCosSinY[nCosSinYIdx++]; - Scanline pScanline = pWriteAcc->GetScanline(nY); + sal_Int32 nRotX = (pCosSinX[nCosSinXIdx++] - nSinY) >> 6; + sal_Int32 nRotY = (pCosSinX[nCosSinXIdx++] + nCosY) >> 6; - for (sal_Int32 nCosSinXIdx = 0, nX = 0; nX < nNewWidth; nX++) + if ((nRotX > -1) && (nRotX < nWidth) && (nRotY > -1) && (nRotY < nHeight)) { - sal_Int32 nRotX = (pCosSinX[nCosSinXIdx++] - nSinY) >> 6; - sal_Int32 nRotY = (pCosSinX[nCosSinXIdx++] + nCosY) >> 6; - - if ((nRotX > -1) && (nRotX < nWidth) && (nRotY > -1) && (nRotY < nHeight)) - { - pWriteAcc->SetPixelOnData(pScanline, nX, - pReadAcc->GetPixel(nRotY, nRotX)); - } - else - { - pWriteAcc->SetPixelOnData(pScanline, nX, aFillColor); - } + pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixel(nRotY, nRotX)); + } + else + { + pWriteAcc->SetPixelOnData(pScanline, nX, aFillColor); } } - - pWriteAcc.reset(); } - aRotatedBmp = aNewBmp; + pWriteAcc.reset(); } - pReadAcc.reset(); + aRotatedBmp = aNewBmp; } + pReadAcc.reset(); + bRet = !aRotatedBmp.IsEmpty(); if (bRet) ReassignWithSize(aRotatedBmp); @@ -759,157 +757,150 @@ bool Bitmap::Replace(const Color& rSearchColor, const Color& rReplaceColor, sal_ } BitmapScopedWriteAccess pAcc(*this); - bool bRet = false; + if (!pAcc) + return false; - if (pAcc) + const tools::Long nMinR = MinMax<tools::Long>(rSearchColor.GetRed() - nTol, 0, 255); + const tools::Long nMaxR = MinMax<tools::Long>(rSearchColor.GetRed() + nTol, 0, 255); + const tools::Long nMinG = MinMax<tools::Long>(rSearchColor.GetGreen() - nTol, 0, 255); + const tools::Long nMaxG = MinMax<tools::Long>(rSearchColor.GetGreen() + nTol, 0, 255); + const tools::Long nMinB = MinMax<tools::Long>(rSearchColor.GetBlue() - nTol, 0, 255); + const tools::Long nMaxB = MinMax<tools::Long>(rSearchColor.GetBlue() + nTol, 0, 255); + + if (pAcc->HasPalette()) { - const tools::Long nMinR = MinMax<tools::Long>(rSearchColor.GetRed() - nTol, 0, 255); - const tools::Long nMaxR = MinMax<tools::Long>(rSearchColor.GetRed() + nTol, 0, 255); - const tools::Long nMinG = MinMax<tools::Long>(rSearchColor.GetGreen() - nTol, 0, 255); - const tools::Long nMaxG = MinMax<tools::Long>(rSearchColor.GetGreen() + nTol, 0, 255); - const tools::Long nMinB = MinMax<tools::Long>(rSearchColor.GetBlue() - nTol, 0, 255); - const tools::Long nMaxB = MinMax<tools::Long>(rSearchColor.GetBlue() + nTol, 0, 255); - - if (pAcc->HasPalette()) + for (sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++) { - for (sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++) - { - const BitmapColor& rCol = pAcc->GetPaletteColor(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); - } + 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)); + } + else + { + BitmapColor aCol; + const BitmapColor aReplace(pAcc->GetBestMatchingColor(rReplaceColor)); - for (tools::Long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++) + for (tools::Long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++) + { + Scanline pScanline = pAcc->GetScanline(nY); + for (tools::Long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++) { - Scanline pScanline = pAcc->GetScanline(nY); - for (tools::Long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++) - { - aCol = pAcc->GetPixelFromData(pScanline, nX); + aCol = pAcc->GetPixelFromData(pScanline, nX); - if (nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() && nMinG <= aCol.GetGreen() - && nMaxG >= aCol.GetGreen() && nMinB <= aCol.GetBlue() - && nMaxB >= aCol.GetBlue()) - { - pAcc->SetPixelOnData(pScanline, nX, aReplace); - } + if (nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() && nMinG <= aCol.GetGreen() + && nMaxG >= aCol.GetGreen() && nMinB <= aCol.GetBlue() + && nMaxB >= aCol.GetBlue()) + { + pAcc->SetPixelOnData(pScanline, nX, aReplace); } } } - - pAcc.reset(); - bRet = true; } - return bRet; + pAcc.reset(); + + return true; } bool Bitmap::Replace(const Color* pSearchColors, const Color* pReplaceColors, size_t nColorCount, sal_uInt8 const* pTols) { BitmapScopedWriteAccess pAcc(*this); - bool bRet = false; + if (!pAcc) + return false; - if (pAcc) + std::vector<sal_uInt8> aMinR(nColorCount); + std::vector<sal_uInt8> aMaxR(nColorCount); + std::vector<sal_uInt8> aMinG(nColorCount); + std::vector<sal_uInt8> aMaxG(nColorCount); + std::vector<sal_uInt8> aMinB(nColorCount); + std::vector<sal_uInt8> aMaxB(nColorCount); + + if (pTols) { - std::vector<sal_uInt8> aMinR(nColorCount); - std::vector<sal_uInt8> aMaxR(nColorCount); - std::vector<sal_uInt8> aMinG(nColorCount); - std::vector<sal_uInt8> aMaxG(nColorCount); - std::vector<sal_uInt8> aMinB(nColorCount); - std::vector<sal_uInt8> aMaxB(nColorCount); - - if (pTols) + for (size_t i = 0; i < nColorCount; ++i) { - for (size_t i = 0; i < nColorCount; ++i) - { - const Color& rCol = pSearchColors[i]; - const sal_uInt8 nTol = pTols[i]; - - aMinR[i] = std::clamp(rCol.GetRed() - nTol, 0, 255); - aMaxR[i] = std::clamp(rCol.GetRed() + nTol, 0, 255); - aMinG[i] = std::clamp(rCol.GetGreen() - nTol, 0, 255); - aMaxG[i] = std::clamp(rCol.GetGreen() + nTol, 0, 255); - aMinB[i] = std::clamp(rCol.GetBlue() - nTol, 0, 255); - aMaxB[i] = std::clamp(rCol.GetBlue() + nTol, 0, 255); - } + const Color& rCol = pSearchColors[i]; + const sal_uInt8 nTol = pTols[i]; + + aMinR[i] = std::clamp(rCol.GetRed() - nTol, 0, 255); + aMaxR[i] = std::clamp(rCol.GetRed() + nTol, 0, 255); + aMinG[i] = std::clamp(rCol.GetGreen() - nTol, 0, 255); + aMaxG[i] = std::clamp(rCol.GetGreen() + nTol, 0, 255); + aMinB[i] = std::clamp(rCol.GetBlue() - nTol, 0, 255); + aMaxB[i] = std::clamp(rCol.GetBlue() + nTol, 0, 255); } - else + } + else + { + for (size_t i = 0; i < nColorCount; ++i) { - for (size_t i = 0; i < nColorCount; ++i) - { - const Color& rCol = pSearchColors[i]; - - aMinR[i] = rCol.GetRed(); - aMaxR[i] = rCol.GetRed(); - aMinG[i] = rCol.GetGreen(); - aMaxG[i] = rCol.GetGreen(); - aMinB[i] = rCol.GetBlue(); - aMaxB[i] = rCol.GetBlue(); - } + const Color& rCol = pSearchColors[i]; + + aMinR[i] = rCol.GetRed(); + aMaxR[i] = rCol.GetRed(); + aMinG[i] = rCol.GetGreen(); + aMaxG[i] = rCol.GetGreen(); + aMinB[i] = rCol.GetBlue(); + aMaxB[i] = rCol.GetBlue(); } + } - if (pAcc->HasPalette()) + if (pAcc->HasPalette()) + { + for (sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; + nEntry++) { - for (sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); - nEntry < nPalCount; nEntry++) - { - const BitmapColor& rCol = pAcc->GetPaletteColor(nEntry); + const BitmapColor& rCol = pAcc->GetPaletteColor(nEntry); - for (size_t i = 0; i < nColorCount; ++i) + for (size_t i = 0; i < nColorCount; ++i) + { + if (aMinR[i] <= rCol.GetRed() && aMaxR[i] >= rCol.GetRed() + && aMinG[i] <= rCol.GetGreen() && aMaxG[i] >= rCol.GetGreen() + && aMinB[i] <= rCol.GetBlue() && aMaxB[i] >= rCol.GetBlue()) { - if (aMinR[i] <= rCol.GetRed() && aMaxR[i] >= rCol.GetRed() - && aMinG[i] <= rCol.GetGreen() && aMaxG[i] >= rCol.GetGreen() - && aMinB[i] <= rCol.GetBlue() && aMaxB[i] >= rCol.GetBlue()) - { - pAcc->SetPaletteColor(nEntry, pReplaceColors[i]); - break; - } + pAcc->SetPaletteColor(nEntry, pReplaceColors[i]); + break; } } } - else - { - std::vector<BitmapColor> aReplaces(nColorCount); + } + else + { + std::vector<BitmapColor> aReplaces(nColorCount); - for (size_t i = 0; i < nColorCount; ++i) - aReplaces[i] = pAcc->GetBestMatchingColor(pReplaceColors[i]); + for (size_t i = 0; i < nColorCount; ++i) + aReplaces[i] = pAcc->GetBestMatchingColor(pReplaceColors[i]); - for (tools::Long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++) + for (tools::Long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++) + { + Scanline pScanline = pAcc->GetScanline(nY); + for (tools::Long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++) { - Scanline pScanline = pAcc->GetScanline(nY); - for (tools::Long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++) - { - BitmapColor aCol = pAcc->GetPixelFromData(pScanline, nX); + BitmapColor aCol = pAcc->GetPixelFromData(pScanline, nX); - for (size_t i = 0; i < nColorCount; ++i) + for (size_t i = 0; i < nColorCount; ++i) + { + if (aMinR[i] <= aCol.GetRed() && aMaxR[i] >= aCol.GetRed() + && aMinG[i] <= aCol.GetGreen() && aMaxG[i] >= aCol.GetGreen() + && aMinB[i] <= aCol.GetBlue() && aMaxB[i] >= aCol.GetBlue()) { - if (aMinR[i] <= aCol.GetRed() && aMaxR[i] >= aCol.GetRed() - && aMinG[i] <= aCol.GetGreen() && aMaxG[i] >= aCol.GetGreen() - && aMinB[i] <= aCol.GetBlue() && aMaxB[i] >= aCol.GetBlue()) - { - pAcc->SetPixelOnData(pScanline, nX, aReplaces[i]); - break; - } + pAcc->SetPixelOnData(pScanline, nX, aReplaces[i]); + break; } } } } - - pAcc.reset(); - bRet = true; } - return bRet; + pAcc.reset(); + + return true; } bool Bitmap::CombineOr(const Bitmap& rMask) diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx index 239ec93e202b..612ea5dc605d 100644 --- a/vcl/source/outdev/bitmap.cxx +++ b/vcl/source/outdev/bitmap.cxx @@ -190,93 +190,92 @@ void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const { - Bitmap aBmp; + if ( !mpGraphics && !AcquireGraphics() ) + return Bitmap(); + + assert(mpGraphics); + tools::Long nX = ImplLogicXToDevicePixel( rSrcPt.X() ); tools::Long nY = ImplLogicYToDevicePixel( rSrcPt.Y() ); tools::Long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() ); tools::Long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() ); + if ( nWidth <= 0 || nHeight <= 0 || nX > (mnOutWidth + mnOutOffX) || nY > (mnOutHeight + mnOutOffY)) + return Bitmap(); - if ( mpGraphics || AcquireGraphics() ) - { - assert(mpGraphics); + Bitmap aBmp; + tools::Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) ); + bool bClipped = false; - if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY)) - { - tools::Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) ); - bool bClipped = false; + // X-Coordinate outside of draw area? + if ( nX < mnOutOffX ) + { + nWidth -= ( mnOutOffX - nX ); + nX = mnOutOffX; + bClipped = true; + } - // X-Coordinate outside of draw area? - if ( nX < mnOutOffX ) - { - nWidth -= ( mnOutOffX - nX ); - nX = mnOutOffX; - bClipped = true; - } + // Y-Coordinate outside of draw area? + if ( nY < mnOutOffY ) + { + nHeight -= ( mnOutOffY - nY ); + nY = mnOutOffY; + bClipped = true; + } - // Y-Coordinate outside of draw area? - if ( nY < mnOutOffY ) - { - nHeight -= ( mnOutOffY - nY ); - nY = mnOutOffY; - bClipped = true; - } + // Width outside of draw area? + if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) ) + { + nWidth = mnOutOffX + mnOutWidth - nX; + bClipped = true; + } - // Width outside of draw area? - if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) ) - { - nWidth = mnOutOffX + mnOutWidth - nX; - bClipped = true; - } + // Height outside of draw area? + if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) ) + { + nHeight = mnOutOffY + mnOutHeight - nY; + bClipped = true; + } - // Height outside of draw area? - if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) ) - { - nHeight = mnOutOffY + mnOutHeight - nY; - bClipped = true; - } + if ( bClipped ) + { + // If the visible part has been clipped, we have to create a + // Bitmap with the correct size in which we copy the clipped + // Bitmap to the correct position. + ScopedVclPtrInstance< VirtualDevice > aVDev( *this ); - if ( bClipped ) + if ( aVDev->SetOutputSizePixel( aRect.GetSize() ) ) + { + if ( aVDev->mpGraphics || aVDev->AcquireGraphics() ) { - // If the visible part has been clipped, we have to create a - // Bitmap with the correct size in which we copy the clipped - // Bitmap to the correct position. - ScopedVclPtrInstance< VirtualDevice > aVDev( *this ); - - if ( aVDev->SetOutputSizePixel( aRect.GetSize() ) ) + if ( (nWidth > 0) && (nHeight > 0) ) { - if ( aVDev->mpGraphics || aVDev->AcquireGraphics() ) - { - if ( (nWidth > 0) && (nHeight > 0) ) - { - SalTwoRect aPosAry(nX, nY, nWidth, nHeight, - (aRect.Left() < mnOutOffX) ? (mnOutOffX - aRect.Left()) : 0L, - (aRect.Top() < mnOutOffY) ? (mnOutOffY - aRect.Top()) : 0L, - nWidth, nHeight); - aVDev->mpGraphics->CopyBits(aPosAry, *mpGraphics, *this, *this); - } - else - { - OSL_ENSURE(false, "CopyBits with zero or negative width or height"); - } - - aBmp = aVDev->GetBitmap( Point(), aVDev->GetOutputSizePixel() ); - } - else - bClipped = false; + SalTwoRect aPosAry(nX, nY, nWidth, nHeight, + (aRect.Left() < mnOutOffX) ? (mnOutOffX - aRect.Left()) : 0L, + (aRect.Top() < mnOutOffY) ? (mnOutOffY - aRect.Top()) : 0L, + nWidth, nHeight); + aVDev->mpGraphics->CopyBits(aPosAry, *mpGraphics, *this, *this); } else - bClipped = false; - } - - if ( !bClipped ) - { - std::shared_ptr<SalBitmap> pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, *this ); - - if( pSalBmp ) { - aBmp.ImplSetSalBitmap(pSalBmp); + OSL_ENSURE(false, "CopyBits with zero or negative width or height"); } + + aBmp = aVDev->GetBitmap( Point(), aVDev->GetOutputSizePixel() ); } + else + bClipped = false; + } + else + bClipped = false; + } + + if ( !bClipped ) + { + std::shared_ptr<SalBitmap> pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, *this ); + + if( pSalBmp ) + { + aBmp.ImplSetSalBitmap(pSalBmp); } } @@ -444,26 +443,26 @@ public: const tools::Long nDstWidth, const tools::Long nDstHeight) { - if (pSource && pSourceAlpha && pDestination) - { - ScanlineFormat nSourceFormat = pSource->GetScanlineFormat(); - ScanlineFormat nDestinationFormat = pDestination->GetScanlineFormat(); + if (!pSource || !pSourceAlpha || !pDestination) + return false; + + ScanlineFormat nSourceFormat = pSource->GetScanlineFormat(); + ScanlineFormat nDestinationFormat = pDestination->GetScanlineFormat(); - switch (nSourceFormat) + switch (nSourceFormat) + { + case ScanlineFormat::N24BitTcRgb: + case ScanlineFormat::N24BitTcBgr: { - case ScanlineFormat::N24BitTcRgb: - case ScanlineFormat::N24BitTcBgr: + if ( (nSourceFormat == ScanlineFormat::N24BitTcBgr && nDestinationFormat == ScanlineFormat::N32BitTcBgra) + || (nSourceFormat == ScanlineFormat::N24BitTcRgb && nDestinationFormat == ScanlineFormat::N32BitTcRgba)) { - if ( (nSourceFormat == ScanlineFormat::N24BitTcBgr && nDestinationFormat == ScanlineFormat::N32BitTcBgra) - || (nSourceFormat == ScanlineFormat::N24BitTcRgb && nDestinationFormat == ScanlineFormat::N32BitTcRgba)) - { - blendBitmap24(pDestination, pSource, pSourceAlpha, nDstWidth, nDstHeight); - return true; - } + blendBitmap24(pDestination, pSource, pSourceAlpha, nDstWidth, nDstHeight); + return true; } - break; - default: break; } + break; + default: break; } return false; }