[Libreoffice-commits] core.git: include/vcl vcl/Library_vcl.mk vcl/source

Chris Sherlock chris.sherlock79 at gmail.com
Fri Apr 20 06:32:41 UTC 2018


 include/vcl/BitmapGaussianSeparableBlurFilter.hxx       |   50 +++
 include/vcl/bitmap.hxx                                  |   16 -
 vcl/Library_vcl.mk                                      |    1 
 vcl/source/bitmap/BitmapGaussianSeparableBlurFilter.cxx |  217 ++++++++++++++++
 vcl/source/gdi/bitmap3.cxx                              |   52 ---
 vcl/source/gdi/bitmap4.cxx                              |  154 -----------
 6 files changed, 280 insertions(+), 210 deletions(-)

New commits:
commit f9473a8d2ea6740d325ac35da74fec16476820f0
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Wed Apr 18 07:51:50 2018 +1000

    vcl: ImplSeparableBlurFilter() -> BitmapGaussianSeparableBlurFilter
    
    Change-Id: I996c9fcb0524e14e0093142be0749f0e5836426b
    Reviewed-on: https://gerrit.libreoffice.org/53071
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/vcl/BitmapGaussianSeparableBlurFilter.hxx b/include/vcl/BitmapGaussianSeparableBlurFilter.hxx
new file mode 100644
index 000000000000..6e6a3a09e6f0
--- /dev/null
+++ b/include/vcl/BitmapGaussianSeparableBlurFilter.hxx
@@ -0,0 +1,50 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_BITMAPGAUSSIANSEPARABLEBLURFILTER_HXX
+#define INCLUDED_VCL_BITMAPGAUSSIANSEPARABLEBLURFILTER_HXX
+
+#include <vcl/BitmapFilter.hxx>
+
+class BitmapEx;
+
+class VCL_DLLPUBLIC BitmapGaussianSeparableBlurFilter : public BitmapFilter
+{
+public:
+    BitmapGaussianSeparableBlurFilter(double fRadius)
+        : mfRadius(fRadius)
+    {
+    }
+
+    /** Separable Gaussian Blur filter and accepts a blur radius
+        as a parameter so the user can change the strength of the blur.
+        Radius of 1.0 is 3 * standard deviation of gauss function.
+
+        Separable Blur implementation uses 2x separable 1D convolution
+        to process the image.
+    */
+    virtual BitmapEx execute(BitmapEx const& rBitmapEx) override;
+
+private:
+    double mfRadius;
+
+    bool convolutionPass(Bitmap& rBitmap, Bitmap& aNewBitmap, BitmapReadAccess const* pReadAcc,
+                         int aNumberOfContributions, const double* pWeights, int const* pPixels,
+                         const int* pCount);
+
+    static double* makeBlurKernel(const double radius, int& rows);
+    static void blurContributions(const int aSize, const int aNumberOfContributions,
+                                  const double* pBlurVector, double*& pWeights, int*& pPixels,
+                                  int*& pCount);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index cc50a6dc9bcc..6370a63d116f 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -676,14 +676,6 @@ public:
     SAL_DLLPRIVATE bool     ImplScaleFast( const double& rScaleX, const double& rScaleY );
     SAL_DLLPRIVATE bool     ImplScaleInterpolate( const double& rScaleX, const double& rScaleY );
 
-    SAL_DLLPRIVATE bool     ImplConvolutionPass(
-                                Bitmap& aNewBitmap,
-                                BitmapReadAccess const * pReadAcc,
-                                int aNumberOfContributions,
-                                const double* pWeights,
-                                int const * pPixels,
-                                const int* pCount );
-
     SAL_DLLPRIVATE bool     ImplMakeGreyscales( sal_uInt16 nGreyscales );
     SAL_DLLPRIVATE bool     ImplDitherMatrix();
     SAL_DLLPRIVATE bool     ImplDitherFloyd();
@@ -707,16 +699,8 @@ public:
     SAL_DLLPRIVATE bool     ImplMosaic( const BmpFilterParam* pFilterParam );
     SAL_DLLPRIVATE bool     ImplPopArt();
 
-    SAL_DLLPRIVATE bool     ImplSeparableBlurFilter( const double aRadius );
     SAL_DLLPRIVATE bool     ImplSeparableUnsharpenFilter( const double aRadius );
     SAL_DLLPRIVATE bool     ImplDuotoneFilter( const sal_uLong nColorOne,  sal_uLong nColorTwo );
-    SAL_DLLPRIVATE static void ImplBlurContributions(
-                                const int aSize,
-                                const int aNumberOfContributions,
-                                const double* pBlurVector,
-                                double*& pWeights,
-                                int*& pPixels,
-                                int*& pCount );
 
 public:
 
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 128541e5d0fd..03c705aa5544 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -317,6 +317,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/bitmap/BitmapDisabledImageFilter \
     vcl/source/bitmap/BitmapColorizeFilter \
     vcl/source/bitmap/bitmappaint \
+    vcl/source/bitmap/BitmapGaussianSeparableBlurFilter \
 	vcl/source/bitmap/BitmapFastScaleFilter \
     vcl/source/bitmap/BitmapScaleSuperFilter \
     vcl/source/bitmap/BitmapScaleConvolutionFilter \
diff --git a/vcl/source/bitmap/BitmapGaussianSeparableBlurFilter.cxx b/vcl/source/bitmap/BitmapGaussianSeparableBlurFilter.cxx
new file mode 100644
index 000000000000..b28ce99e8d19
--- /dev/null
+++ b/vcl/source/bitmap/BitmapGaussianSeparableBlurFilter.cxx
@@ -0,0 +1,217 @@
+/* -*- 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 <basegfx/color/bcolortools.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/BitmapGaussianSeparableBlurFilter.hxx>
+
+#include <bitmapwriteaccess.hxx>
+
+BitmapEx BitmapGaussianSeparableBlurFilter::execute(BitmapEx const& rBitmapEx)
+{
+    Bitmap aBitmap(rBitmapEx.GetBitmap());
+
+    const long nWidth = aBitmap.GetSizePixel().Width();
+    const long nHeight = aBitmap.GetSizePixel().Height();
+
+    // Prepare Blur Vector
+    int aNumberOfContributions;
+    double* pBlurVector = makeBlurKernel(mfRadius, aNumberOfContributions);
+
+    double* pWeights;
+    int* pPixels;
+    int* pCount;
+
+    // Do horizontal filtering
+    blurContributions(nWidth, aNumberOfContributions, pBlurVector, pWeights, pPixels, pCount);
+
+    Bitmap::ScopedReadAccess pReadAcc(aBitmap);
+
+    // switch coordinates as convolution pass transposes result
+    Bitmap aNewBitmap(Size(nHeight, nWidth), 24);
+
+    bool bResult = convolutionPass(aBitmap, aNewBitmap, pReadAcc.get(), aNumberOfContributions,
+                                   pWeights, pPixels, pCount);
+
+    // Cleanup
+    pReadAcc.reset();
+    delete[] pWeights;
+    delete[] pPixels;
+    delete[] pCount;
+
+    if (!bResult)
+    {
+        delete[] pBlurVector;
+    }
+    else
+    {
+        // Swap current bitmap with new bitmap
+        aBitmap.ReassignWithSize(aNewBitmap);
+
+        // Do vertical filtering
+        blurContributions(nHeight, aNumberOfContributions, pBlurVector, pWeights, pPixels, pCount);
+
+        pReadAcc = Bitmap::ScopedReadAccess(aBitmap);
+        aNewBitmap = Bitmap(Size(nWidth, nHeight), 24);
+        bResult = convolutionPass(aBitmap, aNewBitmap, pReadAcc.get(), aNumberOfContributions,
+                                  pWeights, pPixels, pCount);
+
+        // Cleanup
+        pReadAcc.reset();
+        delete[] pWeights;
+        delete[] pCount;
+        delete[] pPixels;
+        delete[] pBlurVector;
+
+        if (bResult)
+            aBitmap.ReassignWithSize(aNewBitmap); // swap current bitmap with new bitmap
+    }
+
+    if (bResult)
+        return BitmapEx(aBitmap);
+
+    return BitmapEx();
+}
+
+bool BitmapGaussianSeparableBlurFilter::convolutionPass(Bitmap& rBitmap, Bitmap& aNewBitmap,
+                                                        BitmapReadAccess const* pReadAcc,
+                                                        int aNumberOfContributions,
+                                                        const double* pWeights, int const* pPixels,
+                                                        const int* pCount)
+{
+    if (!pReadAcc)
+        return false;
+
+    BitmapScopedWriteAccess pWriteAcc(aNewBitmap);
+    if (!pWriteAcc)
+        return false;
+
+    const int nHeight = rBitmap.GetSizePixel().Height();
+    assert(rBitmap.GetSizePixel().Height() == aNewBitmap.GetSizePixel().Width());
+    const int nWidth = rBitmap.GetSizePixel().Width();
+    assert(rBitmap.GetSizePixel().Width() == aNewBitmap.GetSizePixel().Height());
+
+    BitmapColor aColor;
+    double aValueRed, aValueGreen, aValueBlue;
+    double aSum, aWeight;
+    int aBaseIndex, aIndex;
+
+    for (int nSourceY = 0; nSourceY < nHeight; ++nSourceY)
+    {
+        for (int nSourceX = 0; nSourceX < nWidth; ++nSourceX)
+        {
+            aBaseIndex = nSourceX * aNumberOfContributions;
+            aSum = aValueRed = aValueGreen = aValueBlue = 0.0;
+
+            for (int j = 0; j < pCount[nSourceX]; ++j)
+            {
+                aIndex = aBaseIndex + j;
+                aSum += aWeight = pWeights[aIndex];
+
+                aColor = pReadAcc->GetColor(nSourceY, pPixels[aIndex]);
+
+                aValueRed += aWeight * aColor.GetRed();
+                aValueGreen += aWeight * aColor.GetGreen();
+                aValueBlue += aWeight * aColor.GetBlue();
+            }
+
+            BitmapColor aResultColor(static_cast<sal_uInt8>(MinMax(aValueRed / aSum, 0, 255)),
+                                     static_cast<sal_uInt8>(MinMax(aValueGreen / aSum, 0, 255)),
+                                     static_cast<sal_uInt8>(MinMax(aValueBlue / aSum, 0, 255)));
+
+            int nDestX = nSourceY;
+            int nDestY = nSourceX;
+
+            pWriteAcc->SetPixel(nDestY, nDestX, aResultColor);
+        }
+    }
+    return true;
+}
+
+double* BitmapGaussianSeparableBlurFilter::makeBlurKernel(const double radius, int& rows)
+{
+    int intRadius = static_cast<int>(radius + 1.0);
+    rows = intRadius * 2 + 1;
+    double* matrix = new double[rows];
+
+    double sigma = radius / 3;
+    double radius2 = radius * radius;
+    int index = 0;
+    for (int row = -intRadius; row <= intRadius; row++)
+    {
+        double distance = row * row;
+        if (distance > radius2)
+        {
+            matrix[index] = 0.0;
+        }
+        else
+        {
+            matrix[index] = exp(-distance / (2.0 * sigma * sigma)) / sqrt(2.0 * M_PI * sigma);
+        }
+        index++;
+    }
+    return matrix;
+}
+
+void BitmapGaussianSeparableBlurFilter::blurContributions(const int aSize,
+                                                          const int aNumberOfContributions,
+                                                          const double* pBlurVector,
+                                                          double*& pWeights, int*& pPixels,
+                                                          int*& pCount)
+{
+    pWeights = new double[aSize * aNumberOfContributions];
+    pPixels = new int[aSize * aNumberOfContributions];
+    pCount = new int[aSize];
+
+    int aLeft, aRight, aCurrentCount, aPixelIndex;
+    double aWeight;
+
+    for (int i = 0; i < aSize; i++)
+    {
+        aLeft = i - aNumberOfContributions / 2;
+        aRight = i + aNumberOfContributions / 2;
+        aCurrentCount = 0;
+        for (int j = aLeft; j <= aRight; j++)
+        {
+            aWeight = pBlurVector[aCurrentCount];
+
+            // Mirror edges
+            if (j < 0)
+            {
+                aPixelIndex = -j;
+            }
+            else if (j >= aSize)
+            {
+                aPixelIndex = (aSize - j) + aSize - 1;
+            }
+            else
+            {
+                aPixelIndex = j;
+            }
+
+            // Edge case for small bitmaps
+            if (aPixelIndex < 0 || aPixelIndex >= aSize)
+            {
+                aWeight = 0.0;
+            }
+
+            pWeights[i * aNumberOfContributions + aCurrentCount] = aWeight;
+            pPixels[i * aNumberOfContributions + aCurrentCount] = aPixelIndex;
+
+            aCurrentCount++;
+        }
+        pCount[i] = aCurrentCount;
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index b553130c6538..3bf068c3444a 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -1854,56 +1854,4 @@ bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
     return bRet;
 }
 
-bool Bitmap::ImplConvolutionPass(Bitmap& aNewBitmap, BitmapReadAccess const * pReadAcc, int aNumberOfContributions, const double* pWeights, int const * pPixels, const int* pCount)
-{
-    if (!pReadAcc)
-        return false;
-
-    BitmapScopedWriteAccess pWriteAcc(aNewBitmap);
-    if (!pWriteAcc)
-        return false;
-
-    const int nHeight = GetSizePixel().Height();
-    assert(GetSizePixel().Height() == aNewBitmap.GetSizePixel().Width());
-    const int nWidth = GetSizePixel().Width();
-    assert(GetSizePixel().Width() == aNewBitmap.GetSizePixel().Height());
-
-    BitmapColor aColor;
-    double aValueRed, aValueGreen, aValueBlue;
-    double aSum, aWeight;
-    int aBaseIndex, aIndex;
-
-    for (int nSourceY = 0; nSourceY < nHeight; ++nSourceY)
-    {
-        for (int nSourceX = 0; nSourceX < nWidth; ++nSourceX)
-        {
-            aBaseIndex = nSourceX * aNumberOfContributions;
-            aSum = aValueRed = aValueGreen = aValueBlue = 0.0;
-
-            for (int j = 0; j < pCount[nSourceX]; ++j)
-            {
-                aIndex = aBaseIndex + j;
-                aSum += aWeight = pWeights[ aIndex ];
-
-                aColor = pReadAcc->GetColor(nSourceY, pPixels[aIndex]);
-
-                aValueRed += aWeight * aColor.GetRed();
-                aValueGreen += aWeight * aColor.GetGreen();
-                aValueBlue += aWeight * aColor.GetBlue();
-            }
-
-            BitmapColor aResultColor(
-                static_cast<sal_uInt8>(MinMax( aValueRed / aSum, 0, 255 )),
-                static_cast<sal_uInt8>(MinMax( aValueGreen / aSum, 0, 255 )),
-                static_cast<sal_uInt8>(MinMax( aValueBlue / aSum, 0, 255 )) );
-
-            int nDestX = nSourceY;
-            int nDestY = nSourceX;
-
-            pWriteAcc->SetPixel(nDestY, nDestX, aResultColor);
-        }
-    }
-    return true;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/bitmap4.cxx b/vcl/source/gdi/bitmap4.cxx
index 71fd484170ae..e48a2edae9b3 100644
--- a/vcl/source/gdi/bitmap4.cxx
+++ b/vcl/source/gdi/bitmap4.cxx
@@ -17,13 +17,16 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include <memory>
-#include <stdlib.h>
 #include <osl/diagnose.h>
 #include <vcl/bitmapaccess.hxx>
 #include <vcl/bitmap.hxx>
+#include <vcl/BitmapGaussianSeparableBlurFilter.hxx>
+
 #include <bitmapwriteaccess.hxx>
 
+#include <memory>
+#include <stdlib.h>
+
 #define S2(a,b)             { long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } }
 #define MN3(a,b,c)          S2(a,b); S2(a,c);
 #define MX3(a,b,c)          S2(b,c); S2(a,c);
@@ -51,7 +54,9 @@ bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam )
             // Blur for positive values of mnRadius
             if (pFilterParam->mnRadius > 0.0)
             {
-                bRet = ImplSeparableBlurFilter(pFilterParam->mnRadius);
+                BitmapEx aBmpEx(*this);
+                bRet = BitmapFilter::Filter(aBmpEx, BitmapGaussianSeparableBlurFilter(pFilterParam->mnRadius));
+                *this = aBmpEx.GetBitmap();
             }
             // Unsharpen Mask for negative values of mnRadius
             else if (pFilterParam->mnRadius < 0.0)
@@ -1062,144 +1067,6 @@ bool Bitmap::ImplPopArt()
     return bRet;
 }
 
-double* MakeBlurKernel(const double radius, int& rows) {
-    int intRadius = static_cast<int>(radius + 1.0);
-    rows = intRadius * 2 + 1;
-    double* matrix = new double[rows];
-
-    double sigma = radius / 3;
-    double radius2 = radius * radius;
-    int index = 0;
-    for (int row = -intRadius; row <= intRadius; row++)
-    {
-        double distance = row*row;
-        if (distance > radius2) {
-            matrix[index] = 0.0;
-        }else {
-            matrix[index] = exp( -distance / (2.0 * sigma * sigma) ) / sqrt( 2.0 * M_PI * sigma );
-        }
-        index++;
-    }
-    return matrix;
-}
-
-void Bitmap::ImplBlurContributions( const int aSize, const int aNumberOfContributions,
-                                    const double* pBlurVector, double*& pWeights, int*& pPixels, int*& pCount )
-{
-    pWeights = new double[ aSize*aNumberOfContributions ];
-    pPixels = new int[ aSize*aNumberOfContributions ];
-    pCount = new int[ aSize ];
-
-    int aLeft, aRight, aCurrentCount, aPixelIndex;
-    double aWeight;
-
-    for ( int i = 0; i < aSize; i++ )
-    {
-        aLeft  = i - aNumberOfContributions / 2;
-        aRight = i + aNumberOfContributions / 2;
-        aCurrentCount = 0;
-        for ( int j = aLeft; j <= aRight; j++ )
-        {
-            aWeight = pBlurVector[aCurrentCount];
-
-            // Mirror edges
-            if (j < 0)
-            {
-                aPixelIndex = -j;
-            }
-            else if ( j >= aSize )
-            {
-                aPixelIndex = (aSize - j) + aSize - 1;
-            }
-            else
-            {
-                aPixelIndex = j;
-            }
-
-            // Edge case for small bitmaps
-            if ( aPixelIndex < 0 || aPixelIndex >= aSize )
-            {
-                aWeight = 0.0;
-            }
-
-            pWeights[ i*aNumberOfContributions + aCurrentCount ] = aWeight;
-            pPixels[ i*aNumberOfContributions + aCurrentCount ] = aPixelIndex;
-
-            aCurrentCount++;
-        }
-        pCount[ i ] = aCurrentCount;
-    }
-}
-
-// Separable Gaussian Blur
-
-// Separable Gaussian Blur filter and accepts a blur radius
-// as a parameter so the user can change the strength of the blur.
-// Radius of 1.0 is 3 * standard deviation of gauss function.
-
-// Separable Blur implementation uses 2x separable 1D convolution
-// to process the image.
-bool Bitmap::ImplSeparableBlurFilter(const double radius)
-{
-    const long  nWidth = GetSizePixel().Width();
-    const long  nHeight = GetSizePixel().Height();
-
-    // Prepare Blur Vector
-    int aNumberOfContributions;
-    double* pBlurVector = MakeBlurKernel(radius, aNumberOfContributions);
-
-    double* pWeights;
-    int* pPixels;
-    int* pCount;
-
-    // Do horizontal filtering
-    ImplBlurContributions( nWidth, aNumberOfContributions, pBlurVector, pWeights, pPixels, pCount);
-
-    ScopedReadAccess pReadAcc(*this);
-
-    // switch coordinates as convolution pass transposes result
-    Bitmap aNewBitmap( Size( nHeight, nWidth ), 24 );
-
-    bool bResult = ImplConvolutionPass( aNewBitmap, pReadAcc.get(), aNumberOfContributions, pWeights, pPixels, pCount );
-
-    // Cleanup
-    pReadAcc.reset();
-    delete[] pWeights;
-    delete[] pPixels;
-    delete[] pCount;
-
-    if ( !bResult )
-    {
-        delete[] pBlurVector;
-        return bResult;
-    }
-
-    // Swap current bitmap with new bitmap
-    ReassignWithSize(aNewBitmap);
-
-    // Do vertical filtering
-    ImplBlurContributions(nHeight, aNumberOfContributions, pBlurVector, pWeights, pPixels, pCount );
-
-    pReadAcc = ScopedReadAccess(*this);
-    aNewBitmap = Bitmap( Size( nWidth, nHeight ), 24 );
-    bResult = ImplConvolutionPass( aNewBitmap, pReadAcc.get(), aNumberOfContributions, pWeights, pPixels, pCount );
-
-    // Cleanup
-    pReadAcc.reset();
-    delete[] pWeights;
-    delete[] pCount;
-    delete[] pPixels;
-    delete[] pBlurVector;
-
-    if ( !bResult )
-        return bResult;
-
-    // Swap current bitmap with new bitmap
-    ReassignWithSize(aNewBitmap);
-
-    return true;
-}
-
 // Separable Unsharpen Mask filter is actually a subtracted blurred
 // image from the original image.
 bool Bitmap::ImplSeparableUnsharpenFilter(const double radius) {
@@ -1207,7 +1074,10 @@ bool Bitmap::ImplSeparableUnsharpenFilter(const double radius) {
     const long  nHeight = GetSizePixel().Height();
 
     Bitmap aBlur( *this );
-    aBlur.ImplSeparableBlurFilter(-radius);
+    BitmapEx aBlurEx(aBlur);
+
+    BitmapFilter::Filter(aBlurEx, BitmapGaussianSeparableBlurFilter(-radius));
+    aBlur = aBlurEx.GetBitmap();
 
     // Amount of unsharpening effect on image - currently set to a fixed value
     double aAmount = 2.0;


More information about the Libreoffice-commits mailing list