canvas/source/directx/dx_canvasbitmap.cxx                     |    2 
 canvas/source/directx/dx_vcltools.cxx                         |   18 
 canvas/source/vcl/canvasbitmaphelper.cxx                      |    2 
 cppcanvas/source/mtfrenderer/transparencygroupaction.cxx      |    2 
 cui/source/dialogs/about.cxx                                  |   26 -
 drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx   |    6 
 drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx |    1 
 drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx       |    2 
 drawinglayer/source/processor2d/vclhelperbufferdevice.cxx     |    1 
 drawinglayer/source/tools/converters.cxx                      |   27 -
 forms/source/component/imgprod.cxx                            |    4 
 include/tools/color.hxx                                       |    4 
 include/vcl/bitmap.hxx                                        |   31 +
 include/vcl/virdev.hxx                                        |    4 
 sd/qa/unit/PNGExportTests.cxx                                 |    2 
 sfx2/source/dialog/infobar.cxx                                |    2 
 slideshow/source/engine/shapes/gdimtftools.cxx                |    6 
 svx/source/svdraw/svdfmtf.cxx                                 |    5 
 toolkit/source/helper/vclunohelper.cxx                        |    1 
 vcl/backendtest/outputdevice/bitmap.cxx                       |    8 
 vcl/headless/BitmapHelper.cxx                                 |   14 
 vcl/headless/CairoCommon.cxx                                  |   15 
 vcl/inc/bitmap/ScanlineTools.hxx                              |    4 
 vcl/inc/headless/BitmapHelper.hxx                             |    3 
 vcl/inc/headless/CairoCommon.hxx                              |    2 
 vcl/qa/cppunit/BackendTest.cxx                                |    2 
 vcl/qa/cppunit/BitmapExTest.cxx                               |    3 
 vcl/qa/cppunit/ScanlineToolsTest.cxx                          |   10 
 vcl/qa/cppunit/canvasbitmaptest.cxx                           |   28 -
 vcl/qa/cppunit/png/PngFilterTest.cxx                          |   32 -
 vcl/qa/cppunit/skia/skia.cxx                                  |    6 
 vcl/qa/cppunit/svm/svmtest.cxx                                |   21 
 vcl/qt5/QtGraphics_GDI.cxx                                    |    1 
 vcl/quartz/cgutils.mm                                         |   47 +-
 vcl/skia/gdiimpl.cxx                                          |   31 -
 vcl/skia/salbmp.cxx                                           |   26 -
 vcl/source/bitmap/BitmapAlphaClampFilter.cxx                  |    4 
 vcl/source/bitmap/BitmapEx.cxx                                |   48 +-
 vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx                 |    8 
 vcl/source/bitmap/BitmapTools.cxx                             |   43 +
 vcl/source/bitmap/alpha.cxx                                   |   33 +
 vcl/source/bitmap/bitmappaint.cxx                             |  235 ++++++++--
 vcl/source/bitmap/dibtools.cxx                                |   11 
 vcl/source/filter/eps/eps.cxx                                 |    8 
 vcl/source/filter/igif/gifread.cxx                            |    4 
 vcl/source/filter/ipdf/pdfread.cxx                            |    3 
 vcl/source/filter/ipsd/ipsd.cxx                               |    4 
 vcl/source/filter/itiff/itiff.cxx                             |    2 
 vcl/source/filter/jpeg/JpegReader.cxx                         |    6 
 vcl/source/filter/jpeg/JpegReader.hxx                         |    2 
 vcl/source/filter/png/PngImageReader.cxx                      |    5 
 vcl/source/filter/png/PngImageWriter.cxx                      |    8 
 vcl/source/filter/wmf/emfwr.cxx                               |    3 
 vcl/source/filter/wmf/wmfwr.cxx                               |    3 
 vcl/source/gdi/gdimtf.cxx                                     |    2 
 vcl/source/gdi/pdfwriter_impl2.cxx                            |   89 ++-
 vcl/source/gdi/virdev.cxx                                     |   18 
 vcl/source/graphic/GraphicObject2.cxx                         |    4 
 vcl/source/graphic/UnoGraphic.cxx                             |    2 
 vcl/source/helper/canvasbitmap.cxx                            |   16 
 vcl/source/helper/canvastools.cxx                             |    4 
 vcl/source/image/ImplImage.cxx                                |   11 
 vcl/source/opengl/OpenGLHelper.cxx                            |    2 
 vcl/source/outdev/background.cxx                              |    8 
 vcl/source/outdev/bitmap.cxx                                  |   15 
 vcl/source/outdev/bitmapex.cxx                                |    6 
 vcl/source/outdev/fill.cxx                                    |    2 
 vcl/source/outdev/font.cxx                                    |    2 
 vcl/source/outdev/gradient.cxx                                |    2 
 vcl/source/outdev/line.cxx                                    |    2 
 vcl/source/outdev/pixel.cxx                                   |    4 
 vcl/source/outdev/text.cxx                                    |    4 
 vcl/source/outdev/textline.cxx                                |    4 
 vcl/source/outdev/transparent.cxx                             |   43 +
 vcl/source/rendercontext/drawmode.cxx                         |    2 
 vcl/win/gdi/salbmp.cxx                                        |    2 
 76 files changed, 703 insertions(+), 370 deletions(-)

New commits:
commit 81994cb2b8b32453a92bcb011830fcb884f22ff3
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Fri Apr 16 20:33:10 2021 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Tue Jul 25 08:38:12 2023 +0200

    Convert internal vcl bitmap formats transparency->alpha (II)
    
    (Second attempt at landing this)
    
    Image formats and graphics APIs use alpha, not transparency,
    so change our internal formats and data structures to work directly
    with alpha, so we don't need to modify data before we push it to
    graphics APIs.
    
    Add a couple of new Color constants to make the intention
    of the vcl code clearer.
    
    Notes
    (*) On macOS, tweaking the logic in CreateWithSalBitmapAndMask
    to more accurately reflect the requirements of the
    CGImageCreateWithMask function seems to fix some
    tests.
    
    (*) The vcl code does not properly support gradients
    with transparency. So the previous code was wrong, and this
    change is going to result in slightly different wrongness.
    
    Change-Id: I9e21c2e98d88ecfdc5f75db13bd1ffff7c38db98
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114168
    Tested-by: Jenkins
    Reviewed-by: Patrick Luby <plub...@neooffice.org>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/canvas/source/directx/dx_canvasbitmap.cxx 
b/canvas/source/directx/dx_canvasbitmap.cxx
index 33dc7859fadb..fb06288ada86 100644
--- a/canvas/source/directx/dx_canvasbitmap.cxx
+++ b/canvas/source/directx/dx_canvasbitmap.cxx
@@ -214,7 +214,7 @@ namespace dxcanvas
                         sal_uInt8* pOutBits=pAlphaBits.get()+y*nScanWidth;
                         for( sal_Int32 x=0; x<aSize.getWidth(); ++x )
                         {
-                            *pOutBits++ = 255-*pInBits;
+                            *pOutBits++ = *pInBits;
                             pInBits += 4;
                         }
                     }
diff --git a/canvas/source/directx/dx_vcltools.cxx 
b/canvas/source/directx/dx_vcltools.cxx
index 456f22386dd1..fb5e5c5e93db 100644
--- a/canvas/source/directx/dx_vcltools.cxx
+++ b/canvas/source/directx/dx_vcltools.cxx
@@ -211,11 +211,7 @@ namespace dxcanvas::tools
                                     *pCurrOutput++ = aCol.GetBlue();
                                     *pCurrOutput++ = aCol.GetGreen();
                                     *pCurrOutput++ = aCol.GetRed();
-
-                                    // our notion of alpha is
-                                    // different from the rest
-                                    // of the world's
-                                    *pCurrOutput++ = 255 - 
static_cast<BYTE>(*pAScan++);
+                                    *pCurrOutput++ = 
static_cast<BYTE>(*pAScan++);
                                 }
                             }
                             break;
@@ -231,11 +227,7 @@ namespace dxcanvas::tools
                                     *pCurrOutput++ = *pScan++;
                                     *pCurrOutput++ = *pScan++;
                                     *pCurrOutput++ = *pScan++;
-
-                                    // our notion of alpha is
-                                    // different from the rest
-                                    // of the world's
-                                    *pCurrOutput++ = 255 - 
static_cast<BYTE>(*pAScan++);
+                                    *pCurrOutput++ = 
static_cast<BYTE>(*pAScan++);
                                 }
                             }
                             break;
@@ -258,11 +250,7 @@ namespace dxcanvas::tools
                                     *pCurrOutput++ = aCol.GetBlue();
                                     *pCurrOutput++ = aCol.GetGreen();
                                     *pCurrOutput++ = aCol.GetRed();
-
-                                    // our notion of alpha is
-                                    // different from the rest
-                                    // of the world's
-                                    *pCurrOutput++ = 255 - 
static_cast<BYTE>(*pAScan++);
+                                    *pCurrOutput++ = 
static_cast<BYTE>(*pAScan++);
                                 }
                             }
                             break;
diff --git a/canvas/source/vcl/canvasbitmaphelper.cxx 
b/canvas/source/vcl/canvasbitmaphelper.cxx
index cd33b266346d..99b9831cabf6 100644
--- a/canvas/source/vcl/canvasbitmaphelper.cxx
+++ b/canvas/source/vcl/canvasbitmaphelper.cxx
@@ -146,7 +146,7 @@ namespace vclcanvas
         pRes[ 0 ] = aColor.GetRed();
         pRes[ 1 ] = aColor.GetGreen();
         pRes[ 2 ] = aColor.GetBlue();
-        pRes[ 3 ] = 255 - aColor.GetAlpha();
+        pRes[ 3 ] = aColor.GetAlpha();
 
         return aRes;
     }
diff --git a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx 
b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx
index 35a2b45fd7bd..b8350a8f3944 100644
--- a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx
+++ b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx
@@ -229,7 +229,7 @@ namespace cppcanvas::internal
                     // VirtualDevice with alpha channel
                     ScopedVclPtrInstance<VirtualDevice> aVDev(
                         *::Application::GetDefaultDevice(), 
DeviceFormat::WITH_ALPHA );
-                    aVDev->SetOutputSizePixel( aBitmapSizePixel );
+                    aVDev->SetOutputSizePixel( aBitmapSizePixel, true, true );
                     aVDev->SetMapMode();
 
                     if( rSubset.mnSubsetBegin != 0 ||
diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx
index 41d17b2a06d5..ce82e418cf9e 100644
--- a/cui/source/dialogs/about.cxx
+++ b/cui/source/dialogs/about.cxx
@@ -26,9 +26,9 @@
 #include <osl/process.h>     //osl_getProcessLocale
 #include <rtl/bootstrap.hxx>
 #include <sal/log.hxx>       //SAL_WARN
+#include <vcl/graph.hxx>     //Graphic
 #include <vcl/settings.hxx>  //GetSettings
 #include <vcl/svapp.hxx>     //Application::
-#include <vcl/virdev.hxx>    //VirtualDevice
 #include <vcl/weld.hxx>
 #include <unotools/resmgr.hxx> //Translate
 
@@ -105,20 +105,20 @@ AboutDialog::AboutDialog(weld::Window *pParent)
                                        ? "shell/logo_inverted"
                                        : "shell/logo",
                                    aBackgroundBitmap, nWidth * 0.8)) {
-    ScopedVclPtr<VirtualDevice> m_pVirDev =
-        m_pBrandImage->create_virtual_device();
-    m_pVirDev->SetOutputSizePixel(aBackgroundBitmap.GetSizePixel());
-    m_pVirDev->DrawBitmapEx(Point(0, 0), aBackgroundBitmap);
-    m_pBrandImage->set_image(m_pVirDev.get());
-    m_pVirDev.disposeAndClear();
+    // Eliminate white background when Skia is disabled by not drawing the
+    // background bitmap to a VirtualDevice. On most platforms, non-Skia
+    // VirtualDevices will be filled with a solid color when drawing
+    // the bitmap.
+    Graphic aGraphic(aBackgroundBitmap);
+    m_pBrandImage->set_image(aGraphic.GetXGraphic());
   }
   if (SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, nWidth * 
0.9)) {
-    ScopedVclPtr<VirtualDevice> m_pVirDev =
-        m_pAboutImage->create_virtual_device();
-    m_pVirDev->SetOutputSizePixel(aBackgroundBitmap.GetSizePixel());
-    m_pVirDev->DrawBitmapEx(Point(0, 0), aBackgroundBitmap);
-    m_pAboutImage->set_image(m_pVirDev.get());
-    m_pVirDev.disposeAndClear();
+    // Eliminate white background when Skia is disabled by not drawing the
+    // background bitmap to a VirtualDevice. On most platforms, non-Skia
+    // VirtualDevices will be filled with a solid color when drawing
+    // the bitmap.
+    Graphic aGraphic(aBackgroundBitmap);
+    m_pAboutImage->set_image(aGraphic.GetXGraphic());
   }
 
   // Links
diff --git a/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx 
b/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx
index 3c45fdd030f4..9bbdf7176935 100644
--- a/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx
+++ b/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx
@@ -58,10 +58,10 @@ AlphaMask ProcessAndBlurAlphaMask(const Bitmap& rMask, 
double fErodeDilateRadius
     else if (fErodeDilateRadius < 0)
         BitmapFilter::Filter(mask, BitmapErodeFilter(-fErodeDilateRadius, 
0xFF));
 
-    if (nTransparency)
+    if (nTransparency != 255)
     {
         const Color aTransparency(nTransparency, nTransparency, nTransparency);
-        mask.Replace(COL_BLACK, aTransparency);
+        mask.Replace(COL_WHITE, aTransparency);
     }
 
     // We need 8-bit grey mask for blurring
@@ -72,6 +72,8 @@ AlphaMask ProcessAndBlurAlphaMask(const Bitmap& rMask, double 
fErodeDilateRadius
 
     mask.Scale(rMask.GetSizePixel());
 
+    mask.Invert(); // convert transparency to alpha
+
     return AlphaMask(mask.GetBitmap());
 }
 
diff --git a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx 
b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx
index 4a64da368a2f..89c4335bb0b3 100644
--- a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx
@@ -32,6 +32,7 @@ namespace drawinglayer::primitive2d
         DiscreteShadow::DiscreteShadow(const BitmapEx& rBitmapEx)
         :   maBitmapEx(rBitmapEx)
         {
+            maBitmapEx.Invert(); // convert transparency to alpha
             const Size& rBitmapSize = getBitmapEx().GetSizePixel();
 
             if(rBitmapSize.Width() != rBitmapSize.Height() || 
rBitmapSize.Width() < 7)
diff --git a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
index 783060c2be4c..7671e0c29a05 100644
--- a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
@@ -410,7 +410,7 @@ sal::systools::COMReference<ID2D1Bitmap> 
createB2DBitmap(const BitmapEx& rBitmap
             {
                 const BitmapColor aColor(pReadAccess->GetColor(y, x));
                 const BitmapColor aAlpha(pAlphaReadAccess->GetColor(y, x));
-                const sal_uInt16 nAlpha(255 - aAlpha.GetRed());
+                const sal_uInt16 nAlpha(aAlpha.GetRed());
 
                 *pTarget++ = sal_uInt32(BitmapColor(
                     ColorAlpha, sal_uInt8((sal_uInt16(aColor.GetRed()) * 
nAlpha) >> 8),
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx 
b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
index c76225194dd7..f90049bf8773 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -476,6 +476,7 @@ void impBufferDevice::paint(double fTrans)
     {
         mpAlpha->EnableMapMode(false);
         AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel));
+        aAlphaMask.Invert(); // convert transparency to alpha
 
 #ifdef DBG_UTIL
         if (!sDumpPath.isEmpty() && bDoSaveForVisualControl)
diff --git a/drawinglayer/source/tools/converters.cxx 
b/drawinglayer/source/tools/converters.cxx
index 001019cd9623..80ae15a3b6a9 100644
--- a/drawinglayer/source/tools/converters.cxx
+++ b/drawinglayer/source/tools/converters.cxx
@@ -95,7 +95,7 @@ AlphaMask 
implcreateAlphaMask(drawinglayer::primitive2d::Primitive2DContainer& r
     // prepare for mask creation
     pContent->SetMapMode(MapMode(MapUnit::MapPixel));
 
-    // set alpha to all white (fully transparent)
+    // set transparency to all white (fully transparent)
     pContent->Erase();
 
     basegfx::BColorModifierSharedPtr aBColorModifier;
@@ -107,7 +107,7 @@ AlphaMask 
implcreateAlphaMask(drawinglayer::primitive2d::Primitive2DContainer& r
     }
     else
     {
-        // Embed primitives to paint them black
+        // Embed primitives to paint them black (fully opaque)
         aBColorModifier
             = 
std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0.0, 0.0, 
0.0));
     }
@@ -123,7 +123,14 @@ AlphaMask 
implcreateAlphaMask(drawinglayer::primitive2d::Primitive2DContainer& r
     // get alpha channel from vdev
     pContent->EnableMapMode(false);
     const Point aEmptyPoint;
-    return AlphaMask(pContent->GetBitmap(aEmptyPoint, rSizePixel));
+
+    // Convert from transparency->alpha.
+    // FIXME in theory I should be able to directly construct alpha by using 
black as background
+    // and white as foreground, but that doesn't work for some reason.
+    Bitmap aContentBitmap = pContent->GetBitmap(aEmptyPoint, rSizePixel);
+    aContentBitmap.Invert();
+
+    return AlphaMask(aContentBitmap);
 }
 }
 
@@ -257,12 +264,16 @@ BitmapEx 
convertToBitmapEx(drawinglayer::primitive2d::Primitive2DContainer&& rSe
     if (aAlpha.hasAlpha())
     {
         // Need to correct content using known alpha to get to background-free
-        // RGBA result, usable e.g. in PNG export(s) or convert-to-bitmap
-        aRetval.RemoveBlendedStartColor(COL_WHITE, aAlpha);
+        // RGBA result, usable e.g. in PNG export(s) or convert-to-bitmap.
+        // Now that vcl supports bitmaps with an alpha channel, only apply
+        // this correction to bitmaps without an alpha channel.
+        if (pContent->GetBitCount() < 32)
+            aRetval.RemoveBlendedStartColor(COL_WHITE, aAlpha);
+        // return combined result
+        return BitmapEx(aRetval, aAlpha);
     }
-
-    // return combined result
-    return BitmapEx(aRetval, aAlpha);
+    else
+        return BitmapEx(aRetval);
 }
 
 BitmapEx 
convertPrimitive2DContainerToBitmapEx(primitive2d::Primitive2DContainer&& 
rSequence,
diff --git a/forms/source/component/imgprod.cxx 
b/forms/source/component/imgprod.cxx
index 46439682519f..3f2e6bfdee5b 100644
--- a/forms/source/component/imgprod.cxx
+++ b/forms/source/component/imgprod.cxx
@@ -379,7 +379,7 @@ void ImageProducer::ImplUpdateConsumer( const Graphic& 
rGraphic )
 
     if( !pMskAcc )
     {
-        aMask = Bitmap(aBmp.GetSizePixel(), vcl::PixelFormat::N8_BPP, 
&Bitmap::GetGreyPalette(256));
+        aMask = AlphaMask(aBmp.GetSizePixel());
         aMask.Erase( 0 );
         pMskAcc = aMask.AcquireReadAccess();
     }
@@ -389,7 +389,7 @@ void ImageProducer::ImplUpdateConsumer( const Graphic& 
rGraphic )
 
     if( pBmpAcc->HasPalette() )
     {
-        const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( COL_WHITE ) );
+        const BitmapColor aWhite( pMskAcc->GetBestMatchingColor( 
COL_ALPHA_TRANSPARENT ) );
 
         if( mnTransIndex < 256 )
         {
diff --git a/include/tools/color.hxx b/include/tools/color.hxx
index 41826ec2335f..c3bbb5bf0e2b 100644
--- a/include/tools/color.hxx
+++ b/include/tools/color.hxx
@@ -449,6 +449,10 @@ static_assert (sal_uInt32(Color(0x12, 0x34, 0x56)) == 
0x00123456);
 
 inline constexpr ::Color COL_TRANSPARENT             ( ColorTransparency, 
0xFF, 0xFF, 0xFF, 0xFF );
 inline constexpr ::Color COL_AUTO                    ( ColorTransparency, 
0xFF, 0xFF, 0xFF, 0xFF );
+// These are used when drawing to the separate alpha channel we use in vcl
+inline constexpr ::Color COL_ALPHA_TRANSPARENT       ( 0x00, 0x00, 0x00 );
+inline constexpr ::Color COL_ALPHA_OPAQUE            ( 0xff, 0xff, 0xff );
+
 inline constexpr ::Color COL_BLACK                   ( 0x00, 0x00, 0x00 );
 inline constexpr ::Color COL_BLUE                    ( 0x00, 0x00, 0x80 );
 inline constexpr ::Color COL_GREEN                   ( 0x00, 0x80, 0x00 );
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index 0c794d496342..bc0d628179ca 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -374,6 +374,37 @@ public:
      */
     Bitmap                  CreateMask( const Color& rTransColor, sal_uInt8 
nTol ) const;
 
+    /** Create on-off alpha mask from bitmap
+
+        This method creates a bitmask from the bitmap, where every
+        pixel that equals rTransColor is set transparent, the rest
+        opaque.
+
+        @param rTransColor
+        Color value where the bitmask should be transparent
+
+        @return the resulting bitmask.
+     */
+    AlphaMask              CreateAlphaMask( const Color& rTransColor ) const;
+
+    /** Create on-off alpha mask from bitmap
+
+        This method creates a bitmask from the bitmap, where every
+        pixel that equals rTransColor is set transparent, the rest
+        opaque.
+
+        @param rTransColor
+        Color value where the bitmask should be transparent
+
+        @param nTol
+        Tolerance value. Specifies the maximal difference between
+        rTransColor and the individual pixel values, such that the
+        corresponding pixel is still regarded as transparent.
+
+        @return the resulting bitmask.
+     */
+    AlphaMask             CreateAlphaMask( const Color& rTransColor, sal_uInt8 
nTol ) const;
+
     /** Create region of similar colors in a given rectangle
 
         @param rColor
diff --git a/include/vcl/virdev.hxx b/include/vcl/virdev.hxx
index 0f6ec8ee1857..40cf445f0390 100644
--- a/include/vcl/virdev.hxx
+++ b/include/vcl/virdev.hxx
@@ -58,7 +58,7 @@ private:
     SAL_DLLPRIVATE bool InnerImplSetOutputSizePixel( const Size& rNewSize, 
bool bErase,
                                                      sal_uInt8* pBuffer );
     SAL_DLLPRIVATE bool ImplSetOutputSizePixel( const Size& rNewSize, bool 
bErase,
-                                                sal_uInt8* pBuffer );
+                                                sal_uInt8* pBuffer, bool 
bAlphaMaskTransparent = false );
 
     VirtualDevice (const VirtualDevice &) = delete;
     VirtualDevice & operator= (const VirtualDevice &) = delete;
@@ -124,7 +124,7 @@ public:
 
     virtual void        EnableRTL( bool bEnable = true ) override;
 
-    bool                SetOutputSizePixel( const Size& rNewSize, bool bErase 
= true );
+    bool                SetOutputSizePixel( const Size& rNewSize, bool bErase 
= true, bool bAlphaMaskTransparent = false );
     bool                SetOutputSizePixelScaleOffsetAndLOKBuffer( const Size& 
rNewSize,
                                                                    const 
Fraction& rScale,
                                                                    const 
Point& rNewOffset,
diff --git a/sd/qa/unit/PNGExportTests.cxx b/sd/qa/unit/PNGExportTests.cxx
index 5ca65f545dc2..58ec8d6077cc 100644
--- a/sd/qa/unit/PNGExportTests.cxx
+++ b/sd/qa/unit/PNGExportTests.cxx
@@ -295,7 +295,7 @@ CPPUNIT_TEST_FIXTURE(SdPNGExportTest, testTdf147119)
                 // - Expected: Color: R:255 G:255 B:255 A:0
                 // - Actual  : Color: R:0 G:0 B:0 A:0
                 const Color aColor = pReadAccess->GetColor(nY, nX);
-                CPPUNIT_ASSERT_EQUAL(COL_WHITE, aColor);
+                CPPUNIT_ASSERT_EQUAL(COL_ALPHA_TRANSPARENT, aColor);
             }
         }
     }
diff --git a/sfx2/source/dialog/infobar.cxx b/sfx2/source/dialog/infobar.cxx
index 81e8ffe9d864..778b5e9b140e 100644
--- a/sfx2/source/dialog/infobar.cxx
+++ b/sfx2/source/dialog/infobar.cxx
@@ -115,7 +115,7 @@ void SfxInfoBarWindow::SetCloseButtonImage()
     drawinglayer::primitive2d::Primitive2DContainer aSeq(2);
 
     // Draw backround. The right and bottom need to be extended by 1 or
-    // there will be a white line on both edges when Skia is enabled.
+    // there will be a white line on both edges.
     B2DPolygon aPolygon;
     aPolygon.append(B2DPoint(aRect.Left(), aRect.Top()));
     aPolygon.append(B2DPoint(aRect.Right() + 1, aRect.Top()));
diff --git a/slideshow/source/engine/shapes/gdimtftools.cxx 
b/slideshow/source/engine/shapes/gdimtftools.cxx
index 990d9d26caac..c5a215eefbc4 100644
--- a/slideshow/source/engine/shapes/gdimtftools.cxx
+++ b/slideshow/source/engine/shapes/gdimtftools.cxx
@@ -338,15 +338,15 @@ bool getAnimationFromGraphic( VectorOfMtfAnimationFrames& 
  o_rFrames,
         // extract current aVDev content into a new animation
         // frame
         GDIMetaFileSharedPtr pMtf = std::make_shared<GDIMetaFile>();
+        Bitmap aAlphaMask = pVDevMask->GetBitmap(aEmptyPoint, aAnimSize);
+        aAlphaMask.Invert(); // convert from transparency to alpha
         pMtf->AddAction(
             new MetaBmpExAction( aEmptyPoint,
                                  BitmapEx(
                                      pVDev->GetBitmap(
                                          aEmptyPoint,
                                          aAnimSize ),
-                                     pVDevMask->GetBitmap(
-                                         aEmptyPoint,
-                                         aAnimSize ))));
+                                     aAlphaMask)));
 
         // setup mtf dimensions and pref map mode (for
         // simplicity, keep it all in pixel. the metafile
diff --git a/svx/source/svdraw/svdfmtf.cxx b/svx/source/svdraw/svdfmtf.cxx
index 839fff3bdb15..923c40a550fa 100644
--- a/svx/source/svdraw/svdfmtf.cxx
+++ b/svx/source/svdraw/svdfmtf.cxx
@@ -1564,6 +1564,7 @@ void 
ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
         pVDev->DrawGradient(tools::Rectangle(Point(0, 0), 
pVDev->GetOutputSizePixel()), rGradient);
 
         aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), 
pVDev->GetOutputSizePixel()));
+        aNewMask.Invert(); // convert transparency to alpha
         bHasNewMask = true;
     }
 
@@ -1577,9 +1578,9 @@ void 
ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
             // no transparence yet, apply new one
             if(bFixedTransparence)
             {
-                sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
+                sal_uInt8 nTransparence(basegfx::fround(fTransparence * 
255.0));
 
-                aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), 
&aAlpha);
+                aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), 
&nTransparence);
             }
 
             aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
diff --git a/toolkit/source/helper/vclunohelper.cxx 
b/toolkit/source/helper/vclunohelper.cxx
index 45580c37cac8..9f05ae707065 100644
--- a/toolkit/source/helper/vclunohelper.cxx
+++ b/toolkit/source/helper/vclunohelper.cxx
@@ -89,6 +89,7 @@ BitmapEx VCLUnoHelper::GetBitmap( const css::uno::Reference< 
css::awt::XBitmap>&
                 SvMemoryStream aMem( aBytes.getArray(), aBytes.getLength(), 
StreamMode::READ );
                 ReadDIB(aMask, aMem, true);
             }
+            aMask.Invert(); // Convert from transparency to alpha
             aBmp = BitmapEx( aDIB, aMask );
         }
     }
diff --git a/vcl/backendtest/outputdevice/bitmap.cxx 
b/vcl/backendtest/outputdevice/bitmap.cxx
index 5b491badf587..9ea1a6f08d84 100644
--- a/vcl/backendtest/outputdevice/bitmap.cxx
+++ b/vcl/backendtest/outputdevice/bitmap.cxx
@@ -105,8 +105,8 @@ Bitmap 
OutputDeviceTestBitmap::setupDrawBitmapExWithAlpha(vcl::PixelFormat aBitm
     AlphaMask aAlpha(aBitmapSize);
     {
         AlphaScopedWriteAccess aWriteAccess(aAlpha);
-        aWriteAccess->Erase(COL_WHITE);
-        aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44));
+        aWriteAccess->Erase(COL_ALPHA_TRANSPARENT);
+        aWriteAccess->SetLineColor(Color(0xBB, 0xBB, 0xBB));
         aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
         aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
     }
@@ -154,8 +154,8 @@ BitmapEx 
OutputDeviceTestBitmap::setupDrawBlend(vcl::PixelFormat aBitmapFormat)
     AlphaMask aAlpha(aBitmapSize);
     {
         AlphaScopedWriteAccess aWriteAccess(aAlpha);
-        aWriteAccess->Erase(COL_WHITE);
-        aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44));
+        aWriteAccess->Erase(COL_ALPHA_TRANSPARENT);
+        aWriteAccess->SetLineColor(Color(0xBB, 0xBB, 0xBB));
         aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
         aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
     }
diff --git a/vcl/headless/BitmapHelper.cxx b/vcl/headless/BitmapHelper.cxx
index 3eb29aa76ad3..8ed0cac09fcb 100644
--- a/vcl/headless/BitmapHelper.cxx
+++ b/vcl/headless/BitmapHelper.cxx
@@ -84,19 +84,7 @@ MaskHelper::MaskHelper(const SalBitmap& rAlphaBitmap)
     const BitmapBuffer* pMaskBuf = rMask.GetBuffer();
     assert(rAlphaBitmap.GetBitCount() == 8 && "we only support 8-bit masks 
now");
 
-    // the alpha values need to be inverted for Cairo
-    // so big stupid copy and invert here
-    const int nImageSize = pMaskBuf->mnHeight * pMaskBuf->mnScanlineSize;
-    pAlphaBits.reset(new unsigned char[nImageSize]);
-    memcpy(pAlphaBits.get(), pMaskBuf->mpBits, nImageSize);
-
-    // TODO: make upper layers use standard alpha
-    sal_uInt32* pLDst = reinterpret_cast<sal_uInt32*>(pAlphaBits.get());
-    for (int i = nImageSize / sizeof(sal_uInt32); --i >= 0; ++pLDst)
-        *pLDst = ~*pLDst;
-    assert(reinterpret_cast<unsigned char*>(pLDst) == pAlphaBits.get() + 
nImageSize);
-
-    implSetSurface(cairo_image_surface_create_for_data(pAlphaBits.get(), 
CAIRO_FORMAT_A8,
+    implSetSurface(cairo_image_surface_create_for_data(pMaskBuf->mpBits, 
CAIRO_FORMAT_A8,
                                                        pMaskBuf->mnWidth, 
pMaskBuf->mnHeight,
                                                        
pMaskBuf->mnScanlineSize));
 }
diff --git a/vcl/headless/CairoCommon.cxx b/vcl/headless/CairoCommon.cxx
index 15b8cebfb261..d378d1477bd4 100644
--- a/vcl/headless/CairoCommon.cxx
+++ b/vcl/headless/CairoCommon.cxx
@@ -1912,8 +1912,6 @@ std::shared_ptr<SalBitmap> 
CairoCommon::getBitmap(tools::Long nX, tools::Long nY
     cairo_destroy(cr);
     cairo_surface_destroy(target);
 
-    Toggle1BitTransparency(*pBitmap->GetBuffer());
-
     return pBitmap;
 }
 
@@ -2080,19 +2078,6 @@ std::unique_ptr<BitmapBuffer> 
FastConvert24BitRgbTo32BitCairo(const BitmapBuffer
     return pDst;
 }
 
-void Toggle1BitTransparency(const BitmapBuffer& rBuf)
-{
-    assert(rBuf.maPalette.GetBestIndex(BitmapColor(COL_BLACK)) == 0);
-    // TODO: make upper layers use standard alpha
-    if (getCairoFormat(rBuf) == CAIRO_FORMAT_A1)
-    {
-        const int nImageSize = rBuf.mnHeight * rBuf.mnScanlineSize;
-        unsigned char* pDst = rBuf.mpBits;
-        for (int i = nImageSize; --i >= 0; ++pDst)
-            *pDst = ~*pDst;
-    }
-}
-
 namespace
 {
 // check for env var that decides for using downscale pattern
diff --git a/vcl/inc/bitmap/ScanlineTools.hxx b/vcl/inc/bitmap/ScanlineTools.hxx
index c343cf34f61e..99ce5dc33aae 100644
--- a/vcl/inc/bitmap/ScanlineTools.hxx
+++ b/vcl/inc/bitmap/ScanlineTools.hxx
@@ -39,14 +39,14 @@ public:
 
     virtual Color readPixel() override
     {
-        const Color aColor(ColorTransparency, pData[4], pData[1], pData[2], 
pData[3]);
+        const Color aColor(ColorAlpha, pData[4], pData[1], pData[2], pData[3]);
         pData += 4;
         return aColor;
     }
 
     virtual void writePixel(Color nColor) override
     {
-        *pData++ = 255 - nColor.GetAlpha();
+        *pData++ = nColor.GetAlpha();
         *pData++ = nColor.GetRed();
         *pData++ = nColor.GetGreen();
         *pData++ = nColor.GetBlue();
diff --git a/vcl/inc/headless/BitmapHelper.hxx 
b/vcl/inc/headless/BitmapHelper.hxx
index dbd7e86675e3..2b6598464703 100644
--- a/vcl/inc/headless/BitmapHelper.hxx
+++ b/vcl/inc/headless/BitmapHelper.hxx
@@ -39,9 +39,6 @@ public:
 
 class VCL_DLLPUBLIC MaskHelper : public SurfaceHelper
 {
-private:
-    std::unique_ptr<unsigned char[]> pAlphaBits;
-
 public:
     explicit MaskHelper(const SalBitmap& rAlphaBitmap);
 };
diff --git a/vcl/inc/headless/CairoCommon.hxx b/vcl/inc/headless/CairoCommon.hxx
index ea07e798b74b..8402e38b1d59 100644
--- a/vcl/inc/headless/CairoCommon.hxx
+++ b/vcl/inc/headless/CairoCommon.hxx
@@ -111,8 +111,6 @@ VCL_DLLPUBLIC cairo_format_t getCairoFormat(const 
BitmapBuffer& rBuffer);
 VCL_DLLPUBLIC std::unique_ptr<BitmapBuffer>
 FastConvert24BitRgbTo32BitCairo(const BitmapBuffer* pSrc);
 
-VCL_DLLPUBLIC void Toggle1BitTransparency(const BitmapBuffer& rBuf);
-
 enum class PaintMode
 {
     Over,
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx
index 2c85be06e66d..e5013d244335 100644
--- a/vcl/qa/cppunit/BackendTest.cxx
+++ b/vcl/qa/cppunit/BackendTest.cxx
@@ -1181,7 +1181,7 @@ public:
         device->Erase();
         alpha.Erase(255); // transparent
         BitmapWriteAccess* alphaWrite = alpha.AcquireAlphaWriteAccess();
-        alphaWrite->SetPixelIndex(0, 0, 0); // opaque
+        alphaWrite->SetPixelIndex(0, 0, 255); // opaque
         alpha.ReleaseAccess(alphaWrite);
         device->DrawBitmapEx(Point(2, 2), BitmapEx(bitmap, alpha));
         exportDevice("blend_extended_04.png", device);
diff --git a/vcl/qa/cppunit/BitmapExTest.cxx b/vcl/qa/cppunit/BitmapExTest.cxx
index a0a6b3096f53..a8f1e5a9cda5 100644
--- a/vcl/qa/cppunit/BitmapExTest.cxx
+++ b/vcl/qa/cppunit/BitmapExTest.cxx
@@ -47,8 +47,7 @@ void BitmapExTest::testGetPixelColor24_8()
 
     BitmapEx aBitmapEx(aBitmap, aMask);
 
-    CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xAA, 0x00, 0xFF, 0x00),
-                         aBitmapEx.GetPixelColor(0, 0));
+    CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 0xAA, 0x00, 0xFF, 0x00), 
aBitmapEx.GetPixelColor(0, 0));
 }
 
 void BitmapExTest::testGetPixelColor32()
diff --git a/vcl/qa/cppunit/ScanlineToolsTest.cxx 
b/vcl/qa/cppunit/ScanlineToolsTest.cxx
index 8b8a9088a1ea..97233f2692af 100644
--- a/vcl/qa/cppunit/ScanlineToolsTest.cxx
+++ b/vcl/qa/cppunit/ScanlineToolsTest.cxx
@@ -42,9 +42,9 @@ void ScanlineToolsTest::ScanlineTransformer_32_ARGB()
     pScanlineTransformer->startLine(aScanLine.data());
 
     std::vector<Color> aColors{
-        Color(ColorTransparency, 0, 10, 250, 120),   Color(ColorTransparency, 
50, 30, 230, 110),
-        Color(ColorTransparency, 100, 50, 210, 100), Color(ColorTransparency, 
150, 70, 190, 90),
-        Color(ColorTransparency, 200, 90, 170, 80),
+        Color(ColorAlpha, 255, 10, 250, 120), Color(ColorAlpha, 205, 30, 230, 
110),
+        Color(ColorAlpha, 155, 50, 210, 100), Color(ColorAlpha, 105, 70, 190, 
90),
+        Color(ColorAlpha, 55, 90, 170, 80),
     };
 
     for (Color const& aColor : aColors)
@@ -52,8 +52,8 @@ void ScanlineToolsTest::ScanlineTransformer_32_ARGB()
         pScanlineTransformer->writePixel(aColor);
     }
 
-    std::vector<sal_uInt8> aExpectedBytes{ 0,   10,  250, 120, 50,  30, 230, 
110, 100, 50,
-                                           210, 100, 150, 70,  190, 90, 200, 
90,  170, 80 };
+    std::vector<sal_uInt8> aExpectedBytes{ 255, 10,  250, 120, 205, 30, 230, 
110, 155, 50,
+                                           210, 100, 105, 70,  190, 90, 55,  
90,  170, 80 };
 
     for (size_t i = 0; i < aScanLine.size(); ++i)
     {
diff --git a/vcl/qa/cppunit/canvasbitmaptest.cxx 
b/vcl/qa/cppunit/canvasbitmaptest.cxx
index 27ac06d0d9de..78eb033f90b0 100644
--- a/vcl/qa/cppunit/canvasbitmaptest.cxx
+++ b/vcl/qa/cppunit/canvasbitmaptest.cxx
@@ -672,17 +672,17 @@ void CanvasBitmapTest::runTest()
 
         checkCanvasBitmap( xBmp, "single bitmap", nDepth );
 
-        Bitmap aMask(Size(200,200), vcl::PixelFormat::N8_BPP, 
&Bitmap::GetGreyPalette(256));
-        aMask.Erase(COL_WHITE);
+        AlphaMask aMask(Size(200,200));
+        aMask.Erase(255);
         {
             BitmapScopedWriteAccess pAcc(aMask);
             if( pAcc.get() )
             {
-                pAcc->SetFillColor(COL_BLACK);
+                pAcc->SetFillColor(COL_ALPHA_OPAQUE);
                 pAcc->FillRect(tools::Rectangle(0,0,100,100));
-                pAcc->SetPixel(0,0,BitmapColor(255));
-                pAcc->SetPixel(0,1,BitmapColor(0));
-                pAcc->SetPixel(0,2,BitmapColor(255));
+                pAcc->SetPixel(0,0,BitmapColor(0));
+                pAcc->SetPixel(0,1,BitmapColor(255));
+                pAcc->SetPixel(0,2,BitmapColor(0));
             }
         }
 
@@ -691,16 +691,16 @@ void CanvasBitmapTest::runTest()
         checkCanvasBitmap( xBmp, "masked bitmap", nDepth );
 
         AlphaMask aAlpha(Size(200,200));
-        aAlpha.Erase(255);
+        aAlpha.Erase(0);
         {
             BitmapWriteAccess* pAcc = aAlpha.AcquireWriteAccess();
             if( pAcc )
             {
-                pAcc->SetFillColor(COL_BLACK);
+                pAcc->SetFillColor(COL_ALPHA_OPAQUE);
                 pAcc->FillRect(tools::Rectangle(0,0,100,100));
-                pAcc->SetPixel(0,0,BitmapColor(255));
-                pAcc->SetPixel(0,1,BitmapColor(0));
-                pAcc->SetPixel(0,2,BitmapColor(255));
+                pAcc->SetPixel(0,0,BitmapColor(0));
+                pAcc->SetPixel(0,1,BitmapColor(255));
+                pAcc->SetPixel(0,2,BitmapColor(0));
                 aAlpha.ReleaseAccess(pAcc);
             }
         }
@@ -762,15 +762,15 @@ void CanvasBitmapTest::runTest()
         CPPUNIT_ASSERT_EQUAL_MESSAGE("(0,0) incorrect content",
                                BitmapColor(0,1,0), pBmpAcc->GetPixel(0,0));
         CPPUNIT_ASSERT_EQUAL_MESSAGE("(0,0) incorrect alpha content",
-                               BitmapColor(255), pAlphaAcc->GetPixel(0,0));
+                               BitmapColor(0), pAlphaAcc->GetPixel(0,0));
         CPPUNIT_ASSERT_EQUAL_MESSAGE("(2,2) incorrect content",
                                BitmapColor(0,3,2), pBmpAcc->GetPixel(2,2));
         CPPUNIT_ASSERT_EQUAL_MESSAGE("(2,2) incorrect alpha content",
-                               BitmapColor(253), pAlphaAcc->GetPixel(2,2));
+                               BitmapColor(2), pAlphaAcc->GetPixel(2,2));
         CPPUNIT_ASSERT_EQUAL_MESSAGE("(9,2) incorrect content",
                                BitmapColor(0,3,9), pBmpAcc->GetPixel(2,9));
         CPPUNIT_ASSERT_EQUAL_MESSAGE("(9,2) correct alpha content",
-                               BitmapColor(253), pAlphaAcc->GetPixel(2,9));
+                               BitmapColor(2), pAlphaAcc->GetPixel(2,9));
 
         aBitmapAlpha.ReleaseAccess(pAlphaAcc);
         Bitmap::ReleaseAccess(pBmpAcc);
diff --git a/vcl/qa/cppunit/png/PngFilterTest.cxx 
b/vcl/qa/cppunit/png/PngFilterTest.cxx
index 760e12f8b3fc..8e9c15e6dd49 100644
--- a/vcl/qa/cppunit/png/PngFilterTest.cxx
+++ b/vcl/qa/cppunit/png/PngFilterTest.cxx
@@ -325,22 +325,22 @@ void PngFilterTest::testPng()
                     CPPUNIT_ASSERT_EQUAL(tools::Long(4), 
pAlphaAccess->Width());
                     CPPUNIT_ASSERT_EQUAL(tools::Long(4), 
pAlphaAccess->Height());
 
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x80, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x7F, 0x00),
                                          pAlphaAccess->GetPixel(0, 0));
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x80, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x7F, 0x00),
                                          pAlphaAccess->GetPixel(3, 3));
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x80, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x7F, 0x00),
                                          pAlphaAccess->GetPixel(3, 0));
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x80, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x7F, 0x00),
                                          pAlphaAccess->GetPixel(0, 3));
 
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x40, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0xBF, 0x00),
                                          pAlphaAccess->GetPixel(1, 1));
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0xC0, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x3F, 0x00),
                                          pAlphaAccess->GetPixel(1, 2));
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0xC0, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x3F, 0x00),
                                          pAlphaAccess->GetPixel(2, 1));
-                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0x40, 0x00),
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 
0x00, 0xBF, 0x00),
                                          pAlphaAccess->GetPixel(2, 2));
                 }
             }
@@ -1887,15 +1887,14 @@ void PngFilterTest::testPngRoundtrip24_8()
         {
             BitmapScopedWriteAccess pWriteAccessBitmap(aBitmap);
             AlphaScopedWriteAccess pWriteAccessAlpha(aAlpha);
-            pWriteAccessAlpha->Erase(Color(ColorTransparency, 0x00, 0xAA, 
0xAA, 0xAA));
+            pWriteAccessAlpha->Erase(Color(0xAA, 0xAA, 0xAA));
             pWriteAccessBitmap->Erase(COL_BLACK);
             for (int i = 0; i < 8; ++i)
             {
                 for (int j = 0; j < 8; ++j)
                 {
                     pWriteAccessBitmap->SetPixel(i, j, COL_LIGHTRED);
-                    pWriteAccessAlpha->SetPixel(i, j,
-                                                Color(ColorTransparency, 0x00, 
0xBB, 0xBB, 0xBB));
+                    pWriteAccessAlpha->SetPixel(i, j, Color(0xBB, 0xBB, 0xBB));
                 }
             }
             for (int i = 8; i < 16; ++i)
@@ -1903,8 +1902,7 @@ void PngFilterTest::testPngRoundtrip24_8()
                 for (int j = 8; j < 16; ++j)
                 {
                     pWriteAccessBitmap->SetPixel(i, j, COL_LIGHTBLUE);
-                    pWriteAccessAlpha->SetPixel(i, j,
-                                                Color(ColorTransparency, 0x00, 
0xCC, 0xCC, 0xCC));
+                    pWriteAccessAlpha->SetPixel(i, j, Color(0xCC, 0xCC, 0xCC));
                 }
             }
         }
@@ -1922,13 +1920,13 @@ void PngFilterTest::testPngRoundtrip24_8()
 
         CPPUNIT_ASSERT_EQUAL(Size(16, 16), aBitmapEx.GetSizePixel());
 
-        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xBB, 0xFF, 0x00, 0x00),
+        CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 0xBB, 0xFF, 0x00, 0x00),
                              aBitmapEx.GetPixelColor(0, 0));
-        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xCC, 0x00, 0x00, 0xFF),
+        CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 0xCC, 0x00, 0x00, 0xFF),
                              aBitmapEx.GetPixelColor(15, 15));
-        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xAA, 0x00, 0x00, 0x00),
+        CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 0xAA, 0x00, 0x00, 0x00),
                              aBitmapEx.GetPixelColor(15, 0));
-        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xAA, 0x00, 0x00, 0x00),
+        CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 0xAA, 0x00, 0x00, 0x00),
                              aBitmapEx.GetPixelColor(0, 15));
     }
 }
diff --git a/vcl/qa/cppunit/skia/skia.cxx b/vcl/qa/cppunit/skia/skia.cxx
index 5d81e39f587a..b90b915e17ea 100644
--- a/vcl/qa/cppunit/skia/skia.cxx
+++ b/vcl/qa/cppunit/skia/skia.cxx
@@ -244,7 +244,7 @@ void SkiaTest::testAlphaBlendWith()
     skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
     CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
     CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(208),
                          AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 
0));
 
     // Test with images set.
@@ -264,7 +264,7 @@ void SkiaTest::testAlphaBlendWith()
     skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
     CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
     CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(207),
                          AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 
0));
 
     // Test with erase color for alpha and image for other bitmap.
@@ -281,7 +281,7 @@ void SkiaTest::testAlphaBlendWith()
     skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
     CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
     CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(207),
                          AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 
0));
 }
 
diff --git a/vcl/qa/cppunit/svm/svmtest.cxx b/vcl/qa/cppunit/svm/svmtest.cxx
index fcf863e7664a..5161f4cce960 100644
--- a/vcl/qa/cppunit/svm/svmtest.cxx
+++ b/vcl/qa/cppunit/svm/svmtest.cxx
@@ -26,6 +26,7 @@
 #include <vcl/filter/SvmReader.hxx>
 #include <vcl/filter/SvmWriter.hxx>
 #include <salhelper/simplereferenceobject.hxx>
+#include <sal/log.hxx>
 
 #include <bitmap/BitmapWriteAccess.hxx>
 
@@ -46,7 +47,7 @@ class SvmTest : public test::BootstrapFixture, public 
XmlTestTools
         return m_directories.getURLFromSrc(maDataUrl) + sFileName;
     }
 
-    void checkRendering(ScopedVclPtrInstance<VirtualDevice> const & 
pVirtualDev, const GDIMetaFile& rMetaFile);
+    void checkRendering(ScopedVclPtrInstance<VirtualDevice> const & 
pVirtualDev, const GDIMetaFile& rMetaFile, const char * where);
 
     // write GDI Metafile to a file in data directory
     // only use this for new tests to create the svm file
@@ -268,7 +269,7 @@ static void setupBaseVirtualDevice(VirtualDevice& rDevice, 
GDIMetaFile& rMeta)
     rDevice.Erase();
 }
 
-void SvmTest::checkRendering(ScopedVclPtrInstance<VirtualDevice> const & 
pVirtualDev, const GDIMetaFile& rMetaFile)
+void SvmTest::checkRendering(ScopedVclPtrInstance<VirtualDevice> const & 
pVirtualDev, const GDIMetaFile& rMetaFile, const char * where)
 {
     BitmapEx aSourceBitmapEx = pVirtualDev->GetBitmapEx(Point(), Size(10, 10));
     ScopedVclPtrInstance<VirtualDevice> pVirtualDevResult;
@@ -294,7 +295,7 @@ void 
SvmTest::checkRendering(ScopedVclPtrInstance<VirtualDevice> const & pVirtua
             aPNGWriter.write(aResultBitmapEx);
         }
     }
-    CPPUNIT_ASSERT_EQUAL(aSourceBitmapEx.GetChecksum(), 
aResultBitmapEx.GetChecksum());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(where, aSourceBitmapEx.GetChecksum(), 
aResultBitmapEx.GetChecksum());
 }
 
 static GDIMetaFile readMetafile(const OUString& rUrl)
@@ -989,12 +990,12 @@ void SvmTest::testBitmaps()
     {
         GDIMetaFile aReloadedGDIMetaFile = writeAndReadStream(aGDIMetaFile);
         checkBitmaps(aReloadedGDIMetaFile);
-        checkRendering(pVirtualDev, aReloadedGDIMetaFile);
+        checkRendering(pVirtualDev, aReloadedGDIMetaFile, SAL_WHERE);
     }
     {
         GDIMetaFile aFileGDIMetaFile = readFile(u"bitmaps.svm");
         checkBitmaps(aFileGDIMetaFile);
-        checkRendering(pVirtualDev, aFileGDIMetaFile);
+        checkRendering(pVirtualDev, aFileGDIMetaFile, SAL_WHERE);
     }
 }
 
@@ -1005,7 +1006,7 @@ void SvmTest::checkBitmapExs(const GDIMetaFile& 
rMetaFile, bool bIsSvmFile)
     if (SkiaHelper::isVCLSkiaEnabled())
         return; // TODO SKIA using CRCs is broken (the idea of it)
 
-    std::array<OUString, 8> aExpectedCRC
+    static const std::vector<OUString> aExpectedCRC
     {
 #if defined OSL_BIGENDIAN
         "08feb5d3",
@@ -1028,7 +1029,7 @@ void SvmTest::checkBitmapExs(const GDIMetaFile& 
rMetaFile, bool bIsSvmFile)
 #endif
     };
 
-    std::array<OUString, 8> aExpectedContentChecksum
+    static const std::array<OUString, 8> aExpectedContentChecksum
     {
         "26bdebd04e5b18d685cea04982179e273ee3b659",
         "f4f52df6ef965a2f0fbccbe6aca35ba3457cf9d5",
@@ -1126,7 +1127,7 @@ void SvmTest::testBitmapExs()
             pAccess->Erase(COL_MAGENTA);
 
             AlphaScopedWriteAccess pAlphaAccess(aAlpha);
-            pAlphaAccess->Erase(Color(128, 128, 128));
+            pAlphaAccess->Erase(Color(127, 127, 127));
         }
         pVirtualDev->DrawBitmapEx(Point(6, 6), BitmapEx(aBitmap, aAlpha));
     }
@@ -1178,12 +1179,12 @@ void SvmTest::testBitmapExs()
     {
         GDIMetaFile aReloadedGDIMetaFile = writeAndReadStream(aGDIMetaFile);
         checkBitmapExs(aReloadedGDIMetaFile, /*bIsSvmFile*/false);
-        checkRendering(pVirtualDev, aReloadedGDIMetaFile);
+        checkRendering(pVirtualDev, aReloadedGDIMetaFile, SAL_WHERE);
     }
     {
         GDIMetaFile aFileGDIMetaFile = readFile(u"bitmapexs.svm");
         checkBitmapExs(aFileGDIMetaFile, /*bIsSvmFile*/true);
-        checkRendering(pVirtualDev, aFileGDIMetaFile);
+        checkRendering(pVirtualDev, aFileGDIMetaFile, SAL_WHERE);
     }
 }
 
diff --git a/vcl/qt5/QtGraphics_GDI.cxx b/vcl/qt5/QtGraphics_GDI.cxx
index 28bab34a7cca..70c598c8bcd9 100644
--- a/vcl/qt5/QtGraphics_GDI.cxx
+++ b/vcl/qt5/QtGraphics_GDI.cxx
@@ -597,7 +597,6 @@ static QImage getAlphaImage(const SalBitmap& rSourceBitmap, 
const SalBitmap& rAl
     assert(rAlphaBitmap.GetBitCount() == 8 || rAlphaBitmap.GetBitCount() == 1);
 
     QImage aAlphaMask = *static_cast<const 
QtBitmap*>(&rAlphaBitmap)->GetQImage();
-    aAlphaMask.invertPixels();
 
     const QImage* pBitmap = static_cast<const 
QtBitmap*>(&rSourceBitmap)->GetQImage();
     QImage aImage = pBitmap->convertToFormat(Qt_DefaultFormat32);
diff --git a/vcl/quartz/cgutils.mm b/vcl/quartz/cgutils.mm
index c28391c48395..c6a490d44885 100644
--- a/vcl/quartz/cgutils.mm
+++ b/vcl/quartz/cgutils.mm
@@ -41,27 +41,38 @@ CGImageRef CreateWithSalBitmapAndMask( const SalBitmap& 
rBitmap, const SalBitmap
     if( !xMask )
         return xImage;
 
-    // CGImageCreateWithMask() only likes masks or greyscale images => convert 
if needed
-    // TODO: isolate in an extra method?
-    if( !CGImageIsMask(xMask) || rMask.GetBitCount() != 
8)//(CGImageGetColorSpace(xMask) != GetSalData()->mxGraySpace) )
+    // If xMask is an image (i.e. not a mask), it must be greyscale - a 
requirement of the
+    // CGImageCreateWithMask() function.
+    if( !CGImageIsMask(xMask) && CGImageGetColorSpace(xMask) != 
GetSalData()->mxGraySpace )
     {
-        const CGRect xImageRect=CGRectMake( 0, 0, nWidth, nHeight );//the rect 
has no offset
+        CGImageRef xGrayMask = CGImageCreateCopyWithColorSpace(xMask, 
GetSalData()->mxGraySpace);
+        if (xGrayMask)
+        {
+            CFRelease(xMask);
+            xMask = xGrayMask;
+        }
+        else
+        {
+            // Many gallery images will fail to be converted to a grayscale
+            // colorspace so fall back to old mask creation code
+            const CGRect xImageRect=CGRectMake( 0, 0, nWidth, nHeight );//the 
rect has no offset
 
-        // create the alpha mask image fitting our image
-        // TODO: is caching the full mask or the subimage mask worth it?
-        int nMaskBytesPerRow = ((nWidth + 3) & ~3);
-        void* pMaskMem = std::malloc( nMaskBytesPerRow * nHeight );
-        CGContextRef xMaskContext = CGBitmapContextCreate( pMaskMem,
-            nWidth, nHeight, 8, nMaskBytesPerRow, GetSalData()->mxGraySpace, 
kCGImageAlphaNone );
-        CGContextDrawImage( xMaskContext, xImageRect, xMask );
-        CFRelease( xMask );
-        CGDataProviderRef xDataProvider( CGDataProviderCreateWithData( nullptr,
-        pMaskMem, nHeight * nMaskBytesPerRow, &CFRTLFree ) );
+            // create the alpha mask image fitting our image
+            // TODO: is caching the full mask or the subimage mask worth it?
+            int nMaskBytesPerRow = ((nWidth + 3) & ~3);
+            void* pMaskMem = std::malloc( nMaskBytesPerRow * nHeight );
+            CGContextRef xMaskContext = CGBitmapContextCreate( pMaskMem,
+                nWidth, nHeight, 8, nMaskBytesPerRow, 
GetSalData()->mxGraySpace, kCGImageAlphaNone );
+            CGContextDrawImage( xMaskContext, xImageRect, xMask );
+            CFRelease( xMask );
+            CGDataProviderRef xDataProvider( CGDataProviderCreateWithData( 
nullptr,
+            pMaskMem, nHeight * nMaskBytesPerRow, &CFRTLFree ) );
 
-        static const CGFloat* pDecode = nullptr;
-        xMask = CGImageMaskCreate( nWidth, nHeight, 8, 8, nMaskBytesPerRow, 
xDataProvider, pDecode, false );
-        CFRelease( xDataProvider );
-        CFRelease( xMaskContext );
+            static const CGFloat* pDecode = nullptr;
+            xMask = CGImageMaskCreate( nWidth, nHeight, 8, 8, 
nMaskBytesPerRow, xDataProvider, pDecode, false );
+            CFRelease( xDataProvider );
+            CFRelease( xMaskContext );
+        }
     }
 
     if( !xMask )
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 40341bba85f7..e6c373c2f86b 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1272,23 +1272,19 @@ bool SkiaSalGraphicsImpl::blendBitmap(const SalTwoRect& 
rPosAry, const SalBitmap
 
     assert(dynamic_cast<const SkiaSalBitmap*>(&rBitmap));
     const SkiaSalBitmap& rSkiaBitmap = static_cast<const 
SkiaSalBitmap&>(rBitmap);
-    // This is used by VirtualDevice in the alpha mode for the "alpha" layer 
which
-    // is actually one-minus-alpha (opacity). Therefore white=0xff=transparent,
-    // black=0x00=opaque. So the result is transparent only if both the inputs
-    // are transparent. Since for blending operations white=1.0 and black=0.0,
-    // kMultiply should handle exactly that 
(transparent*transparent=transparent,
-    // opaque*transparent=opaque). And guessing from the "floor" in TYPE_BLEND 
in opengl's
-    // combinedTextureFragmentShader.glsl, the layer is not even alpha values 
but
-    // simply yes-or-no mask.
+    // This is used by VirtualDevice in the alpha mode for the "alpha" layer
+    // So the result is transparent only if both the inputs
+    // are transparent. Which seems to be what SkBlendMode::kModulate does,
+    // so use that.
     // See also blendAlphaBitmap().
     if (rSkiaBitmap.IsFullyOpaqueAsAlpha())
     {
-        // Optimization. If the bitmap means fully opaque, it's all zero's. In 
CPU
+        // Optimization. If the bitmap means fully opaque, it's all one's. In 
CPU
         // mode it should be faster to just copy instead of 
SkBlendMode::kMultiply.
         drawBitmap(rPosAry, rSkiaBitmap);
     }
     else
-        drawBitmap(rPosAry, rSkiaBitmap, SkBlendMode::kMultiply);
+        drawBitmap(rPosAry, rSkiaBitmap, SkBlendMode::kModulate);
     return true;
 }
 
@@ -1337,10 +1333,10 @@ bool SkiaSalGraphicsImpl::blendAlphaBitmap(const 
SalTwoRect& rPosAry,
     // First do the "( 1 - alpha ) * mask"
     // (no idea how to do "floor", but hopefully not needed in practice).
     sk_sp<SkShader> shaderAlpha
-        = SkShaders::Blend(SkBlendMode::kDstOut, 
rSkiaMaskBitmap.GetAlphaSkShader(samplingOptions),
+        = SkShaders::Blend(SkBlendMode::kDstIn, 
rSkiaMaskBitmap.GetAlphaSkShader(samplingOptions),
                            rSkiaAlphaBitmap.GetAlphaSkShader(samplingOptions));
     // And now draw the bitmap with "1 - x", where x is the "( 1 - alpha ) * 
mask".
-    sk_sp<SkShader> shader = SkShaders::Blend(SkBlendMode::kSrcOut, 
shaderAlpha,
+    sk_sp<SkShader> shader = SkShaders::Blend(SkBlendMode::kSrcIn, shaderAlpha,
                                               
rSkiaSourceBitmap.GetSkShader(samplingOptions));
     drawShader(rPosAry, shader);
     return true;
@@ -1368,9 +1364,12 @@ void SkiaSalGraphicsImpl::drawMask(const SalTwoRect& 
rPosAry, const SalBitmap& r
 {
     assert(dynamic_cast<const SkiaSalBitmap*>(&rSalBitmap));
     const SkiaSalBitmap& skiaBitmap = static_cast<const 
SkiaSalBitmap&>(rSalBitmap);
+    // SkBlendMode::kDstOut must be used instead of SkBlendMode::kDstIn because
+    // the alpha channel of what is drawn appears to get inverted at some point
+    // after it is drawn
     drawShader(
         rPosAry,
-        SkShaders::Blend(SkBlendMode::kDstOut, // VCL alpha is one-minus-alpha.
+        SkShaders::Blend(SkBlendMode::kDstOut, // VCL alpha is alpha.
                          SkShaders::Color(toSkColor(nMaskColor)),
                          
skiaBitmap.GetAlphaSkShader(makeSamplingOptions(rPosAry, mScaling))));
 }
@@ -1680,7 +1679,7 @@ sk_sp<SkImage> 
SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
     {
         canvas->clear(SK_ColorTRANSPARENT);
         paint.setShader(
-            SkShaders::Blend(SkBlendMode::kDstOut, 
bitmap.GetSkShader(samplingOptions, bitmapType),
+            SkShaders::Blend(SkBlendMode::kDstIn, 
bitmap.GetSkShader(samplingOptions, bitmapType),
                              alphaBitmap->GetAlphaSkShader(samplingOptions, 
alphaBitmapType)));
         canvas->drawPaint(paint);
     }
@@ -1742,7 +1741,7 @@ bool SkiaSalGraphicsImpl::drawAlphaBitmap(const 
SalTwoRect& rPosAry, const SalBi
     else
         drawShader(rPosAry,
                    SkShaders::Blend(
-                       SkBlendMode::kDstOut, // VCL alpha is one-minus-alpha.
+                       SkBlendMode::kDstIn,
                        
rSkiaSourceBitmap.GetSkShader(makeSamplingOptions(rPosAry, mScaling)),
                        
rSkiaAlphaBitmap.GetAlphaSkShader(makeSamplingOptions(rPosAry, mScaling))));
     return true;
@@ -1965,7 +1964,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
         if (pSkiaAlphaBitmap)
         {
             SkPaint paint = makeBitmapPaint();
-            paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, // VCL 
alpha is one-minus-alpha.
+            paint.setShader(SkShaders::Blend(SkBlendMode::kDstIn,
                                              
rSkiaBitmap.GetSkShader(samplingOptions),
                                              
pSkiaAlphaBitmap->GetAlphaSkShader(samplingOptions)));
             if (fAlpha != 1.0)
diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx
index 778917b6db0e..5a514aebb05d 100644
--- a/vcl/skia/salbmp.cxx
+++ b/vcl/skia/salbmp.cxx
@@ -617,7 +617,12 @@ bool SkiaSalBitmap::AlphaBlendWith(const SalBitmap& 
rSalBmp)
     SkPaint paint;
     paint.setBlendMode(SkBlendMode::kSrc); // set as is
     surface->getCanvas()->drawImage(GetSkImage(), 0, 0, SkSamplingOptions(), 
&paint);
-    paint.setBlendMode(SkBlendMode::kScreen); // src+dest - src*dest/255 (in 
0..1)
+    // in the 0..1 range that skia uses, the equation we want is:
+    //     r = 1 - ((1 - src) + (1 - dest) - (1 - src) * (1 - dest))
+    // which simplifies to:
+    //     r = src * dest
+    // which is SkBlendMode::kModulate
+    paint.setBlendMode(SkBlendMode::kModulate);
     surface->getCanvas()->drawImage(otherBitmap->GetSkImage(), 0, 0, 
SkSamplingOptions(), &paint);
     ResetToSkImage(makeCheckedImageSnapshot(surface));
     DataChanged();
@@ -640,8 +645,10 @@ bool SkiaSalBitmap::Invert()
         surface->getCanvas()->clear(SK_ColorWHITE);
         SkPaint paint;
         paint.setBlendMode(SkBlendMode::kDifference);
-        surface->getCanvas()->drawImage(
-            mImage, 0, 0, SkSamplingOptions(SkFilterMode::kLinear, 
SkMipmapMode::kLinear), &paint);
+        // Drawing the image does not work so create a shader from the image
+        paint.setShader(GetSkShader(SkSamplingOptions(SkSamplingOptions())));
+        surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 0, mSize.Width(), 
mSize.Height()),
+                                       paint);
         ResetToSkImage(makeCheckedImageSnapshot(surface));
         DataChanged();
         SAL_INFO("vcl.skia.trace", "invert(" << this << ")");
@@ -746,11 +753,8 @@ SkBitmap SkiaSalBitmap::GetAsSkBitmap() const
 }
 
 // If mEraseColor is set, this is the color to use when the bitmap is used as 
alpha bitmap.
-// E.g. COL_BLACK actually means fully opaque and COL_WHITE means fully 
transparent.
+// E.g. COL_BLACK actually means fully transparent and COL_WHITE means fully 
opaque.
 // This is because the alpha value is set as the color itself, not the alpha 
of the color.
-// Additionally VCL actually uses transparency and not opacity, so we should 
use "255 - value",
-// but we account for this by doing SkBlendMode::kDstOut when using alpha 
images (which
-// basically does another "255 - alpha"), so do not do it here.
 static SkColor fromEraseColorToAlphaImageColor(Color color)
 {
     return SkColorSetARGB(color.GetBlue(), 0, 0, 0);
@@ -1053,9 +1057,7 @@ bool SkiaSalBitmap::IsFullyOpaqueAsAlpha() const
         return false;
     // If the erase color is set so that this bitmap used as alpha would
     // mean a fully opaque alpha mask (= noop), we can skip using it.
-    // Note that for alpha bitmaps we use the VCL "transparency" convention,
-    // i.e. alpha 0 is opaque.
-    return SkColorGetA(fromEraseColorToAlphaImageColor(mEraseColor)) == 0;
+    return SkColorGetA(fromEraseColorToAlphaImageColor(mEraseColor)) == 255;
 }
 
 SkAlphaType SkiaSalBitmap::alphaType() const
@@ -1080,7 +1082,7 @@ void SkiaSalBitmap::PerformErase()
         abort();
     Color fastColor = mEraseColor;
     if (!!mPalette)
-        fastColor = Color(ColorTransparency, mPalette.GetBestIndex(fastColor));
+        fastColor = Color(ColorAlpha, mPalette.GetBestIndex(fastColor));
     if (!ImplFastEraseBitmap(*bitmapBuffer, fastColor))
     {
         FncSetPixel setPixel = 
BitmapReadAccess::SetPixelFunction(bitmapBuffer->mnFormat);
@@ -1406,7 +1408,7 @@ OString SkiaSalBitmap::GetAlphaImageKey(DirectImage 
direct) const
     {
         std::stringstream ss;
         ss << std::hex << std::setfill('0') << std::setw(2)
-           << static_cast<int>(255 - 
SkColorGetA(fromEraseColorToAlphaImageColor(mEraseColor)));
+           << 
static_cast<int>(SkColorGetA(fromEraseColorToAlphaImageColor(mEraseColor)));
         return OString::Concat("E") + ss.str().c_str();
     }
     assert(direct == DirectImage::No || mAlphaImage);
diff --git a/vcl/source/bitmap/BitmapAlphaClampFilter.cxx 
b/vcl/source/bitmap/BitmapAlphaClampFilter.cxx
index eb3245e2347c..820bdbdde34b 100644
--- a/vcl/source/bitmap/BitmapAlphaClampFilter.cxx
+++ b/vcl/source/bitmap/BitmapAlphaClampFilter.cxx
@@ -30,9 +30,9 @@ BitmapEx BitmapAlphaClampFilter::execute(BitmapEx const& 
rBitmapEx) const
             for (sal_Int32 nX = 0; nX < sal_Int32(aSize.Width()); ++nX)
             {
                 BitmapColor 
aBitmapAlphaValue(pWriteAlpha->GetPixelFromData(pScanAlpha, nX));
-                if (aBitmapAlphaValue.GetIndex() > mcThreshold)
+                if ((255 - aBitmapAlphaValue.GetIndex()) > mcThreshold)
                 {
-                    aBitmapAlphaValue.SetIndex(255);
+                    aBitmapAlphaValue.SetIndex(0);
                     pWriteAlpha->SetPixelOnData(pScanAlpha, nX, 
aBitmapAlphaValue);
                 }
             }
diff --git a/vcl/source/bitmap/BitmapEx.cxx b/vcl/source/bitmap/BitmapEx.cxx
index ad4adca6319e..c9be55521f16 100644
--- a/vcl/source/bitmap/BitmapEx.cxx
+++ b/vcl/source/bitmap/BitmapEx.cxx
@@ -113,12 +113,20 @@ BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& 
rMask ) :
     if (rMask.IsEmpty())
         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");
+
     if( rMask.getPixelFormat() == vcl::PixelFormat::N8_BPP && 
rMask.HasGreyPalette8Bit() )
+    {
         maAlphaMask = rMask;
+        maAlphaMask.Invert();
+    }
     else if( rMask.getPixelFormat() == vcl::PixelFormat::N8_BPP )
     {
         BitmapEx aMaskEx(rMask);
         BitmapFilter::Filter(aMaskEx, BitmapMonochromeFilter(255));
+        aMaskEx.Invert();
         maAlphaMask = aMaskEx.GetBitmap();
     }
     else
@@ -127,6 +135,7 @@ BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask 
) :
         SAL_WARN( "vcl", "BitmapEx: forced mask to monochrome");
         BitmapEx aMaskEx(rMask);
         BitmapFilter::Filter(aMaskEx, BitmapMonochromeFilter(255));
+        aMaskEx.Invert();
         maAlphaMask = aMaskEx.GetBitmap();
     }
 
@@ -154,7 +163,7 @@ BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& 
rTransparentColor ) :
         maBitmap             ( rBmp ),
         maBitmapSize         ( maBitmap.GetSizePixel() )
 {
-    maAlphaMask = maBitmap.CreateMask( rTransparentColor );
+    maAlphaMask = maBitmap.CreateAlphaMask( rTransparentColor );
 
     SAL_WARN_IF(rBmp.GetSizePixel() != maAlphaMask.GetSizePixel(), "vcl",
                 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha 
mask.");
@@ -332,14 +341,14 @@ bool BitmapEx::Rotate( Degree10 nAngle10, const Color& 
rFillColor )
             }
 
             if( bRet && !maAlphaMask.IsEmpty() )
-                maAlphaMask.Rotate( nAngle10, COL_WHITE );
+                maAlphaMask.Rotate( nAngle10, COL_ALPHA_TRANSPARENT );
         }
         else
         {
             bRet = maBitmap.Rotate( nAngle10, rFillColor );
 
             if( bRet && !maAlphaMask.IsEmpty() )
-                maAlphaMask.Rotate( nAngle10, COL_WHITE );
+                maAlphaMask.Rotate( nAngle10, COL_ALPHA_TRANSPARENT );
         }
 
         SetSizePixel(maBitmap.GetSizePixel());
@@ -387,7 +396,7 @@ void BitmapEx::Expand( sal_Int32 nDX, sal_Int32 nDY, bool 
bExpandTransparent )
 
     if( bRet && !maAlphaMask.IsEmpty() )
     {
-        Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
+        Color aColor( bExpandTransparent ? COL_ALPHA_TRANSPARENT : 
COL_ALPHA_OPAQUE );
         maAlphaMask.Expand( nDX, nDY, &aColor );
     }
 
@@ -427,8 +436,8 @@ bool BitmapEx::CopyPixel( const tools::Rectangle& rRectDst, 
const tools::Rectang
                         maAlphaMask.CopyPixel_AlphaOptimized( rRectDst, 
rRectSrc, &pBmpExSrc->maAlphaMask );
                     else
                     {
-                        sal_uInt8 cBlack = 0;
-                        std::optional<AlphaMask> pAlpha(std::in_place, 
GetSizePixel(), &cBlack);
+                        sal_uInt8 nTransparencyOpaque = 0;
+                        std::optional<AlphaMask> pAlpha(std::in_place, 
GetSizePixel(), &nTransparencyOpaque);
 
                         maAlphaMask = pAlpha->ImplGetBitmap();
                         pAlpha.reset();
@@ -437,8 +446,8 @@ bool BitmapEx::CopyPixel( const tools::Rectangle& rRectDst, 
const tools::Rectang
                 }
                 else if (IsAlpha())
                 {
-                    sal_uInt8 cBlack = 0;
-                    const AlphaMask aAlphaSrc(pBmpExSrc->GetSizePixel(), 
&cBlack);
+                    sal_uInt8 nTransparencyOpaque = 0;
+                    const AlphaMask aAlphaSrc(pBmpExSrc->GetSizePixel(), 
&nTransparencyOpaque);
 
                     maAlphaMask.CopyPixel( rRectDst, rRectSrc, 
&aAlphaSrc.ImplGetBitmap() );
                 }
@@ -581,7 +590,7 @@ sal_uInt8 BitmapEx::GetAlpha(sal_Int32 nX, sal_Int32 nY) 
const
         if(pRead)
         {
             const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
-            nAlpha = 255 - aBitmapColor.GetIndex();
+            nAlpha = aBitmapColor.GetIndex();
         }
     }
     return nAlpha;
@@ -599,7 +608,7 @@ Color BitmapEx::GetPixelColor(sal_Int32 nX, sal_Int32 nY) 
const
     {
         AlphaMask aAlpha = GetAlphaMask();
         AlphaMask::ScopedReadAccess pAlphaReadAccess(aAlpha);
-        aColor.SetAlpha(255 - pAlphaReadAccess->GetPixel(nY, nX).GetIndex());
+        aColor.SetAlpha(pAlphaReadAccess->GetPixel(nY, nX).GetIndex());
     }
     else if (maBitmap.getPixelFormat() != vcl::PixelFormat::N32_BPP)
     {
@@ -1023,6 +1032,8 @@ BitmapEx createBlendFrame(
     Color aColorBottomRight,
     Color aColorBottomLeft)
 {
+    // FIXME the call sites are actually passing in transparency
+    nAlpha = 255 - nAlpha;
     BlendFrameCache* pBlendFrameCache = ImplGetBlendFrameCache();
 
     if(pBlendFrameCache->m_aLastSize == rSize
@@ -1368,7 +1379,7 @@ void BitmapEx::ChangeColorAlpha( sal_uInt8 cIndexFrom, 
sal_Int8 nAlphaTo )
         {
             const sal_uInt8 cIndex = pReadAccess->GetPixelFromData( 
pScanlineRead, nX ).GetIndex();
             if ( cIndex == cIndexFrom )
-                pAlphaWriteAccess->SetPixelOnData( pScanline, nX, 
BitmapColor(255 - nAlphaTo) );
+                pAlphaWriteAccess->SetPixelOnData( pScanline, nX, 
BitmapColor(nAlphaTo) );
         }
     }
     *this = BitmapEx( GetBitmap(), aAlphaMask );
@@ -1391,7 +1402,7 @@ void BitmapEx::AdjustTransparency(sal_uInt8 cTrans)
         if( !pA )
             return;
 
-        sal_uLong       nTrans = cTrans, nNewTrans;
+        sal_uLong nTrans = cTrans;
         const tools::Long  nWidth = pA->Width(), nHeight = pA->Height();
 
         if( pA->GetScanlineFormat() == ScanlineFormat::N8BitPal )
@@ -1402,8 +1413,10 @@ void BitmapEx::AdjustTransparency(sal_uInt8 cTrans)
 
                 for( tools::Long nX = 0; nX < nWidth; nX++ )
                 {
-                    nNewTrans = nTrans + *pAScan;
-                    *pAScan++ = static_cast<sal_uInt8>( ( nNewTrans & 
0xffffff00 ) ? 255 : nNewTrans );
+                    sal_uLong nNewTrans = nTrans + (255 - *pAScan);
+                    // clamp to 255
+                    nNewTrans = ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans;
+                    *pAScan++ = static_cast<sal_uInt8>( 255 - nNewTrans );
                 }
             }
         }
@@ -1416,8 +1429,11 @@ void BitmapEx::AdjustTransparency(sal_uInt8 cTrans)
                 Scanline pScanline = pA->GetScanline( nY );
                 for( tools::Long nX = 0; nX < nWidth; nX++ )
                 {
-                    nNewTrans = nTrans + pA->GetIndexFromData( pScanline, nX );
-                    aAlphaValue.SetIndex( static_cast<sal_uInt8>( ( nNewTrans 
& 0xffffff00 ) ? 255 : nNewTrans ) );
+                    sal_uLong nNewTrans = nTrans + (255 - 
pA->GetIndexFromData( pScanline, nX ));
+                    // clamp to 255
+                    nNewTrans = ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans;
+                    // convert back to alpha
+                    aAlphaValue.SetIndex( static_cast<sal_uInt8>(255 - 
nNewTrans) );
                     pA->SetPixelOnData( pScanline, nX, aAlphaValue );
                 }
             }
diff --git a/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx 
b/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx
index c9ec102d933a..c5f1cda1d9cb 100644
--- a/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx
+++ b/vcl/source/bitmap/BitmapMaskToAlphaFilter.cxx
@@ -14,7 +14,7 @@
 #include <bitmap/BitmapMaskToAlphaFilter.hxx>
 
 /**
- * Convert a 1-bit mask to an alpha layer
+ * Convert a 1-bit mask to an alpha bitmap
  */
 BitmapEx BitmapMaskToAlphaFilter::execute(BitmapEx const& rBitmapEx) const
 {
@@ -38,11 +38,11 @@ BitmapEx BitmapMaskToAlphaFilter::execute(BitmapEx const& 
rBitmapEx) const
             {
                 BitmapColor aBmpColor = pRead->GetPixelFromData(pScanlineRead, 
nX);
                 if (aBmpColor == COL_BLACK)
-                    aBmpColor = COL_BLACK;
+                    aBmpColor = COL_ALPHA_OPAQUE;
                 else if (aBmpColor == COL_WHITE)
-                    aBmpColor = COL_WHITE;
+                    aBmpColor = COL_ALPHA_TRANSPARENT;
                 else if (aBmpColor == Color(0, 0, 1))
-                    aBmpColor = COL_WHITE;
+                    aBmpColor = COL_ALPHA_TRANSPARENT;
                 else
                     assert(false);
                 pWrite->SetPixelOnData(pScanline, nX, aBmpColor);
diff --git a/vcl/source/bitmap/BitmapTools.cxx 
b/vcl/source/bitmap/BitmapTools.cxx
index beec528b2f0e..7caf1f12f328 100644
--- a/vcl/source/bitmap/BitmapTools.cxx
+++ b/vcl/source/bitmap/BitmapTools.cxx
@@ -205,7 +205,8 @@ BitmapEx CreateFromData(sal_uInt8 const *pData, sal_Int32 
nWidth, sal_Int32 nHei
                 Scanline pMaskScanLine = xMaskAcc->GetScanline(y);
                 for (tools::Long x = 0; x < nWidth; ++x)
                 {
-                    const sal_uInt8 nValue = bReverseAlpha ? 0xff - *p : *p;
+                    // FIXME this parameter is badly named
+                    const sal_uInt8 nValue = bReverseAlpha ? *p : 0xff - *p;
                     xMaskAcc->SetPixelOnData(pMaskScanLine, x, 
BitmapColor(nValue));
                     p += 4;
                 }
@@ -271,11 +272,15 @@ BitmapEx CreateFromData( RawBitmap&& rawBitmap )
             Scanline pMaskScanLine = xMaskAcc->GetScanline(y);
             for (tools::Long x = 0; x < nWidth; ++x)
             {
-                xMaskAcc->SetPixelOnData(pMaskScanLine, x, BitmapColor(255 - 
*p));
+                xMaskAcc->SetPixelOnData(pMaskScanLine, x, BitmapColor(*p));
                 p += 4;
             }
         }
     }
+
+    xMaskAcc.reset();
+    pWrite.reset();
+
     if (nBitCount == 32)
         return BitmapEx(aBmp, *pAlphaMask);
     else
@@ -350,7 +355,7 @@ BitmapEx* CreateFromCairoSurface(Size aSize, 
cairo_surface_t * pSurface)
 #endif
             }
             pRGBWrite->SetPixel( y, x, BitmapColor( nR, nG, nB ) );
-            pMaskWrite->SetPixelIndex( y, x, 255 - nAlpha );
+            pMaskWrite->SetPixelIndex( y, x, nAlpha );
             pPix++;
         }
     }
@@ -462,7 +467,7 @@ BitmapEx CanvasTransformBitmap( const BitmapEx&             
    rBitmap,
                         if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
                             nSrcY < 0 || nSrcY >= aBmpSize.Height() )
                         {
-                            pAlphaWriteAccess->SetPixelOnData( pScanAlpha, x, 
BitmapColor(255) );
+                            pAlphaWriteAccess->SetPixelOnData( pScanAlpha, x, 
BitmapColor(0) );
                         }
                         else
                         {
@@ -486,11 +491,11 @@ BitmapEx CanvasTransformBitmap( const BitmapEx&           
      rBitmap,
                         if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
                             nSrcY < 0 || nSrcY >= aBmpSize.Height() )
                         {
-                            pAlphaWriteAccess->SetPixelOnData( pScanAlpha, x, 
BitmapColor(255) );
+                            pAlphaWriteAccess->SetPixelOnData( pScanAlpha, x, 
BitmapColor(0) );
                         }
                         else
                         {
-                            pAlphaWriteAccess->SetPixelOnData( pScanAlpha, x, 
BitmapColor(0) );
+                            pAlphaWriteAccess->SetPixelOnData( pScanAlpha, x, 
BitmapColor(255) );
                             pWriteAccess->SetPixelOnData( pScan, x, 
pReadAccess->GetPixel( nSrcY,
                                                                                
  nSrcX ) );
                         }
@@ -521,6 +526,7 @@ void DrawAlphaBitmapAndAlphaGradient(BitmapEx & rBitmapEx, 
bool bFixedTransparen
     }
 
     {
+
         AlphaScopedWriteAccess pOld(aOldMask);
 
         assert(pOld && "Got no access to old alpha mask (!)");
@@ -536,8 +542,8 @@ void DrawAlphaBitmapAndAlphaGradient(BitmapEx & rBitmapEx, 
bool bFixedTransparen
                 Scanline pScanline = pOld->GetScanline( y );
                 for(tools::Long x(0); x < pOld->Width(); x++)
                 {
-                    const double fOpOld(1.0 - 
(pOld->GetIndexFromData(pScanline, x) * fFactor));
-                    const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * 
fOpNew)) * 255.0));
+                    const double fOpOld(pOld->GetIndexFromData(pScanline, x) * 
fFactor);
+                    const sal_uInt8 aCol(basegfx::fround((fOpOld * fOpNew) * 
255.0));
 
                     pOld->SetPixelOnData(pScanline, x, BitmapColor(aCol));
                 }
@@ -557,9 +563,9 @@ void DrawAlphaBitmapAndAlphaGradient(BitmapEx & rBitmapEx, 
bool bFixedTransparen
                 Scanline pScanline = pOld->GetScanline( y );
                 for(tools::Long x(0); x < pOld->Width(); x++)
                 {
-                    const double fOpOld(1.0 - 
(pOld->GetIndexFromData(pScanline, x) * fFactor));
-                    const double fOpNew(1.0 - 
(pNew->GetIndexFromData(pScanline, x) * fFactor));
-                    const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * 
fOpNew)) * 255.0));
+                    const double fOpOld(pOld->GetIndexFromData(pScanline, x) * 
fFactor);
+                    const double fOpNew(pNew->GetIndexFromData(pScanline, x) * 
fFactor);
+                    const sal_uInt8 aCol(basegfx::fround((fOpOld * fOpNew) * 
255.0));
 
                     pOld->SetPixelOnData(pScanline, x, BitmapColor(aCol));
                 }
@@ -619,10 +625,9 @@ void DrawAndClipBitmap(const Point& rPos, const Size& 
rSize, const BitmapEx& rBi
                     const sal_uInt8 nIndR(pR->GetIndexFromData(pScanlineR, 
nX));
                     const sal_uInt8 nIndW(pW->GetIndexFromData(pScanlineW, 
nX));
 
-                    // these values represent transparency (0 == no, 255 == 
fully transparent),
-                    // so to blend these we have to multiply the inverse 
(opacity)
-                    // and re-invert the result to transparence
-                    const sal_uInt8 nCombined(0x00ff - (((0x00ff - nIndR) * 
(0x00ff - nIndW)) >> 8));
+                    // these values represent alpha (255 == no, 0 == fully 
transparent),
+                    // so to blend these we have to multiply
+                    const sal_uInt8 nCombined((nIndR * nIndW) >> 8);
 
                     pW->SetPixelOnData(pScanlineW, nX, BitmapColor(nCombined));
                 }
@@ -672,7 +677,7 @@ static bool readAlpha( BitmapReadAccess const * 
pAlphaReadAcc, tools::Long nY, c
                 BitmapColor const& rColor(
                     pAlphaReadAcc->GetPaletteColor(*pReadScan));
                 pReadScan++;
-                nAlpha = data[ nOff ] = 255 - rColor.GetIndex();
+                nAlpha = data[ nOff ] = rColor.GetIndex();
                 if( nAlpha != 255 )
                     bIsAlpha = true;
                 nOff += 4;
@@ -682,7 +687,7 @@ static bool readAlpha( BitmapReadAccess const * 
pAlphaReadAcc, tools::Long nY, c
             SAL_INFO( "canvas.cairo", "fallback to GetColor for alpha - slow, 
format: " << static_cast<int>(pAlphaReadAcc->GetScanlineFormat()) );
             for( nX = 0; nX < nWidth; nX++ )
             {
-                nAlpha = data[ nOff ] = 255 - pAlphaReadAcc->GetColor( nY, nX 
).GetIndex();
+                nAlpha = data[ nOff ] = pAlphaReadAcc->GetColor( nY, nX 
).GetIndex();
                 if( nAlpha != 255 )
                     bIsAlpha = true;
                 nOff += 4;
@@ -1027,7 +1032,7 @@ void CanvasCairoExtractBitmapData( BitmapEx const & 
aBmpEx, Bitmap & aBitmap, un
                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x 
).GetRed();
                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x 
).GetGreen();
                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x 
).GetBlue();
-                    pRes[ nCurrPos++ ] = pAlphaReadAccess->GetIndexFromData( 
pScanlineReadAlpha, x );
+                    pRes[ nCurrPos++ ] = 255 - 
pAlphaReadAccess->GetIndexFromData( pScanlineReadAlpha, x );
                 }
             }
             else
@@ -1217,7 +1222,7 @@ bool convertBitmap32To24Plus8(BitmapEx const & rInput, 
BitmapEx & rResult)
             {
                 const BitmapColor aColor = 
pReadAccess->GetPixelFromData(aReadScan, nX);
                 BitmapColor aResultColor(aColor.GetRed(), aColor.GetGreen(), 
aColor.GetBlue());
-                BitmapColor aResultColorAlpha(255 - aColor.GetAlpha(), 255 - 
aColor.GetAlpha(), 255 - aColor.GetAlpha());
+                BitmapColor aResultColorAlpha(aColor.GetAlpha(), 
aColor.GetAlpha(), aColor.GetAlpha());
 
                 pResultBitmapAccess->SetPixelOnData(aResultScan, nX, 
aResultColor);
                 pResultAlphaAccess->SetPixelOnData(aResultScanAlpha, nX, 
aResultColorAlpha);
diff --git a/vcl/source/bitmap/alpha.cxx b/vcl/source/bitmap/alpha.cxx
index f307dda63a28..8e082c695137 100644
--- a/vcl/source/bitmap/alpha.cxx
+++ b/vcl/source/bitmap/alpha.cxx
@@ -31,8 +31,11 @@ AlphaMask::AlphaMask() = default;
 AlphaMask::AlphaMask( const Bitmap& rBitmap ) :
     Bitmap( rBitmap )
 {
-    if( !rBitmap.IsEmpty() )
+    // no need to do any conversion if it is already an AlphaMask
+    if ( typeid(rBitmap) != typeid(AlphaMask) && !rBitmap.IsEmpty() )
         Convert( BmpConversion::N8BitNoConversion );
+    assert( (IsEmpty() || getPixelFormat() == vcl::PixelFormat::N8_BPP) && 
"alpha bitmap should be 8bpp" );
+    assert( (IsEmpty() || HasGreyPalette8Bit()) && "alpha bitmap should have 
greyscale palette" );
 }
 
 AlphaMask::AlphaMask( const AlphaMask& ) = default;
@@ -43,7 +46,12 @@ AlphaMask::AlphaMask( const Size& rSizePixel, const 
sal_uInt8* pEraseTransparenc
     : Bitmap(rSizePixel, vcl::PixelFormat::N8_BPP, 
&Bitmap::GetGreyPalette(256))
 {
     if( pEraseTransparency )
-        Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, 
*pEraseTransparency ) );
+    {
+        sal_uInt8 nAlpha = 255 - *pEraseTransparency;
+        Bitmap::Erase( Color( nAlpha, nAlpha, nAlpha ) );
+    }
+    else
+        Bitmap::Erase( COL_ALPHA_OPAQUE );
 }
 
 AlphaMask::~AlphaMask() = default;
@@ -55,6 +63,9 @@ AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap )
     if( !rBitmap.IsEmpty() )
         Convert( BmpConversion::N8BitNoConversion );
 
+    assert( getPixelFormat() == vcl::PixelFormat::N8_BPP && "alpha bitmap 
should be 8bpp" );
+    assert( HasGreyPalette8Bit() && "alpha bitmap should have greyscale 
palette" );
+
     return *this;
 }
 
@@ -70,7 +81,8 @@ Bitmap const & AlphaMask::GetBitmap() const
 
 void AlphaMask::Erase( sal_uInt8 cTransparency )
 {
-    Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) );
+    sal_uInt8 nAlpha = 255 - cTransparency;
+    Bitmap::Erase( Color( nAlpha, nAlpha, nAlpha ) );
 }
 
 void AlphaMask::BlendWith(const AlphaMask& rOther)
@@ -79,6 +91,8 @@ void AlphaMask::BlendWith(const AlphaMask& rOther)
     if (xImpBmp->Create(*ImplGetSalBitmap()) && 
xImpBmp->AlphaBlendWith(*rOther.ImplGetSalBitmap()))
     {
         ImplSetSalBitmap(xImpBmp);
+        assert( getPixelFormat() == vcl::PixelFormat::N8_BPP && "alpha bitmap 
should be 8bpp" );
+        assert( HasGreyPalette8Bit() && "alpha bitmap should have greyscale 
palette" );
         return;
     }
     Bitmap::ScopedReadAccess pOtherAcc(const_cast<AlphaMask&>(rOther));
@@ -101,11 +115,18 @@ void AlphaMask::BlendWith(const AlphaMask& rOther)
             // Use sal_uInt16 for following multiplication
             const sal_uInt16 nGrey1 = *scanline;
             const sal_uInt16 nGrey2 = *otherScanline;
-            *scanline = static_cast<sal_uInt8>(nGrey1 + nGrey2 - nGrey1 * 
nGrey2 / 255);
+            // Awkward calculation because the original used transparency, and 
to replicate
+            // the logic we need to translate into transparency, perform the 
original logic,
+            // then translate back to alpha.
+            auto tmp = 255 - ((255 - nGrey1) + (255 - nGrey2) - (255 - nGrey1) 
* (255 - nGrey2));
+            *scanline = static_cast<sal_uInt8>(tmp / 255);
             ++scanline;
             ++otherScanline;
         }
     }
+    pAcc.reset();
+    assert( getPixelFormat() == vcl::PixelFormat::N8_BPP && "alpha bitmap 
should be 8bpp" );
+    assert( HasGreyPalette8Bit() && "alpha bitmap should have greyscale 
palette" );
 }
 
 bool AlphaMask::hasAlpha() const
@@ -126,7 +147,7 @@ bool AlphaMask::hasAlpha() const
     {
         for (tools::Long x = 0; x < nWidth; ++x)
         {
-            if (0 != pAcc->GetColor(y, x).GetRed())
+            if (255 != pAcc->GetColor(y, x).GetRed())
             {
                 return true;
             }
@@ -143,6 +164,8 @@ void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess )
         Bitmap::ReleaseAccess( pAccess );
         Convert( BmpConversion::N8BitNoConversion );
     }
+    assert( getPixelFormat() == vcl::PixelFormat::N8_BPP && "alpha bitmap 
should be 8bpp" );
+    assert( HasGreyPalette8Bit() && "alpha bitmap should have greyscale 
palette" );
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/bitmap/bitmappaint.cxx 
b/vcl/source/bitmap/bitmappaint.cxx
index 0207bb813fe8..487e6d1a6ad6 100644
--- a/vcl/source/bitmap/bitmappaint.cxx
+++ b/vcl/source/bitmap/bitmappaint.cxx
@@ -60,38 +60,54 @@ bool Bitmap::Erase(const Color& rFillColor)
 
 bool Bitmap::Invert()
 {
-    ScopedReadAccess pReadAcc(*this);
-    if (!pReadAcc)
+    if (!mxSalBmp)
         return false;
 
-    if (pReadAcc->HasPalette())
+    // For alpha masks, we need to actually invert the underlying data
+    // or the optimisations elsewhere do not work right.
+    if (typeid(*this) != typeid(AlphaMask))
     {
-        BitmapScopedWriteAccess pWriteAcc(*this);
-        BitmapPalette aBmpPal(pWriteAcc->GetPalette());
-        const sal_uInt16 nCount = aBmpPal.GetEntryCount();
-
-        for (sal_uInt16 i = 0; i < nCount; i++)
+        // We want to avoid using ScopedReadAccess until we really need
+        // it, because on Skia it triggers a GPU->RAM copy, which is very slow.
+        ScopedReadAccess pReadAcc(*this);
+        if (!pReadAcc)
+            return false;
+        if (pReadAcc->HasPalette())
         {
-            aBmpPal[i].Invert();
-        }
+            BitmapScopedWriteAccess pWriteAcc(*this);
+            BitmapPalette aBmpPal(pWriteAcc->GetPalette());
+            const sal_uInt16 nCount = aBmpPal.GetEntryCount();
 
-        pWriteAcc->SetPalette(aBmpPal);
+            for (sal_uInt16 i = 0; i < nCount; i++)
+            {
+                aBmpPal[i].Invert();
+            }
+
+            pWriteAcc->SetPalette(aBmpPal);
+            mxSalBmp->InvalidateChecksum();
+            return true;
+        }
     }
-    else if (!mxSalBmp->Invert()) // try optimised call first
+
+    // try optimised call, much faster on Skia
+    if (mxSalBmp->Invert())
     {
-        BitmapScopedWriteAccess pWriteAcc(*this);
-        const tools::Long nWidth = pWriteAcc->Width();
-        const tools::Long nHeight = pWriteAcc->Height();
+        mxSalBmp->InvalidateChecksum();
+        return true;
+    }
 
-        for (tools::Long nY = 0; nY < nHeight; nY++)
+    BitmapScopedWriteAccess pWriteAcc(*this);
+    const tools::Long nWidth = pWriteAcc->Width();
+    const tools::Long nHeight = pWriteAcc->Height();
+
+    for (tools::Long nY = 0; nY < nHeight; nY++)
+    {
+        Scanline pScanline = pWriteAcc->GetScanline(nY);
+        for (tools::Long nX = 0; nX < nWidth; nX++)
         {
-            Scanline pScanline = pWriteAcc->GetScanline(nY);
-            for (tools::Long nX = 0; nX < nWidth; nX++)
-            {
-                BitmapColor aBmpColor = pWriteAcc->GetPixelFromData(pScanline, 
nX);
-                aBmpColor.Invert();
-                pWriteAcc->SetPixelOnData(pScanline, nX, aBmpColor);
-            }
+            BitmapColor aBmpColor = pWriteAcc->GetPixelFromData(pScanline, nX);
+            aBmpColor.Invert();
+            pWriteAcc->SetPixelOnData(pScanline, nX, aBmpColor);
         }
     }
 
@@ -607,6 +623,174 @@ Bitmap Bitmap::CreateMask(const Color& rTransColor, 
sal_uInt8 nTol) const
     return aNewBmp;
 }
 
+AlphaMask Bitmap::CreateAlphaMask(const Color& rTransColor) const
+{
+    ScopedReadAccess pReadAcc(const_cast<Bitmap&>(*this));
+    if (!pReadAcc)
+        return AlphaMask();
+
+    // Historically LO used 1bpp masks, but 8bpp masks are much faster,
+    // better supported by hardware, and the memory savings are not worth
+    // it anymore.
+
+    if ((pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal)
+        && pReadAcc->GetBestMatchingColor(COL_ALPHA_TRANSPARENT)
+               == pReadAcc->GetBestMatchingColor(rTransColor))
+    {
+        // if we're a 1 bit pixel already, and the transcolor matches the 
color that would replace it
+        // already, then just return a copy
+        return AlphaMask(*this);
+    }
+
+    AlphaMask aNewBmp(GetSizePixel());
+    BitmapScopedWriteAccess pWriteAcc(aNewBmp);
+    if (!pWriteAcc)
+        return AlphaMask();
+
+    const tools::Long nWidth = pReadAcc->Width();
+    const tools::Long nHeight = pReadAcc->Height();
+    const BitmapColor 
aOpaqueColor(pWriteAcc->GetBestMatchingColor(COL_ALPHA_OPAQUE));
+    const BitmapColor 
aTransparentColor(pWriteAcc->GetBestMatchingColor(COL_ALPHA_TRANSPARENT));
+
+    const BitmapColor aTest(pReadAcc->GetBestMatchingColor(rTransColor));
+
+    if (pReadAcc->GetScanlineFormat() == ScanlineFormat::N8BitPal)
+    {
+        // optimized for 8Bit source palette
+        const sal_uInt8 cTest = aTest.GetIndex();
+
+        for (tools::Long nY = 0; nY < nHeight; ++nY)
+        {
+            Scanline pSrc = pReadAcc->GetScanline(nY);
+            Scanline pDst = pWriteAcc->GetScanline(nY);
+            for (tools::Long nX = 0; nX < nWidth; ++nX)
+            {
+                if (cTest == pSrc[nX])
+                    pDst[nX] = aTransparentColor.GetIndex();
+                else
+                    pDst[nX] = aOpaqueColor.GetIndex();
+            }
+        }
+    }
+    else
+    {
+        // not optimized
+        for (tools::Long nY = 0; nY < nHeight; ++nY)
+        {
+            Scanline pScanline = pWriteAcc->GetScanline(nY);
+            Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+            for (tools::Long nX = 0; nX < nWidth; ++nX)
+            {
+                if (aTest == pReadAcc->GetPixelFromData(pScanlineRead, nX))
+                    pWriteAcc->SetPixelOnData(pScanline, nX, 
aTransparentColor);
+                else
+                    pWriteAcc->SetPixelOnData(pScanline, nX, aOpaqueColor);
+            }
+        }
+    }
+
+    pWriteAcc.reset();
+    pReadAcc.reset();
+
+    aNewBmp.maPrefSize = maPrefSize;
+    aNewBmp.maPrefMapMode = maPrefMapMode;
+
+    return aNewBmp;
+}
+
+AlphaMask Bitmap::CreateAlphaMask(const Color& rTransColor, sal_uInt8 nTol) 
const
+{
+    if (nTol == 0)
+        return CreateAlphaMask(rTransColor);
+
+    ScopedReadAccess pReadAcc(const_cast<Bitmap&>(*this));
+    if (!pReadAcc)
+        return AlphaMask();
+
+    // Historically LO used 1bpp masks, but 8bpp masks are much faster,
+    // better supported by hardware, and the memory savings are not worth
+    // it anymore.
+    // TODO: Possibly remove the 1bpp code later.
+
+    AlphaMask aNewBmp(GetSizePixel());
+    BitmapScopedWriteAccess pWriteAcc(aNewBmp);
+    if (!pWriteAcc)
+        return AlphaMask();
+
+    const tools::Long nWidth = pReadAcc->Width();
+    const tools::Long nHeight = pReadAcc->Height();
+    const BitmapColor 
aOpaqueColor(pWriteAcc->GetBestMatchingColor(COL_ALPHA_OPAQUE));
+    const BitmapColor 
aTransparentColor(pWriteAcc->GetBestMatchingColor(COL_ALPHA_TRANSPARENT));
+
+    BitmapColor aCol;
+    tools::Long nR, nG, nB;
+    const tools::Long nMinR = MinMax<tools::Long>(rTransColor.GetRed() - nTol, 
0, 255);
+    const tools::Long nMaxR = MinMax<tools::Long>(rTransColor.GetRed() + nTol, 
0, 255);
+    const tools::Long nMinG = MinMax<tools::Long>(rTransColor.GetGreen() - 
nTol, 0, 255);
+    const tools::Long nMaxG = MinMax<tools::Long>(rTransColor.GetGreen() + 
nTol, 0, 255);
+    const tools::Long nMinB = MinMax<tools::Long>(rTransColor.GetBlue() - 
nTol, 0, 255);
+    const tools::Long nMaxB = MinMax<tools::Long>(rTransColor.GetBlue() + 
nTol, 0, 255);
+
+    if (pReadAcc->HasPalette())
+    {
+        for (tools::Long nY = 0; nY < nHeight; nY++)
+        {
+            Scanline pScanline = pWriteAcc->GetScanline(nY);
+            Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+            for (tools::Long nX = 0; nX < nWidth; nX++)
+            {
+                aCol = 
pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
+                nR = aCol.GetRed();
+                nG = aCol.GetGreen();
+                nB = aCol.GetBlue();
+
+                if (nMinR <= nR && nMaxR >= nR && nMinG <= nG && nMaxG >= nG 
&& nMinB <= nB
+                    && nMaxB >= nB)
+                {
+                    pWriteAcc->SetPixelOnData(pScanline, nX, 
aTransparentColor);
+                }
+                else
+                {
+                    pWriteAcc->SetPixelOnData(pScanline, nX, aOpaqueColor);
+                }
+            }
+        }
+    }
+    else
+    {
+        for (tools::Long nY = 0; nY < nHeight; nY++)
+        {
+            Scanline pScanline = pWriteAcc->GetScanline(nY);
+            Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+            for (tools::Long nX = 0; nX < nWidth; nX++)
+            {
+                aCol = pReadAcc->GetPixelFromData(pScanlineRead, nX);
+                nR = aCol.GetRed();
+                nG = aCol.GetGreen();
+                nB = aCol.GetBlue();
+
+                if (nMinR <= nR && nMaxR >= nR && nMinG <= nG && nMaxG >= nG 
&& nMinB <= nB
+                    && nMaxB >= nB)
+                {
+                    pWriteAcc->SetPixelOnData(pScanline, nX, 
aTransparentColor);
+                }
+                else
+                {
+                    pWriteAcc->SetPixelOnData(pScanline, nX, aOpaqueColor);
+                }
+            }
+        }
+    }
+
+    pWriteAcc.reset();
+    pReadAcc.reset();
+
+    aNewBmp.maPrefSize = maPrefSize;
+    aNewBmp.maPrefMapMode = maPrefMapMode;
+
+    return aNewBmp;
+}
+
 vcl::Region Bitmap::CreateRegion(const Color& rColor, const tools::Rectangle& 
rRect) const
 {
     tools::Rectangle aRect(rRect);
@@ -721,7 +905,7 @@ bool Bitmap::Replace(const AlphaMask& rAlpha, const Color& 
rMergeColor)
         for (tools::Long nX = 0; nX < nWidth; nX++)
         {
             aCol = pAcc->GetColor(nY, nX);
-            aCol.Merge(rMergeColor, 255 - 
pAlphaAcc->GetIndexFromData(pScanlineAlpha, nX));
+            aCol.Merge(rMergeColor, 
pAlphaAcc->GetIndexFromData(pScanlineAlpha, nX));
             pNewAcc->SetPixelOnData(pScanline, nX, aCol);
         }
     }
@@ -965,8 +1149,7 @@ bool Bitmap::Blend(const AlphaMask& rAlpha, const Color& 
rBackgroundColor)
         for (tools::Long nX = 0; nX < nWidth; ++nX)
         {
             BitmapColor aBmpColor = pAcc->GetPixelFromData(pScanline, nX);
-            aBmpColor.Merge(rBackgroundColor,
-                            255 - pAlphaAcc->GetIndexFromData(pScanlineAlpha, 
nX));
+            aBmpColor.Merge(rBackgroundColor, 
pAlphaAcc->GetIndexFromData(pScanlineAlpha, nX));
             pAcc->SetPixelOnData(pScanline, nX, aBmpColor);
         }
     }
diff --git a/vcl/source/bitmap/dibtools.cxx b/vcl/source/bitmap/dibtools.cxx
index d8fa61362635..d6ac43a403da 100644
--- a/vcl/source/bitmap/dibtools.cxx
+++ b/vcl/source/bitmap/dibtools.cxx
@@ -1699,7 +1699,11 @@ bool ReadDIBV5(
     AlphaMask& rTargetAlpha,
     SvStream& rIStm)
 {
-    return ImplReadDIB(rTarget, &rTargetAlpha, rIStm, true);
+    bool rv = ImplReadDIB(rTarget, &rTargetAlpha, rIStm, true);
+    // convert transparency->alpha
+    if (rv)
+        rTargetAlpha.Invert();
+    return rv;
 }
 
 bool ReadRawDIB(
@@ -1747,7 +1751,10 @@ bool WriteDIBBitmapEx(
 
         if(rSource.IsAlpha())
         {
-            return ImplWriteDIB(rSource.maAlphaMask, rOStm, true, true);
+            // invert the alpha because the other routines actually want 
transparency
+            AlphaMask tmpAlpha = rSource.maAlphaMask;
+            tmpAlpha.Invert();
+            return ImplWriteDIB(tmpAlpha, rOStm, true, true);
         }
     }
 
diff --git a/vcl/source/filter/eps/eps.cxx b/vcl/source/filter/eps/eps.cxx
index 455e89cc543a..a107a5d400c6 100644
--- a/vcl/source/filter/eps/eps.cxx
+++ b/vcl/source/filter/eps/eps.cxx
@@ -200,7 +200,7 @@ private:
     void                ImplPolyLine( const tools::Polygon & rPolygon );
 
     void                ImplSetClipRegion( vcl::Region const & rRegion );
-    void                ImplBmp( Bitmap const *, Bitmap const *, const Point 
&, double nWidth, double nHeight );
+    void                ImplBmp( Bitmap const *, AlphaMask const *, const 
Point &, double nWidth, double nHeight );
     void                ImplText( const OUString& rUniString, const Point& 
rPos, KernArraySpan pDXArry, o3tl::span<const sal_Bool> pKashidaArry, sal_Int32 
nWidth, VirtualDevice const & rVDev );
     void                ImplSetAttrForText( const Point & rPoint );
     void                ImplWriteCharacter( char );
@@ -1641,7 +1641,7 @@ void PSWriter::ImplSetClipRegion( vcl::Region const & 
rClipRegion )
 //          color       1(pal), 4(pal), 8(pal), 24 Bit
 //
 
-void PSWriter::ImplBmp( Bitmap const * pBitmap, Bitmap const * pMaskBitmap, 
const Point & rPoint, double nXWidth, double nYHeightOrg )
+void PSWriter::ImplBmp( Bitmap const * pBitmap, AlphaMask const * 
pAlphaMaskBitmap, const Point & rPoint, double nXWidth, double nYHeightOrg )
 {
     if ( !pBitmap )
         return;
@@ -1662,7 +1662,7 @@ void PSWriter::ImplBmp( Bitmap const * pBitmap, Bitmap 
const * pMaskBitmap, cons
         tools::Rectangle   aRect;
         vcl::Region      aRegion;
 
-        if ( pMaskBitmap )
+        if ( pAlphaMaskBitmap )
         {
             bDoTrans = true;
             while (true)
@@ -1670,7 +1670,7 @@ void PSWriter::ImplBmp( Bitmap const * pBitmap, Bitmap 
const * pMaskBitmap, cons
                 if ( mnLevel == 1 && nHeight > 10 )
                     nHeight = 8;
                 aRect = tools::Rectangle( Point( 0, nHeightOrg - nHeightLeft 
), Size( nWidth, nHeight ) );
-                aRegion = pMaskBitmap->CreateRegion( COL_BLACK, aRect );
+                aRegion = pAlphaMaskBitmap->CreateRegion( COL_ALPHA_OPAQUE, 
aRect );
 
                 if( mnLevel == 1 )
                 {
diff --git a/vcl/source/filter/igif/gifread.cxx 
b/vcl/source/filter/igif/gifread.cxx
index 7cdc37710f51..818317f8baa8 100644
--- a/vcl/source/filter/igif/gifread.cxx
+++ b/vcl/source/filter/igif/gifread.cxx
@@ -661,7 +661,9 @@ void GIFReader::CreateNewBitmaps()
     if( bGCTransparent )
     {
         pAcc1.reset();
-        aAnimationFrame.maBitmapEx = BitmapEx( aBmp8, aBmp1 );
+        AlphaMask aAlphaMask(aBmp1);
+        aAlphaMask.Invert(); // convert from transparency to alpha
+        aAnimationFrame.maBitmapEx = BitmapEx( aBmp8, aAlphaMask );
     }
     else
         aAnimationFrame.maBitmapEx = BitmapEx( aBmp8 );
diff --git a/vcl/source/filter/ipdf/pdfread.cxx 
b/vcl/source/filter/ipdf/pdfread.cxx
index e3d70f7c0ade..18f8c4dee95e 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -102,8 +102,7 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, 
std::vector<BitmapEx>& r
                 pWriteAccess->CopyScanline(nRow, pPdfLine, 
ScanlineFormat::N32BitTcBgra, nStride);
                 for (int nCol = 0; nCol < nPageWidth; ++nCol)
                 {
-                    // Invert alpha (source is alpha, target is opacity).
-                    aScanlineAlpha[nCol] = ~pPdfLine[3];
+                    aScanlineAlpha[nCol] = pPdfLine[3];
                     pPdfLine += 4;
                 }
                 pMaskAccess->CopyScanline(nRow, aScanlineAlpha.data(), 
ScanlineFormat::N8BitPal,
diff --git a/vcl/source/filter/ipsd/ipsd.cxx b/vcl/source/filter/ipsd/ipsd.cxx
index 0ded0938efef..79ccda943dca 100644
--- a/vcl/source/filter/ipsd/ipsd.cxx
+++ b/vcl/source/filter/ipsd/ipsd.cxx
@@ -727,7 +727,7 @@ bool PSDReader::ImplReadBody()
                     m_rPSD.ReadUChar( nDummy );
                 for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
                 {
-                    mpBitmap->SetAlpha(nY, nX, nDat ? 0 : 255);
+                    mpBitmap->SetAlpha(nY, nX, nDat ? 255 : 0);
                     if ( ++nX == mpFileHeader->nColumns )
                     {
                         nX = 0;
@@ -748,7 +748,7 @@ bool PSDReader::ImplReadBody()
                         nDat = 1;
                     if ( mpFileHeader->nDepth == 16 )   // 16 bit depth is to 
be skipped
                         m_rPSD.ReadUChar( nDummy );
-                    mpBitmap->SetAlpha(nY, nX, nDat ? 0 : 255);
+                    mpBitmap->SetAlpha(nY, nX, nDat ? 255 : 0);
                     if ( ++nX == mpFileHeader->nColumns )
                     {
                         nX = 0;
diff --git a/vcl/source/filter/itiff/itiff.cxx 
b/vcl/source/filter/itiff/itiff.cxx
index 439cbd856182..bdbf0309e296 100644
--- a/vcl/source/filter/itiff/itiff.cxx
+++ b/vcl/source/filter/itiff/itiff.cxx
@@ -277,7 +277,7 @@ bool ImportTiffGraphicImport(SvStream& rTIFF, Graphic& 
rGraphic)
                     }
 
                     access->SetPixel(y, dest, Color(r, g, b));
-                    accessAlpha->SetPixelIndex(y, dest, 255 - a);
+                    accessAlpha->SetPixelIndex(y, dest, a);
                     ++src;
                 }
             }
diff --git a/vcl/source/filter/jpeg/JpegReader.cxx 
b/vcl/source/filter/jpeg/JpegReader.cxx
index 8d190200face..186105603904 100644
--- a/vcl/source/filter/jpeg/JpegReader.cxx
+++ b/vcl/source/filter/jpeg/JpegReader.cxx
@@ -249,8 +249,8 @@ Graphic JPEGReader::CreateIntermediateGraphic(tools::Long 
nLines)
 
     if (!mnLastLines)
     {
-        mpIncompleteAlpha.emplace(aSizePixel, vcl::PixelFormat::N8_BPP, 
&Bitmap::GetGreyPalette(256));
-        mpIncompleteAlpha->Erase(COL_WHITE);
+        mpIncompleteAlpha.emplace(aSizePixel);
+        mpIncompleteAlpha->Erase(255);
     }
 
     if (nLines && (nLines < aSizePixel.Height()))
@@ -261,7 +261,7 @@ Graphic JPEGReader::CreateIntermediateGraphic(tools::Long 
nLines)
         {
             {
                 BitmapScopedWriteAccess pAccess(*mpIncompleteAlpha);
-                pAccess->SetFillColor(COL_BLACK);
+                pAccess->SetFillColor(COL_ALPHA_OPAQUE);
                 pAccess->FillRect(tools::Rectangle(Point(0, mnLastLines), 
Size(pAccess->Width(), nNewLines)));
             }
 
diff --git a/vcl/source/filter/jpeg/JpegReader.hxx 
b/vcl/source/filter/jpeg/JpegReader.hxx
index a4df7e212119..576027237ab8 100644
--- a/vcl/source/filter/jpeg/JpegReader.hxx
+++ b/vcl/source/filter/jpeg/JpegReader.hxx
@@ -49,7 +49,7 @@ class JPEGReader : public GraphicReader
 {
     SvStream&           mrStream;
     std::optional<Bitmap> mpBitmap;
-    std::optional<Bitmap> mpIncompleteAlpha;
+    std::optional<AlphaMask> mpIncompleteAlpha;
 
     tools::Long                mnLastPos;
     tools::Long                mnLastLines;
diff --git a/vcl/source/filter/png/PngImageReader.cxx 
b/vcl/source/filter/png/PngImageReader.cxx
index e7b5c414762b..fcdcd210a157 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -465,6 +465,7 @@ bool reader(SvStream& rStream, Graphic& rGraphic,
                 {
                     aBitmap = Bitmap(Size(width, height), 
vcl::PixelFormat::N24_BPP);
                     aBitmapAlpha = AlphaMask(Size(width, height), nullptr);
+                    aBitmapAlpha.Erase(0); // opaque
                 }
                 break;
             case PNG_COLOR_TYPE_GRAY:
@@ -605,7 +606,7 @@ bool reader(SvStream& rStream, Graphic& rGraphic,
                         pScanline[iColor++] = pRow[i + 0];
                         pScanline[iColor++] = pRow[i + 1];
                         pScanline[iColor++] = pRow[i + 2];
-                        pScanAlpha[iAlpha++] = 0xFF - pRow[i + 3];
+                        pScanAlpha[iAlpha++] = pRow[i + 3];
                     }
                 }
             }
@@ -629,7 +630,7 @@ bool reader(SvStream& rStream, Graphic& rGraphic,
                             pScanline[iColor++] = pRow[i + 0];
                             pScanline[iColor++] = pRow[i + 1];
                             pScanline[iColor++] = pRow[i + 2];
-                            pScanAlpha[iAlpha++] = 0xFF - pRow[i + 3];
+                            pScanAlpha[iAlpha++] = pRow[i + 3];
                         }
                     }
                 }

... etc. - the rest is truncated

Reply via email to