[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-1+backports' - include/vcl vcl/opengl vcl/qa vcl/quartz vcl/source

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Sat Jul 18 12:28:26 UTC 2020


 include/vcl/bitmap.hxx                           |    3 
 include/vcl/salbtype.hxx                         |    6 
 vcl/opengl/salbmp.cxx                            |   12 -
 vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx |  167 +++++++++++++++++++++++
 vcl/qa/cppunit/bitmaprender/data/tdf116888.gif   |binary
 vcl/qa/cppunit/jpeg/JpegWriterTest.cxx           |  105 ++++++++++++++
 vcl/quartz/salbmp.cxx                            |    2 
 vcl/source/bitmap/bitmap.cxx                     |   34 ++++
 vcl/source/filter/jpeg/JpegWriter.cxx            |    2 
 vcl/source/gdi/alpha.cxx                         |    2 
 vcl/source/gdi/bitmap3.cxx                       |    4 
 vcl/source/gdi/dibtools.cxx                      |    4 
 vcl/source/gdi/pdfwriter_impl.cxx                |    2 
 13 files changed, 326 insertions(+), 17 deletions(-)

New commits:
commit b2e8d6e4cd263df09466549da7ffe91c9e3e1e96
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Sat Jun 27 14:48:36 2020 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Sat Jul 18 14:27:52 2020 +0200

    differentiate between 8bit and any-bit grey palette (tdf#121120)
    
    Only the grey palette with 256 colors means that pixel values map
    directly to color values. Tdf#121120 has an image with 2-bit
    palette where color index 1 is (255,255,255), but that means
    the pixel value 1 cannot be just treated as color.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97283
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>
    (cherry picked from commit 29dc1029be6d8d02f4b639b32274a286afd0b1b3)
    
    Change-Id: Ifbd953af7f291e4fb8032ea0f4c33c0514770856
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/98933
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index b304baa5af01..8cb830d56ae4 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -150,7 +150,8 @@ public:
     sal_uInt16              GetBitCount() const;
     inline sal_uLong        GetColorCount() const;
     inline sal_uLong        GetSizeBytes() const;
-    bool                    HasGreyPalette() const;
+    bool                    HasGreyPalette8Bit() const;
+    bool                    HasGreyPaletteAny() const;
     /** get system dependent bitmap data
 
         @param rData
diff --git a/include/vcl/salbtype.hxx b/include/vcl/salbtype.hxx
index b965fa333c08..f825023a3db3 100644
--- a/include/vcl/salbtype.hxx
+++ b/include/vcl/salbtype.hxx
@@ -246,6 +246,12 @@ public:
     }
 
     bool IsGreyPalette() const;
+
+    /// Returns true if the palette is 8-bit grey palette.
+    bool IsGreyPalette8Bit() const;
+    /// Returns true if the palette is a grey palette (may not be 8-bit).
+    bool IsGreyPaletteAny() const;
+
 };
 
 struct VCL_DLLPUBLIC ColorMaskElement
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 6e497ff71d74..46843a98e8e2 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -496,9 +496,9 @@ GLuint OpenGLSalBitmap::CreateTexture()
 
             determineTextureFormat(mnBits, nFormat, nType);
         }
-        else if( mnBits == 8 && maPalette.IsGreyPalette() )
+        else if( mnBits == 8 && maPalette.IsGreyPalette8Bit() )
         {
-            // no conversion needed for grayscale
+            // no conversion needed for 8bit grayscale
             pData = mpUserBuffer.get();
             nFormat = GL_LUMINANCE;
             nType = GL_UNSIGNED_BYTE;
@@ -582,7 +582,8 @@ bool OpenGLSalBitmap::ReadTexture()
     xContext->state().scissor().disable();
     xContext->state().stencil().disable();
 
-    if ((mnBits == 8 && maPalette.IsGreyPalette()) || mnBits == 16 || mnBits == 24 || mnBits == 32)
+
+    if ((mnBits == 8 && maPalette.IsGreyPalette8Bit()) || mnBits == 24 || mnBits == 32)
     {
         determineTextureFormat(mnBits, nFormat, nType);
 
@@ -929,8 +930,9 @@ bool OpenGLSalBitmap::ConvertToGreyscale()
     VCL_GL_INFO("::ConvertToGreyscale");
 
     // avoid re-converting to 8bits.
-    if ( mnBits == 8 && maPalette == Bitmap::GetGreyPalette(256) )
-        return false;
+
+    if ( mnBits == 8 && maPalette.IsGreyPalette8Bit())
+        return true;
 
     OpenGLZone aZone;
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
diff --git a/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx b/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx
index c2455e1e4e16..b2e039280354 100644
--- a/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx
+++ b/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx
@@ -38,10 +38,16 @@ public:
 
     void testTdf104141();
     void testTdf113918();
+    //void testDrawAlphaBitmapEx();
+    //void testAlphaVirtualDevice();
+    void testTdf116888();
 
     CPPUNIT_TEST_SUITE(BitmapRenderTest);
     CPPUNIT_TEST(testTdf104141);
     CPPUNIT_TEST(testTdf113918);
+    //CPPUNIT_TEST(testDrawAlphaBitmapEx);
+    //CPPUNIT_TEST(testAlphaVirtualDevice);
+    CPPUNIT_TEST(testTdf116888);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -95,6 +101,167 @@ void BitmapRenderTest::testTdf113918()
     CPPUNIT_ASSERT(aColor.GetGreen() == aColor.GetRed() && aColor.GetGreen() == aColor.GetBlue());
     CPPUNIT_ASSERT(aColor.GetGreen() > 100);
 }
+/*
+void BitmapRenderTest::testDrawAlphaBitmapEx()
+{
+    ScopedVclPtrInstance<VirtualDevice> pVDev;
+    pVDev->SetOutputSizePixel(Size(8, 8));
+    pVDev->SetBackground(Wallpaper(COL_WHITE));
+    pVDev->Erase();
+
+    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(0, 0)));
+    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(1, 1)));
+    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(2, 2)));
+
+    SvFileStream aFileStream(getFullUrl("ImageRGBA.png"), StreamMode::READ);
+
+    vcl::PngImageReader aPngReader(aFileStream);
+    BitmapEx aBitmapEx;
+    aPngReader.read(aBitmapEx);
+
+    // Check backend capabilities, if the backend support 32-bit bitmap
+    auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
+    if (pBackendCapabilities->mbSupportsBitmap32)
+    {
+        CPPUNIT_ASSERT_EQUAL(sal_uInt16(32), aBitmapEx.GetBitmap().GetBitCount());
+    }
+    else
+    {
+        CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), aBitmapEx.GetBitmap().GetBitCount());
+        CPPUNIT_ASSERT_EQUAL(true, aBitmapEx.IsAlpha());
+        CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), aBitmapEx.GetAlpha().GetBitCount());
+    }
+
+    // Check the bitmap has pixels we expect
+    CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0x00, 0x00, 0x00), aBitmapEx.GetPixelColor(0, 0));
+    CPPUNIT_ASSERT_EQUAL(Color(0x00, 0xFF, 0xFF, 0x00), aBitmapEx.GetPixelColor(1, 1));
+    CPPUNIT_ASSERT_EQUAL(Color(0x7F, 0x00, 0xFF, 0x00), aBitmapEx.GetPixelColor(2, 2));
+
+    pVDev->DrawBitmapEx(Point(), aBitmapEx);
+
+    CPPUNIT_ASSERT_EQUAL(Color(0x00, 0xFF, 0xFF, 0xFF), pVDev->GetPixel(Point(0, 0)));
+    CPPUNIT_ASSERT_EQUAL(Color(0x00, 0xFF, 0xFF, 0x00), pVDev->GetPixel(Point(1, 1)));
+
+// sometimes on Windows we get rounding error in blending so let's ignore this on Windows for now.
+#if !defined(_WIN32)
+    CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x7F, 0xFF, 0x7F), pVDev->GetPixel(Point(2, 2)));
+#endif
+}
+
+#ifdef _WIN32
+
+namespace
+{
+int deltaColor(BitmapColor aColor1, BitmapColor aColor2)
+{
+    int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed());
+    int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen());
+    int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue());
+
+    return std::max(std::max(deltaR, deltaG), deltaB);
+}
+}
+
+#endif
+
+void BitmapRenderTest::testAlphaVirtualDevice()
+{
+    // Create an alpha virtual device
+    ScopedVclPtr<VirtualDevice> pAlphaVirtualDevice(VclPtr<VirtualDevice>::Create(
+        *Application::GetDefaultDevice(), DeviceFormat::DEFAULT, DeviceFormat::DEFAULT));
+
+    // Set it up
+    pAlphaVirtualDevice->SetOutputSizePixel(Size(4, 4));
+    pAlphaVirtualDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
+    pAlphaVirtualDevice->Erase();
+
+    // Get a BitmapEx from the VirDev -> Colors should have alpha
+    BitmapEx aBitmap = pAlphaVirtualDevice->GetBitmapEx(Point(), Size(4, 4));
+    CPPUNIT_ASSERT_EQUAL(long(4), aBitmap.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(long(4), aBitmap.GetSizePixel().Height());
+    Color aColor = aBitmap.GetPixelColor(1, 1);
+    CPPUNIT_ASSERT_EQUAL(Color(0xffffffff), aColor);
+
+    // Draw an opaque pixel to the VirDev
+    pAlphaVirtualDevice->DrawPixel(Point(1, 1), Color(0x0022ff55));
+
+    aColor = pAlphaVirtualDevice->GetPixel(Point(1, 1));
+    // Read back the opaque pixel
+#if defined _WIN32
+    CPPUNIT_ASSERT_LESS(6, deltaColor(Color(0x0022ff55), aColor));
+#else
+    CPPUNIT_ASSERT_EQUAL(Color(0x0022ff55), aColor);
+#endif
+
+    // Read back the BitmapEx and check the opaque pixel
+    aBitmap = pAlphaVirtualDevice->GetBitmapEx(Point(), Size(4, 4));
+    CPPUNIT_ASSERT_EQUAL(long(4), aBitmap.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(long(4), aBitmap.GetSizePixel().Height());
+
+    aColor = aBitmap.GetPixelColor(1, 1);
+#if defined _WIN32
+    CPPUNIT_ASSERT_LESS(6, deltaColor(Color(0x0022ff55), aColor));
+#else
+    CPPUNIT_ASSERT_EQUAL(Color(0x0022ff55), aColor);
+#endif
+
+    // Draw an semi-transparent pixel
+    pAlphaVirtualDevice->DrawPixel(Point(0, 0), Color(0x44, 0x22, 0xff, 0x55));
+
+    aColor = pAlphaVirtualDevice->GetPixel(Point(0, 0));
+    // Read back the semi-transparent pixel
+#if defined _WIN32
+    CPPUNIT_ASSERT_LESS(6, deltaColor(Color(0x4422FF55), aColor));
+#else
+    CPPUNIT_ASSERT_EQUAL(Color(0x4422FF55), aColor);
+#endif
+
+    // Read back the BitmapEx and check the semi-transparent pixel
+    aBitmap = pAlphaVirtualDevice->GetBitmapEx(Point(), Size(4, 4));
+    CPPUNIT_ASSERT_EQUAL(long(4), aBitmap.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(long(4), aBitmap.GetSizePixel().Height());
+
+    aColor = aBitmap.GetPixelColor(0, 0);
+#if defined _WIN32
+    CPPUNIT_ASSERT_LESS(6, deltaColor(Color(0x4422FF55), aColor));
+#else
+    CPPUNIT_ASSERT_EQUAL(Color(0x4422FF55), aColor);
+#endif
+}*/
+
+void BitmapRenderTest::testTdf116888()
+{
+    // The image is a 8bit image with a non-grayscale palette. In OpenGL mode
+    // pdf export of the image was broken, because OpenGLSalBitmap::ReadTexture()
+    // didn't handle 8bit non-grayscale and moreover OpenGLSalBitmap::AcquireBuffer()
+    // didn't properly release mpUserBuffer after ReadTexture() failure.
+    GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+    Graphic aGraphic;
+    const OUString aURL(getFullUrl("tdf116888.gif"));
+    SvFileStream aFileStream(aURL, StreamMode::READ);
+    ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+    CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+    Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+    CPPUNIT_ASSERT(!aBitmap.IsEmpty());
+    aBitmap.Scale(0.8, 0.8); // This scaling discards mpUserData,
+    Bitmap::ScopedReadAccess pAccess(aBitmap); // forcing ReadTexture() here.
+    // Check that there is mpUserBuffer content.
+    CPPUNIT_ASSERT(pAccess);
+    const ScanlineFormat eFormat = pAccess->GetScanlineFormat();
+    CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, eFormat);
+    CPPUNIT_ASSERT(!aBitmap.HasGreyPaletteAny());
+    // HACK: Some rendering backends change white to #FEFEFE while scaling for some reason.
+    // That is pretty much white too in practice, so adjust for that.
+    BitmapColor white(COL_WHITE);
+    if (pAccess->GetColor(0, 0) == Color(0xfe, 0xfe, 0xfe))
+        white = Color(0xfe, 0xfe, 0xfe);
+    // Check that the image contents are also valid.
+    CPPUNIT_ASSERT_EQUAL(white, pAccess->GetColor(0, 0));
+    CPPUNIT_ASSERT_EQUAL(white, pAccess->GetColor(0, pAccess->Width() - 1));
+    CPPUNIT_ASSERT_EQUAL(white, pAccess->GetColor(pAccess->Height() - 1, 0));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+                         pAccess->GetColor(pAccess->Height() - 1, pAccess->Width() - 1));
+}
 
 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapRenderTest);
 
diff --git a/vcl/qa/cppunit/bitmaprender/data/tdf116888.gif b/vcl/qa/cppunit/bitmaprender/data/tdf116888.gif
new file mode 100644
index 000000000000..2953109491c4
Binary files /dev/null and b/vcl/qa/cppunit/bitmaprender/data/tdf116888.gif differ
diff --git a/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx b/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx
new file mode 100644
index 000000000000..b4d9d24603eb
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <tools/stream.hxx>
+
+static OUString const gaDataUrl("/vcl/qa/cppunit/jpeg/data/");
+
+class JpegWriterTest : public test::BootstrapFixtureBase
+{
+    OUString getFullUrl(const OUString& sFileName)
+    {
+        return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+    }
+
+    BitmapEx load(const OUString& aURL);
+    BitmapEx roundtripJPG(const BitmapEx& bitmap);
+    BitmapEx roundtripJPG(const OUString& aURL);
+
+public:
+    void testWrite8BitGrayscale();
+    void testWrite8BitNonGrayscale();
+
+    CPPUNIT_TEST_SUITE(JpegWriterTest);
+    CPPUNIT_TEST(testWrite8BitGrayscale);
+    CPPUNIT_TEST(testWrite8BitNonGrayscale);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+BitmapEx JpegWriterTest::load(const OUString& aURL)
+{
+    GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+    Graphic aGraphic;
+    SvFileStream aFileStream(aURL, StreamMode::READ);
+    ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+    CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+    return aGraphic.GetBitmapEx();
+}
+
+BitmapEx JpegWriterTest::roundtripJPG(const OUString& aURL) { return roundtripJPG(load(aURL)); }
+
+BitmapEx JpegWriterTest::roundtripJPG(const BitmapEx& bitmap)
+{
+    SvMemoryStream stream;
+    GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+    sal_uInt16 exportFormatJPG = rFilter.GetExportFormatNumberForShortName(JPG_SHORTNAME);
+    Graphic aExportGraphic(bitmap);
+    ErrCode bResult = rFilter.ExportGraphic(aExportGraphic, "memory", stream, exportFormatJPG);
+    CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+    stream.Seek(0);
+    Graphic aImportGraphic;
+    sal_uInt16 importFormatJPG = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
+    bResult = rFilter.ImportGraphic(aImportGraphic, "memory", stream, importFormatJPG);
+    CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+    return aImportGraphic.GetBitmapEx();
+}
+
+void JpegWriterTest::testWrite8BitGrayscale()
+{
+    Bitmap bitmap = roundtripJPG(getFullUrl("8BitGrayscale.jpg")).GetBitmap();
+    Bitmap::ScopedReadAccess access(bitmap);
+    const ScanlineFormat format = access->GetScanlineFormat();
+    // Check that it's still 8bit grayscale.
+    CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, format);
+    CPPUNIT_ASSERT(bitmap.HasGreyPalette8Bit());
+    // Check that the content is valid.
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, 0));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, access->Width() - 1));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(access->Height() - 1, 0));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+                         access->GetColor(access->Height() - 1, access->Width() - 1));
+}
+
+void JpegWriterTest::testWrite8BitNonGrayscale()
+{
+    Bitmap bitmap = roundtripJPG(getFullUrl("8BitNonGrayscale.gif")).GetBitmap();
+    Bitmap::ScopedReadAccess access(bitmap);
+    const ScanlineFormat format = access->GetScanlineFormat();
+    // Check that it's still 8bit grayscale.
+    CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, format);
+    // The original image has grayscale palette, just with entries in a different order.
+    // Do not check for grayscale 8bit, the roundtrip apparently fixes that. What's important
+    // is the content.
+    CPPUNIT_ASSERT(bitmap.HasGreyPaletteAny());
+    // CPPUNIT_ASSERT(bitmap.HasGreyPalette8Bit());
+    // Check that the content is valid.
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, 0));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, access->Width() - 1));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(access->Height() - 1, 0));
+    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+                         access->GetColor(access->Height() - 1, access->Width() - 1));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(JpegWriterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx
index d7de93591f8a..32c2fce50c37 100644
--- a/vcl/quartz/salbmp.cxx
+++ b/vcl/quartz/salbmp.cxx
@@ -256,7 +256,7 @@ bool QuartzSalBitmap::CreateContext()
         // no conversion needed for truecolor
         m_pContextBuffer = m_pUserBuffer;
     }
-    else if( mnBits == 8 && maPalette.IsGreyPalette() )
+    else if( mnBits == 8 && maPalette.IsGreyPalette8Bit() )
     {
         // no conversion needed for grayscale
         m_pContextBuffer = m_pUserBuffer;
diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx
index 2de0da7b1a72..89f580f4f8e8 100644
--- a/vcl/source/bitmap/bitmap.cxx
+++ b/vcl/source/bitmap/bitmap.cxx
@@ -182,7 +182,7 @@ const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
     }
 }
 
-bool BitmapPalette::IsGreyPalette() const
+bool BitmapPalette::IsGreyPaletteAny() const
 {
     const int nEntryCount = GetEntryCount();
     if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
@@ -207,6 +207,21 @@ bool BitmapPalette::IsGreyPalette() const
     return bRet;
 }
 
+bool BitmapPalette::IsGreyPalette8Bit() const
+{
+    const int nEntryCount = GetEntryCount();
+    if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
+        return true;
+    if( nEntryCount != 256 )
+        return false;
+    for (sal_uInt16 i = 0; i < 256; ++i)
+    {
+        if( maBitmapColor[i] != BitmapColor(i, i, i))
+            return false;
+    }
+    return true;
+}
+
 Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
 {
     if (this == &rBitmap)
@@ -264,7 +279,7 @@ sal_uInt16 Bitmap::GetBitCount() const
                                 ( ( nBitCount <= 8 ) ? 8 : 24);
 }
 
-bool Bitmap::HasGreyPalette() const
+bool Bitmap::HasGreyPaletteAny() const
 {
     const sal_uInt16    nBitCount = GetBitCount();
     bool            bRet = nBitCount == 1;
@@ -273,7 +288,20 @@ bool Bitmap::HasGreyPalette() const
 
     if( pIAcc )
     {
-        bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPalette();
+        bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPaletteAny();
+    }
+
+    return bRet;
+}
+
+bool Bitmap::HasGreyPalette8Bit() const
+{
+    bool            bRet = false;
+    ScopedInfoAccess pIAcc(const_cast<Bitmap&>(*this));
+
+    if( pIAcc )
+    {
+        bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPalette8Bit();
     }
 
     return bRet;
diff --git a/vcl/source/filter/jpeg/JpegWriter.cxx b/vcl/source/filter/jpeg/JpegWriter.cxx
index c7a476a84de6..5314738c7d2e 100644
--- a/vcl/source/filter/jpeg/JpegWriter.cxx
+++ b/vcl/source/filter/jpeg/JpegWriter.cxx
@@ -224,7 +224,7 @@ bool JPEGWriter::Write( const Graphic& rGraphic )
             *mpExpWasGrey = mbGreys;
 
         if ( mbGreys )
-            mbNative = ( mpReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal );
+            mbNative = ( mpReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal && aGraphicBmp.HasGreyPalette8Bit());
         else
             mbNative = ( mpReadAccess->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb );
 
diff --git a/vcl/source/gdi/alpha.cxx b/vcl/source/gdi/alpha.cxx
index 4f39015287a9..e47043dd47ba 100644
--- a/vcl/source/gdi/alpha.cxx
+++ b/vcl/source/gdi/alpha.cxx
@@ -62,7 +62,7 @@ const Bitmap& AlphaMask::ImplGetBitmap() const
 void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap )
 {
     SAL_WARN_IF( 8 != rBitmap.GetBitCount(), "vcl.gdi", "Bitmap should be 8bpp, not " << rBitmap.GetBitCount() << "bpp" );
-    SAL_WARN_IF( !rBitmap.HasGreyPalette(), "vcl.gdi", "Bitmap isn't greyscale" );
+    SAL_WARN_IF( !rBitmap.HasGreyPalette8Bit(), "vcl.gdi", "Bitmap isn't greyscale" );
     *static_cast<Bitmap*>(this) = rBitmap;
 }
 
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index e178a0c845b3..291845effe44 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -849,7 +849,7 @@ void Bitmap::AdaptBitCount(Bitmap& rNew) const
             }
             case 4:
             {
-                if(HasGreyPalette())
+                if(HasGreyPaletteAny())
                 {
                     rNew.Convert(BmpConversion::N4BitGreys);
                 }
@@ -861,7 +861,7 @@ void Bitmap::AdaptBitCount(Bitmap& rNew) const
             }
             case 8:
             {
-                if(HasGreyPalette())
+                if(HasGreyPaletteAny())
                 {
                     rNew.Convert(BmpConversion::N8BitGreys);
                 }
diff --git a/vcl/source/gdi/dibtools.cxx b/vcl/source/gdi/dibtools.cxx
index 4088d6287894..8cb3d635726f 100644
--- a/vcl/source/gdi/dibtools.cxx
+++ b/vcl/source/gdi/dibtools.cxx
@@ -995,7 +995,7 @@ bool ImplReadDIBBody(SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_uL
     const BitmapPalette* pPal = &aPalette;
     //ofz#948 match the surrounding logic of case TransparentType::Bitmap of
     //ReadDIBBitmapEx but do it while reading for performance
-    const bool bIsAlpha = (nBitCount == 8 && !!aPalette && aPalette.IsGreyPalette());
+    const bool bIsAlpha = (nBitCount == 8 && !!aPalette && aPalette.IsGreyPalette8Bit());
     const bool bForceToMonoWhileReading = (bIsMask && !bIsAlpha && nBitCount != 1);
     if (bForceToMonoWhileReading)
     {
@@ -1775,7 +1775,7 @@ bool ReadDIBBitmapEx(
                             if(!!aMask)
                             {
                                 // do we have an alpha mask?
-                                if((8 == aMask.GetBitCount()) && aMask.HasGreyPalette())
+                                if((8 == aMask.GetBitCount()) && aMask.HasGreyPalette8Bit())
                                 {
                                     AlphaMask aAlpha;
 
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index d9411779fb34..7b098aa4fdf8 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -9531,7 +9531,7 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
         aLine.append( "/ColorSpace" );
         if( bTrueColor )
             aLine.append( "/DeviceRGB\n" );
-        else if( aBitmap.HasGreyPalette() )
+        else if( aBitmap.HasGreyPaletteAny() )
         {
             aLine.append( "/DeviceGray\n" );
             if( aBitmap.GetBitCount() == 1 )


More information about the Libreoffice-commits mailing list