include/vcl/bitmap.hxx | 4 - include/vcl/bitmapex.hxx | 3 - vcl/source/bitmap/BitmapEx.cxx | 17 ------ vcl/source/bitmap/bitmap.cxx | 102 ++++++++++++++++++++++++++++++----------- 4 files changed, 77 insertions(+), 49 deletions(-)
New commits: commit a65a224c2b1b9b5fcccfb04ca14d37a8d615b85e Author: Noel Grandin <[email protected]> AuthorDate: Fri Sep 5 11:01:20 2025 +0200 Commit: Noel Grandin <[email protected]> CommitDate: Fri Sep 5 16:55:12 2025 +0200 use less BitmapEx in Bitmap we want Bitmap to be independant of BitmapEx Change-Id: I47dc1e62f5575a75fd2e9e78085146b079c49187 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190616 Reviewed-by: Noel Grandin <[email protected]> Tested-by: Jenkins diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index 3cb18150a00d..2005bfeab669 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -38,7 +38,6 @@ #include <memory> class AlphaMask; -class BitmapEx; namespace basegfx { class BColorModifierStack; } namespace com::sun::star::rendering { class XBitmapCanvas; @@ -119,7 +118,6 @@ public: explicit Bitmap( const OUString& rIconName ); Bitmap( const Bitmap& rBitmap ); Bitmap( const Bitmap& rBitmap, Point aSrc, Size aSize ); - explicit Bitmap( const BitmapEx& rBitmapEx ); Bitmap( const Size& rSizePixel, vcl::PixelFormat ePixelFormat, const BitmapPalette* pPal = nullptr ); Bitmap( const Bitmap& rBmp, const Bitmap& rMask ); Bitmap( const Bitmap& rBmp, const AlphaMask& rAlphaMask ); @@ -658,7 +656,7 @@ public: /** Remove existing blending against COL_WHITE based on given AlphaMask - Inside convertToBitmapEx the content gets rendered to RGB target (no 'A'), + Inside convertToBitmap the content gets rendered to RGB target (no 'A'), so it gets blended against the start condition of the target device which is blank (usually white background, but others may be used). Usually rendering to RGB is sufficient (e.g. EditViews), but for conversion diff --git a/include/vcl/bitmapex.hxx b/include/vcl/bitmapex.hxx index 0b1a14e77fff..b319071bce85 100644 --- a/include/vcl/bitmapex.hxx +++ b/include/vcl/bitmapex.hxx @@ -439,9 +439,6 @@ public: SAL_DLLPRIVATE std::shared_ptr<SalBitmap> const & ImplGetBitmapSalBitmap() const { return maBitmap.ImplGetSalBitmap(); } - /// Dumps the pixels as PNG in bitmap.png. - void DumpAsPng(const char* pFileName = nullptr) const; - private: friend class ImpGraphic; friend class OutputDevice; diff --git a/vcl/source/bitmap/BitmapEx.cxx b/vcl/source/bitmap/BitmapEx.cxx index 61f7db99a63b..8a853d2bdbd9 100644 --- a/vcl/source/bitmap/BitmapEx.cxx +++ b/vcl/source/bitmap/BitmapEx.cxx @@ -1311,21 +1311,4 @@ void BitmapEx::GetColorModel(css::uno::Sequence< sal_Int32 >& rRGBPalette, rnBitCount = pReadAccess->GetBitCount(); } -void BitmapEx::DumpAsPng(const char* pFileName) const -{ - OUString sPath(u"file:///tmp/bitmap.png"_ustr); - if (pFileName) - { - sPath = OUString::fromUtf8(pFileName); - } - else if (OUString env = o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr); !env.isEmpty()) - { - sPath = env; - } - SvFileStream aStream(sPath, StreamMode::STD_READWRITE | StreamMode::TRUNC); - assert(aStream.good()); - vcl::PngImageWriter aWriter(aStream); - aWriter.write(Bitmap(*this)); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx index e38b0236daa3..db842d55090c 100644 --- a/vcl/source/bitmap/bitmap.cxx +++ b/vcl/source/bitmap/bitmap.cxx @@ -26,7 +26,6 @@ #include <utility> #include <vcl/bitmap.hxx> -#include <vcl/bitmapex.hxx> #include <vcl/outdev.hxx> #include <svdata.hxx> @@ -141,26 +140,25 @@ Bitmap::Bitmap( const Size& rSizePixel, vcl::PixelFormat ePixelFormat, const Bit mxSalBmp->Create(rSizePixel, ePixelFormat, *pPal); } -Bitmap::Bitmap(const BitmapEx& rBitmapEx) - : maPrefMapMode(rBitmapEx.GetPrefMapMode()) - , maPrefSize(rBitmapEx.GetPrefSize()) +static Bitmap createBitmapFromColorAndAlpha(const Bitmap& rColorBitmap, const Bitmap& rAlphaBitmap) { - if (!rBitmapEx.IsAlpha()) - mxSalBmp = rBitmapEx.GetBitmap().mxSalBmp; + if (rAlphaBitmap.IsEmpty()) + return rColorBitmap; else { - Size aSize = rBitmapEx.GetSizePixel(); + Size aSize = rColorBitmap.GetSizePixel(); static const BitmapPalette aPalEmpty; - mxSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap(); - const bool bSuccess = mxSalBmp->Create(aSize, vcl::PixelFormat::N32_BPP, aPalEmpty); + std::shared_ptr<SalBitmap> xSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap(); + const bool bSuccess = xSalBmp->Create(aSize, vcl::PixelFormat::N32_BPP, aPalEmpty); if (!bSuccess) { SAL_WARN("vcl", "Bitmap::Bitmap(): could not create image"); - return; + return Bitmap(xSalBmp); } - BitmapScopedReadAccess pReadColorAcc(rBitmapEx.GetBitmap()); - BitmapScopedReadAccess pReadAlphaAcc(rBitmapEx.GetAlphaMask()); - BitmapScopedWriteAccess pWriteAcc(*this); + Bitmap aRetBmp(xSalBmp); + BitmapScopedReadAccess pReadColorAcc(rColorBitmap); + BitmapScopedReadAccess pReadAlphaAcc(rAlphaBitmap); + BitmapScopedWriteAccess pWriteAcc(aRetBmp); auto nHeight = pReadColorAcc->Height(); auto nWidth = pReadColorAcc->Width(); bool bPalette = pReadColorAcc->HasPalette(); @@ -182,6 +180,7 @@ Bitmap::Bitmap(const BitmapEx& rBitmapEx) pWriteAcc->SetPixelOnData(pScanlineWrite, nX, aCol); } } + return aRetBmp; // So.... in theory the following code should work, and be much more efficient. In practice, the gen/cairo // code is doing something weird involving masks that results in alpha not doing the same thing as on the other @@ -227,23 +226,73 @@ void Bitmap::loadFromIconTheme( const OUString& rIconName ) bSuccess = false; } - SAL_WARN_IF( !bSuccess, "vcl", "BitmapEx::BitmapEx(): could not load image " << rIconName << " via icon theme " << aIconTheme); + SAL_WARN_IF( !bSuccess, "vcl", "Bitmap::Bitmap(): could not load image " << rIconName << " via icon theme " << aIconTheme); } Bitmap::Bitmap( const Bitmap& rBmp, const Bitmap& rMask ) { - *this = Bitmap(BitmapEx(rBmp, rMask)); + if (rMask.IsEmpty()) + { + *this = rBmp; + return; + } + + assert(typeid(rMask) != typeid(AlphaMask) + && "If this mask is actually an AlphaMask, then it will be inverted unnecessarily " + "and the alpha channel will be wrong"); + + AlphaMask aAlphaMask; + if( rMask.getPixelFormat() == vcl::PixelFormat::N8_BPP && rMask.HasGreyPalette8Bit() ) + { + aAlphaMask = rMask; + aAlphaMask.Invert(); + } + else if( rMask.getPixelFormat() == vcl::PixelFormat::N8_BPP ) + { + Bitmap aMask(rMask); + BitmapFilter::Filter(aMask, BitmapMonochromeFilter(255)); + aMask.Invert(); + aAlphaMask = aMask; + } + else + { + // convert to alpha bitmap + SAL_WARN("vcl", "Bitmap: forced mask to monochrome"); + Bitmap aMask(rMask); + BitmapFilter::Filter(aMask, BitmapMonochromeFilter(255)); + aMask.Invert(); + aAlphaMask = aMask; + } + + if (!rBmp.IsEmpty() && rBmp.GetSizePixel() != aAlphaMask.GetSizePixel()) + { + SAL_WARN("vcl", "Mask size differs from Bitmap size, corrected Mask (!)"); + aAlphaMask.Scale(rBmp.GetSizePixel(), BmpScaleFlag::Fast); + } + *this = createBitmapFromColorAndAlpha(rBmp, aAlphaMask.GetBitmap()); } Bitmap::Bitmap( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) { - *this = Bitmap(BitmapEx(rBmp, rAlphaMask)); + if (!rBmp.IsEmpty() && !rAlphaMask.IsEmpty() && rBmp.GetSizePixel() != rAlphaMask.GetSizePixel()) + { + SAL_WARN("vcl", "Alpha size differs from Bitmap size, corrected Mask (!)"); + AlphaMask aNewMask = rAlphaMask; + aNewMask.Scale(rBmp.GetSizePixel(), BmpScaleFlag::Fast); + *this = createBitmapFromColorAndAlpha(rBmp, aNewMask.GetBitmap()); + } + else + *this = createBitmapFromColorAndAlpha(rBmp, rAlphaMask.GetBitmap()); } Bitmap::Bitmap( const Bitmap& rBmp, const Color& rTransparentColor ) { - *this = Bitmap(BitmapEx(rBmp, rTransparentColor)); + AlphaMask aAlphaMask = rBmp.CreateAlphaMask( rTransparentColor ); + + SAL_WARN_IF(rBmp.GetSizePixel() != aAlphaMask.GetSizePixel(), "vcl", + "Bitmap::Bitmap(): size mismatch for bitmap and alpha mask."); + *this = createBitmapFromColorAndAlpha(rBmp, aAlphaMask.GetBitmap()); } @@ -2051,7 +2100,7 @@ Bitmap Bitmap::Modify(const basegfx::BColorModifierStack& rBColorModifierStack) { // at the top of the stack we have a BColorModifier_replace -> no Bitmap needed, // representation can be replaced by filled colored polygon. signal the caller - // about that by returning empty BitmapEx + // about that by returning empty Bitmap return Bitmap(); } @@ -2109,7 +2158,7 @@ Bitmap Bitmap::Modify(const basegfx::BColorModifierStack& rBColorModifierStack) AlphaMask aAlphaMask(CreateAlphaMask()); Bitmap aTmpBitmap(CreateColorBitmap()); aTmpBitmap.Erase(Color(pLastModifierReplace->getBColor())); - aChangedBitmap = Bitmap(BitmapEx(aTmpBitmap, aAlphaMask)); + aChangedBitmap = createBitmapFromColorAndAlpha(aTmpBitmap, aAlphaMask.GetBitmap()); } else { @@ -2205,7 +2254,7 @@ Bitmap Bitmap::Modify(const basegfx::BColorModifierStack& rBColorModifierStack) if (nullptr != pHolder) { - // create new BufferedData_ModifiedBitmapEx (should be nullptr here) + // create new BufferedData_ModifiedBitmap (should be nullptr here) if (nullptr == pBufferedData_ModifiedBitmap) { pBufferedData_ModifiedBitmap = std::make_shared<BufferedData_ModifiedBitmap>(aChangedBitmap, rBColorModifierStack); @@ -2236,14 +2285,16 @@ AlphaMask Bitmap::CreateAlphaMask() const assert(HasAlpha()); if (!HasAlpha()) return AlphaMask(); - return BitmapEx(*this).GetAlphaMask(); + std::pair<Bitmap, AlphaMask> aPair = SplitIntoColorAndAlpha(); + return aPair.second; } Bitmap Bitmap::CreateColorBitmap() const { if (!HasAlpha()) return *this; - return BitmapEx(*this).GetBitmap(); + std::pair<Bitmap, AlphaMask> aPair = SplitIntoColorAndAlpha(); + return aPair.first; } void Bitmap::ChangeColorAlpha( sal_uInt8 cIndexFrom, sal_Int8 nAlphaTo ) @@ -2278,8 +2329,7 @@ void Bitmap::AdjustTransparency(sal_uInt8 cTrans) if (!HasAlpha()) { AlphaMask aAlpha(GetSizePixel(), &cTrans); - BitmapEx aNew( *this, aAlpha ); - *this = Bitmap(aNew); + *this = createBitmapFromColorAndAlpha(*this, aAlpha.GetBitmap()); } else { @@ -2344,7 +2394,7 @@ void Bitmap::BlendAlpha(sal_uInt8 nAlpha) if (!HasAlpha()) { sal_uInt8 cTrans = 255 - nAlpha; - *this = Bitmap(BitmapEx( *this, AlphaMask(GetSizePixel(), &cTrans) )); + *this = createBitmapFromColorAndAlpha( *this, AlphaMask(GetSizePixel(), &cTrans).GetBitmap() ); } else { @@ -2474,7 +2524,7 @@ void Bitmap::CombineMaskOr(Color rTransColor, sal_uInt8 nTol) const MapMode aMap( maPrefMapMode ); const Size aSize( maPrefSize ); - *this = Bitmap(BitmapEx(aColBmp, aNewMask)); + *this = createBitmapFromColorAndAlpha(aColBmp, aNewMask.GetBitmap()); maPrefMapMode = aMap; maPrefSize = aSize;
