oox/inc/drawingml/fillproperties.hxx                         |    1 
 oox/source/drawingml/fillproperties.cxx                      |   40 +++++++++
 oox/source/drawingml/misccontexts.cxx                        |    4 
 sd/qa/unit/data/pptx/tdf89928-blackWhiteEffectThreshold.pptx |binary
 sd/qa/unit/import-tests2.cxx                                 |   45 +++++++++++
 5 files changed, 90 insertions(+)

New commits:
commit 9ecc76988ec46ba0d6c5cb72ac88f65da48867b1
Author:     Sarper Akdemir <sarper.akde...@collabora.com>
AuthorDate: Mon Sep 19 09:56:57 2022 +0300
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Sep 20 08:29:29 2022 +0200

    tdf#89928 pptx import: implement import of BiLevel threshold
    
    Implement import BiLevel effect's threshold value.
    If threshold isn't exactly 50%, we can't map it to the doc model.
    
    Therefore as a workaround apply the BiLevel (Black/White) effect with
    specified threshold directly to the graphic.
    
    Change-Id: Ib24d149d74b103d926560708c68bb937b02c4cfe
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140136
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/oox/inc/drawingml/fillproperties.hxx 
b/oox/inc/drawingml/fillproperties.hxx
index 9cef3c98f2b1..828c858e12f2 100644
--- a/oox/inc/drawingml/fillproperties.hxx
+++ b/oox/inc/drawingml/fillproperties.hxx
@@ -113,6 +113,7 @@ struct BlipFillProperties
     std::optional< sal_Int32 > moColorEffect;        /// XML token for a color 
effect.
     std::optional< sal_Int32 > moBrightness;         /// Brightness in the 
range [-100000,100000].
     std::optional< sal_Int32 > moContrast;           /// Contrast in the range 
[-100000,100000].
+    std::optional< sal_Int32 > moBiLevelThreshold;   /// Bi-Level 
(Black/White) effect threshold (1/1000 percent)
     Color                 maColorChangeFrom;      /// Start color of color 
transformation.
     Color                 maColorChangeTo;        /// Destination color of 
color transformation.
     Color                 maDuotoneColors[2];     /// Duotone Colors
diff --git a/oox/source/drawingml/fillproperties.cxx 
b/oox/source/drawingml/fillproperties.cxx
index 1ef7579a7725..7933a79f5dba 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -24,6 +24,8 @@
 #include <comphelper/propertyvalue.hxx>
 #include <drawingml/graphicproperties.hxx>
 #include <vcl/graph.hxx>
+#include <vcl/BitmapFilter.hxx>
+#include <vcl/BitmapMonochromeFilter.hxx>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/awt/Gradient.hpp>
@@ -185,6 +187,32 @@ Reference< XGraphic > 
lclGreysScaleGraphic(uno::Reference<graphic::XGraphic> con
     return aReturnGraphic.GetXGraphic();
 }
 
+/// Applies the graphic Black&White (Monochrome) effect with the imported 
threshold
+Reference<XGraphic> lclApplyBlackWhiteEffect(const BlipFillProperties& 
aBlipProps,
+                                             const 
uno::Reference<graphic::XGraphic>& xGraphic)
+{
+    const auto& oBiLevelThreshold = aBlipProps.moBiLevelThreshold;
+    if (oBiLevelThreshold.has_value())
+    {
+        sal_uInt8 nThreshold
+            = static_cast<sal_uInt8>(oBiLevelThreshold.value() * 255 / 
MAX_PERCENT);
+
+        ::Graphic aGraphic(xGraphic);
+        ::Graphic aReturnGraphic;
+
+        BitmapEx aBitmapEx(aGraphic.GetBitmapEx());
+        AlphaMask aMask(aBitmapEx.GetAlpha());
+
+        BitmapEx aTmpBmpEx(aBitmapEx.GetBitmap());
+        BitmapFilter::Filter(aTmpBmpEx, BitmapMonochromeFilter{ nThreshold });
+
+        aReturnGraphic = ::Graphic(BitmapEx(aTmpBmpEx.GetBitmap(), aMask));
+        aReturnGraphic.setOriginURL(aGraphic.getOriginURL());
+        return aReturnGraphic.GetXGraphic();
+    }
+    return xGraphic;
+}
+
 Reference< XGraphic > lclCheckAndApplyChangeColorTransform(const 
BlipFillProperties &aBlipProps, uno::Reference<graphic::XGraphic> const & 
xGraphic,
                                                            const 
GraphicHelper& rGraphicHelper, const ::Color nPhClr)
 {
@@ -350,6 +378,7 @@ void BlipFillProperties::assignUsed( const 
BlipFillProperties& rSourceProps )
     assignIfUsed( moColorEffect, rSourceProps.moColorEffect );
     assignIfUsed( moBrightness, rSourceProps.moBrightness );
     assignIfUsed( moContrast, rSourceProps.moContrast );
+    assignIfUsed( moBiLevelThreshold, rSourceProps.moBiLevelThreshold );
     maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom );
     maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo );
     maDuotoneColors[0].assignIfUsed( rSourceProps.maDuotoneColors[0] );
@@ -907,6 +936,17 @@ void GraphicProperties::pushToPropMap( PropertyMap& 
rPropMap, const GraphicHelpe
         uno::Reference<graphic::XGraphic> xGraphic = 
lclCheckAndApplyChangeColorTransform(maBlipProps, maBlipProps.mxFillGraphic, 
rGraphicHelper, API_RGB_TRANSPARENT);
         xGraphic = lclCheckAndApplyDuotoneTransform(maBlipProps, xGraphic, 
rGraphicHelper, API_RGB_TRANSPARENT);
 
+        if( eColorMode == ColorMode_MONO )
+        {
+            // ColorMode_MONO is the same with MSO's biLevel with 50000 (50%) 
threshold,
+            // when threshold isn't 50000 bake the effect instead.
+            if( maBlipProps.moBiLevelThreshold != 50000 )
+            {
+                xGraphic = lclApplyBlackWhiteEffect(maBlipProps, xGraphic);
+                eColorMode = ColorMode_STANDARD;
+            }
+        }
+
         if (eColorMode == ColorMode_STANDARD && nBrightness == 70 && nContrast 
== -70)
         {
             // map MSO 'washout' to our Watermark colormode
diff --git a/oox/source/drawingml/misccontexts.cxx 
b/oox/source/drawingml/misccontexts.cxx
index ceeeca3d5c62..e7ec679ad318 100644
--- a/oox/source/drawingml/misccontexts.cxx
+++ b/oox/source/drawingml/misccontexts.cxx
@@ -172,6 +172,10 @@ ContextHandlerRef BlipContext::onCreateContext(
     switch( nElement )
     {
         case A_TOKEN( biLevel ):
+            mrBlipProps.moBiLevelThreshold = rAttribs.getInteger( XML_thresh );
+            mrBlipProps.moColorEffect = getBaseToken(nElement);
+            break;
+
         case A_TOKEN( grayscl ):
             mrBlipProps.moColorEffect = getBaseToken( nElement );
         break;
diff --git a/sd/qa/unit/data/pptx/tdf89928-blackWhiteEffectThreshold.pptx 
b/sd/qa/unit/data/pptx/tdf89928-blackWhiteEffectThreshold.pptx
new file mode 100644
index 000000000000..90edf8ea0afb
Binary files /dev/null and 
b/sd/qa/unit/data/pptx/tdf89928-blackWhiteEffectThreshold.pptx differ
diff --git a/sd/qa/unit/import-tests2.cxx b/sd/qa/unit/import-tests2.cxx
index 17c793d08ab8..bf4939c39365 100644
--- a/sd/qa/unit/import-tests2.cxx
+++ b/sd/qa/unit/import-tests2.cxx
@@ -141,6 +141,7 @@ public:
     void testDefaultTabStop();
     void testCropToZero();
     void testTdf144092TableHeight();
+    void testTdf89928BlackWhiteThreshold();
 
     CPPUNIT_TEST_SUITE(SdImportTest2);
 
@@ -215,6 +216,7 @@ public:
     CPPUNIT_TEST(testDefaultTabStop);
     CPPUNIT_TEST(testCropToZero);
     CPPUNIT_TEST(testTdf144092TableHeight);
+    CPPUNIT_TEST(testTdf89928BlackWhiteThreshold);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -2121,6 +2123,49 @@ void SdImportTest2::testTdf144092TableHeight()
     xDocShRef->DoClose();
 }
 
+void SdImportTest2::testTdf89928BlackWhiteThreshold()
+{
+    // A slide with two graphics, one with color HSV{0,0,74%} and one with 
HSV{0,0,76%}
+    // where both have an applied 75% Black/White Color Effect.
+    sd::DrawDocShellRef xDocShRef
+        = loadURL(m_directories.getURLFromSrc(
+                      
u"sd/qa/unit/data/pptx/tdf89928-blackWhiteEffectThreshold.pptx"),
+                  PPTX);
+
+    // First graphic should appear black
+    {
+        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0, 
xDocShRef),
+                                                   uno::UNO_SET_THROW);
+        uno::Reference<graphic::XGraphic> xGraphic;
+        xShape->getPropertyValue("Graphic") >>= xGraphic;
+        CPPUNIT_ASSERT(xGraphic.is());
+
+        Graphic aGraphic(xGraphic);
+        BitmapEx aBitmap(aGraphic.GetBitmapEx());
+
+        // Without the accompanying fix in place, this test would have failed 
with:
+        // - Expected: Color: R:0 G:0 B:0 A:0
+        // - Actual  : Color: R:189 G:189 B:189 A:0
+        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0x000000), 
aBitmap.GetPixelColor(0, 0));
+    }
+
+    // Second graphic should appear white
+    {
+        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(1, 0, 
xDocShRef),
+                                                   uno::UNO_SET_THROW);
+        uno::Reference<graphic::XGraphic> xGraphic;
+        xShape->getPropertyValue("Graphic") >>= xGraphic;
+        CPPUNIT_ASSERT(xGraphic.is());
+
+        Graphic aGraphic(xGraphic);
+        BitmapEx aBitmap(aGraphic.GetBitmapEx());
+
+        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xFFFFFF), 
aBitmap.GetPixelColor(0, 0));
+    }
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();

Reply via email to