[Libreoffice-commits] core.git: vcl/CppunitTest_vcl_bitmap_test.mk vcl/qa vcl/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Oct 10 11:36:03 UTC 2019


 vcl/CppunitTest_vcl_bitmap_test.mk |    1 
 vcl/qa/cppunit/BitmapExTest.cxx    |   40 +++++++++++++++++++++++++++++++++++++
 vcl/source/gdi/bitmapex.cxx        |   37 ++++++++++++++++++++++++++++++++--
 3 files changed, 76 insertions(+), 2 deletions(-)

New commits:
commit 55b4d5ea9e1a42edf71d2eef6028830983dbc11c
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Oct 10 09:49:29 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Oct 10 13:35:24 2019 +0200

    vcl: only smooth bitmap transform when needed
    
    If you have a very small bitmap and you rotate it by 90 degrees, then
    smoothing is not needed, but the result will be blurry. So in case
    scaling / shear doesn't need it and we do 90/180/270 rotation, avoid
    smoothing.
    
    Change-Id: I4b8fad4b0b70516d35eaecfa70a707e6e8362d18
    Reviewed-on: https://gerrit.libreoffice.org/80589
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/vcl/CppunitTest_vcl_bitmap_test.mk b/vcl/CppunitTest_vcl_bitmap_test.mk
index 90db22099b40..9ebef12dcfb2 100644
--- a/vcl/CppunitTest_vcl_bitmap_test.mk
+++ b/vcl/CppunitTest_vcl_bitmap_test.mk
@@ -33,6 +33,7 @@ $(eval $(call gb_CppunitTest_set_include,vcl_bitmap_test,\
 ))
 
 $(eval $(call gb_CppunitTest_use_libraries,vcl_bitmap_test, \
+	basegfx \
 	comphelper \
 	cppu \
 	cppuhelper \
diff --git a/vcl/qa/cppunit/BitmapExTest.cxx b/vcl/qa/cppunit/BitmapExTest.cxx
index 3a89441b9604..23f40f0013cd 100644
--- a/vcl/qa/cppunit/BitmapExTest.cxx
+++ b/vcl/qa/cppunit/BitmapExTest.cxx
@@ -12,6 +12,7 @@
 #include <cppunit/extensions/HelperMacros.h>
 
 #include <vcl/bitmapex.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
 #include <bitmapwriteaccess.hxx>
 #include <svdata.hxx>
 #include <salinst.hxx>
@@ -22,10 +23,12 @@ class BitmapExTest : public CppUnit::TestFixture
 {
     void testGetPixelColor24_8();
     void testGetPixelColor32();
+    void testTransformBitmapEx();
 
     CPPUNIT_TEST_SUITE(BitmapExTest);
     CPPUNIT_TEST(testGetPixelColor24_8);
     CPPUNIT_TEST(testGetPixelColor32);
+    CPPUNIT_TEST(testTransformBitmapEx);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -66,6 +69,43 @@ void BitmapExTest::testGetPixelColor32()
     CPPUNIT_ASSERT_EQUAL(Color(0xAA, 0x00, 0xFF, 0x00), aBitmapEx.GetPixelColor(0, 0));
 }
 
+void BitmapExTest::testTransformBitmapEx()
+{
+    Bitmap aBitmap(Size(16, 16), 24);
+    {
+        BitmapScopedWriteAccess pWriteAccess(aBitmap);
+        pWriteAccess->Erase(COL_WHITE);
+        for (int i = 0; i < 8; ++i)
+        {
+            for (int j = 0; j < 8; ++j)
+            {
+                pWriteAccess->SetPixel(i, j, COL_BLACK);
+            }
+        }
+    }
+    BitmapEx aBitmapEx(aBitmap);
+
+    basegfx::B2DHomMatrix aMatrix;
+    aMatrix.rotate(M_PI / 2);
+    BitmapEx aTransformed = aBitmapEx.TransformBitmapEx(16, 16, aMatrix);
+    aBitmap = aTransformed.GetBitmap();
+    Bitmap::ScopedReadAccess pAccess(aBitmap);
+    for (int i = 0; i < 16; ++i)
+    {
+        for (int j = 0; j < 16; ++j)
+        {
+            BitmapColor aColor = pAccess->GetPixel(i, j);
+            std::stringstream ss;
+            ss << "Color is expected to be white or black, is '" << aColor.AsRGBHexString() << "'";
+            // Without the accompanying fix in place, this test would have failed with:
+            // - Expression: aColor == COL_WHITE || aColor == COL_BLACK
+            // - Color is expected to be white or black, is 'bfbfbf'
+            // i.e. smoothing introduced noise for a simple 90 deg rotation.
+            CPPUNIT_ASSERT_MESSAGE(ss.str(), aColor == COL_WHITE || aColor == COL_BLACK);
+        }
+    }
+}
+
 } // namespace
 
 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapExTest);
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
index d4f96bcd86f3..5e410d05fb9b 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -867,6 +867,38 @@ namespace
 
         return aDestination;
     }
+
+    /// Decides if rTransformation needs smoothing or not (e.g. 180 deg rotation doesn't need it).
+    bool implTransformNeedsSmooth(const basegfx::B2DHomMatrix& rTransformation)
+    {
+        basegfx::B2DVector aScale, aTranslate;
+        double fRotate, fShearX;
+        rTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
+        if (aScale != basegfx::B2DVector(1, 1))
+        {
+            return true;
+        }
+
+        fRotate = fmod( fRotate, F_2PI );
+        if (fRotate < 0)
+        {
+            fRotate += F_2PI;
+        }
+        if (!rtl::math::approxEqual(fRotate, 0)
+            && !rtl::math::approxEqual(fRotate, F_PI2)
+            && !rtl::math::approxEqual(fRotate, F_PI)
+            && !rtl::math::approxEqual(fRotate, 3 * F_PI2))
+        {
+            return true;
+        }
+
+        if (!rtl::math::approxEqual(fShearX, 0))
+        {
+            return true;
+        }
+
+        return false;
+    }
 } // end of anonymous namespace
 
 BitmapEx BitmapEx::TransformBitmapEx(
@@ -879,14 +911,15 @@ BitmapEx BitmapEx::TransformBitmapEx(
 
     // force destination to 24 bit, we want to smooth output
     const Size aDestinationSize(basegfx::fround(fWidth), basegfx::fround(fHeight));
-    const Bitmap aDestination(impTransformBitmap(GetBitmapRef(), aDestinationSize, rTransformation, /*bSmooth*/true));
+    bool bSmooth = implTransformNeedsSmooth(rTransformation);
+    const Bitmap aDestination(impTransformBitmap(GetBitmapRef(), aDestinationSize, rTransformation, bSmooth));
 
     // create mask
     if(IsTransparent())
     {
         if(IsAlpha())
         {
-            const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, /*bSmooth*/true));
+            const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, bSmooth));
             return BitmapEx(aDestination, AlphaMask(aAlpha));
         }
         else


More information about the Libreoffice-commits mailing list