From 03b2f7c15093ada5c6140960aa87531d4391b2b0 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Mon, 19 Apr 2021 16:07:23 +0200 Subject: BitmapEx: always convert 1-bit mask to alpha which is a step towards dropping masks, and only using alpha. Change-Id: I6882c0e5b1c805b0cda5a2eaadcbdd078d8566c6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114622 Tested-by: Jenkins Reviewed-by: Noel Grandin --- vcl/Library_vcl.mk | 1 + vcl/inc/bitmap/BitmapMaskToAlphaFilter.hxx | 21 ++++++++++ vcl/qa/cppunit/GraphicTest.cxx | 6 +-- vcl/qa/cppunit/TypeSerializerTest.cxx | 4 +- vcl/source/bitmap/BitmapEx.cxx | 26 ++++++++---- vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx | 58 +++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 vcl/inc/bitmap/BitmapMaskToAlphaFilter.hxx create mode 100644 vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx (limited to 'vcl') diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 998eed0e0766..0c4cb6e65864 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -352,6 +352,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/bitmap/BitmapShadowFilter \ vcl/source/bitmap/BitmapAlphaClampFilter \ vcl/source/bitmap/BitmapBasicMorphologyFilter \ + vcl/source/bitmap/BitmapMaskToAlphaFilter \ vcl/source/bitmap/BitmapMonochromeFilter \ vcl/source/bitmap/BitmapSmoothenFilter \ vcl/source/bitmap/BitmapLightenFilter \ diff --git a/vcl/inc/bitmap/BitmapMaskToAlphaFilter.hxx b/vcl/inc/bitmap/BitmapMaskToAlphaFilter.hxx new file mode 100644 index 000000000000..355d066846c1 --- /dev/null +++ b/vcl/inc/bitmap/BitmapMaskToAlphaFilter.hxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include + +class BitmapMaskToAlphaFilter final : public BitmapFilter +{ +public: + virtual BitmapEx execute(BitmapEx const& rBitmapEx) const override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx index 0f670a4fee36..608c5f4de85d 100644 --- a/vcl/qa/cppunit/GraphicTest.cxx +++ b/vcl/qa/cppunit/GraphicTest.cxx @@ -1072,7 +1072,7 @@ void GraphicTest::testSwappingAnimationGraphic_GIF_WithGfxLink() // Get the declared byte size of the graphic sal_uLong rByteSize = aGraphic.GetSizeBytes(); - CPPUNIT_ASSERT_EQUAL(sal_uLong(50373), rByteSize); + CPPUNIT_ASSERT_EQUAL(sal_uLong(89552), rByteSize); // Make sure we don't have a file CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->getSwapFileURL().isEmpty()); @@ -1148,10 +1148,10 @@ void GraphicTest::testSwappingAnimationGraphic_GIF_WithoutGfxLink() CPPUNIT_ASSERT_EQUAL(true, bool(xStream)); // Check size of the stream - CPPUNIT_ASSERT_EQUAL(sal_uInt64(15183), xStream->remainingSize()); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(15139), xStream->remainingSize()); std::vector aHash = calculateHash(xStream); - CPPUNIT_ASSERT_EQUAL(std::string("deb13fdf0ffa0b58ce92fff0a6ca9e98c5d26ed9"), + CPPUNIT_ASSERT_EQUAL(std::string("ecae5354edd9cf98553eb3153e44181f56d35338"), toHexString(aHash)); } diff --git a/vcl/qa/cppunit/TypeSerializerTest.cxx b/vcl/qa/cppunit/TypeSerializerTest.cxx index 5d7b72b0f560..1c7b93d25a62 100644 --- a/vcl/qa/cppunit/TypeSerializerTest.cxx +++ b/vcl/qa/cppunit/TypeSerializerTest.cxx @@ -248,9 +248,9 @@ void TypeSerializerTest::testGraphic_Animation() } aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); - CPPUNIT_ASSERT_EQUAL(sal_uInt64(15167), aMemoryStream.remainingSize()); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(15123), aMemoryStream.remainingSize()); std::vector aHash = calculateHash(aMemoryStream); - CPPUNIT_ASSERT_EQUAL(std::string("69d0f80832a0aebcbda7ad43ecadf85e99fc1057"), + CPPUNIT_ASSERT_EQUAL(std::string("86e02d37ab5e9c96fbeda717f62bc6e35dec3a70"), toHexString(aHash)); aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); diff --git a/vcl/source/bitmap/BitmapEx.cxx b/vcl/source/bitmap/BitmapEx.cxx index 7ff6af59f776..bcf8480163cc 100644 --- a/vcl/source/bitmap/BitmapEx.cxx +++ b/vcl/source/bitmap/BitmapEx.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -123,20 +124,31 @@ BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) : maMask ( rMask ), maBitmapSize ( maBitmap.GetSizePixel() ), meTransparent ( rMask.IsEmpty() ? TransparentType::NONE : TransparentType::Bitmap ), - mbAlpha ( false ) + mbAlpha ( !rMask.IsEmpty() ) { - // Ensure a mask is exactly one bit deep, - // alternatively also allow 8bpp masks. - if (!maMask.IsEmpty() && maMask.getPixelFormat() != vcl::PixelFormat::N1_BPP - && !(maMask.getPixelFormat() == vcl::PixelFormat::N8_BPP && maMask.HasGreyPalette8Bit())) + if (rMask.IsEmpty()) + return; + + if( maMask.getPixelFormat() == vcl::PixelFormat::N8_BPP && maMask.HasGreyPalette8Bit() ) + maMask = rMask; + else if (maMask.getPixelFormat() == vcl::PixelFormat::N1_BPP) + { + // convert 1-bit mask to alpha bitmap + BitmapEx aBmpEx(rMask); + BitmapFilter::Filter(aBmpEx, BitmapMaskToAlphaFilter()); + maMask = aBmpEx.GetBitmap(); + } + else { + // convert to alpha bitmap SAL_WARN( "vcl", "BitmapEx: forced mask to monochrome"); - BitmapEx aMaskEx(maMask); + BitmapEx aMaskEx(rMask); BitmapFilter::Filter(aMaskEx, BitmapMonochromeFilter(255)); + BitmapFilter::Filter(aMaskEx, BitmapMaskToAlphaFilter()); maMask = aMaskEx.GetBitmap(); } - if (!maBitmap.IsEmpty() && !maMask.IsEmpty() && maBitmap.GetSizePixel() != maMask.GetSizePixel()) + if (!maBitmap.IsEmpty() && maBitmap.GetSizePixel() != maMask.GetSizePixel()) { OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)"); maMask.Scale(maBitmap.GetSizePixel()); diff --git a/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx b/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx new file mode 100644 index 000000000000..3ccca0ebd90b --- /dev/null +++ b/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include + +#include +#include + +/** + * Convert a 1-bit mask to an alpha layer + */ +BitmapEx BitmapMaskToAlphaFilter::execute(BitmapEx const& rBitmapEx) const +{ + const Size aSize(rBitmapEx.GetSizePixel()); + + Bitmap aBitmap(rBitmapEx.GetBitmap()); + Bitmap aOutBitmap(aSize, vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256)); + + Bitmap::ScopedReadAccess pRead(aBitmap); + BitmapScopedWriteAccess pWrite(aOutBitmap); + + if (pRead && pWrite) + { + assert(pRead->HasPalette() && "only supposed to be called with 1-bit mask"); + assert(pRead->GetPaletteEntryCount() == 2); + for (tools::Long nY = 0; nY < aSize.Height(); ++nY) + { + Scanline pScanline = pWrite->GetScanline(nY); + Scanline pScanlineRead = pRead->GetScanline(nY); + for (tools::Long nX = 0; nX < aSize.Width(); ++nX) + { + BitmapColor aBmpColor = pRead->GetPixelFromData(pScanlineRead, nX); + if (aBmpColor == COL_BLACK) + aBmpColor = COL_BLACK; + else if (aBmpColor == COL_WHITE) + aBmpColor = COL_WHITE; + else if (aBmpColor == Color(0, 0, 1)) + aBmpColor = COL_WHITE; + else + assert(false); + pWrite->SetPixelOnData(pScanline, nX, aBmpColor); + } + } + } + pWrite.reset(); + pRead.reset(); + + return BitmapEx(aOutBitmap); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit