summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.com>2015-12-10 12:55:47 +0100
committerAshod Nakashian <ashod.nakashian@collabora.co.uk>2016-07-12 22:06:27 -0400
commit933268b50345016918aa07a4c93ad956472f40ef (patch)
treeebaae9f16d6ceb92aba2ed869f7f69a06e404087 /vcl
parent9c88e3f97ba14f81bc1541d7356fe96a96838d7c (diff)
vcl: extract scale convolution from bitmap to its own class/file
Change-Id: Ibb10aa7450b78ca2709da38857f095ccbc679c54 (cherry picked from commit 5919f0bbe82129e25962be88db4156dd7daa2a36)
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/inc/BitmapScaleConvolution.hxx62
-rw-r--r--vcl/source/bitmap/BitmapScaleConvolution.cxx397
-rw-r--r--vcl/source/gdi/bitmap3.cxx384
4 files changed, 469 insertions, 375 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 7f0b95d5bd20..7b9ad01f9749 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -315,6 +315,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/gdi/wall \
vcl/source/bitmap/bitmapfilter \
vcl/source/bitmap/bitmapscalesuper \
+ vcl/source/bitmap/BitmapScaleConvolution \
vcl/source/bitmap/BitmapSymmetryCheck \
vcl/source/bitmap/BitmapFilterStackBlur \
vcl/source/bitmap/BitmapProcessor \
diff --git a/vcl/inc/BitmapScaleConvolution.hxx b/vcl/inc/BitmapScaleConvolution.hxx
new file mode 100644
index 000000000000..a026f03e2e4d
--- /dev/null
+++ b/vcl/inc/BitmapScaleConvolution.hxx
@@ -0,0 +1,62 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_VCL_BITMAPSCALECONVOLUTION_HXX
+#define INCLUDED_VCL_BITMAPSCALECONVOLUTION_HXX
+
+#include <vcl/bitmapfilter.hxx>
+
+namespace vcl
+{
+
+enum class ConvolutionKernelType
+{
+ Box = 0,
+ BiLinear = 1,
+ BiCubic = 2,
+ Lanczos3 = 3,
+};
+
+class VCL_DLLPUBLIC BitmapScaleConvolution : public BitmapFilter
+{
+public:
+
+ BitmapScaleConvolution(const double& rScaleX, const double& rScaleY, ConvolutionKernelType eKernelType)
+ : mrScaleX(rScaleX)
+ , mrScaleY(rScaleY)
+ , meKernelType(eKernelType)
+ {}
+
+ virtual ~BitmapScaleConvolution()
+ {}
+
+ virtual bool filter(Bitmap& rBitmap) override;
+
+private:
+ double mrScaleX;
+ double mrScaleY;
+
+ ConvolutionKernelType meKernelType;
+};
+
+}
+
+#endif // INCLUDED_VCL_BITMAPSCALECONVOLUTION_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/bitmap/BitmapScaleConvolution.cxx b/vcl/source/bitmap/BitmapScaleConvolution.cxx
new file mode 100644
index 000000000000..a596603f827e
--- /dev/null
+++ b/vcl/source/bitmap/BitmapScaleConvolution.cxx
@@ -0,0 +1,397 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BitmapScaleConvolution.hxx"
+#include "ResampleKernel.hxx"
+
+#include <vcl/bmpacc.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+#include <memory>
+
+namespace vcl
+{
+
+namespace
+{
+
+void ImplCalculateContributions(
+ const long aSourceSize,
+ const long aDestinationSize,
+ long& aNumberOfContributions,
+ double*& pWeights,
+ long*& pPixels,
+ long*& pCount,
+ const Kernel& aKernel)
+{
+ const double fSamplingRadius(aKernel.GetWidth());
+ const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
+ const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
+ const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
+
+ aNumberOfContributions = (long(fabs(ceil(fScaledRadius))) * 2) + 1;
+ const long nAllocSize(aDestinationSize * aNumberOfContributions);
+ pWeights = new double[nAllocSize];
+ pPixels = new long[nAllocSize];
+ pCount = new long[aDestinationSize];
+
+ for(long i(0); i < aDestinationSize; i++)
+ {
+ const long aIndex(i * aNumberOfContributions);
+ const double aCenter(i / fScale);
+ const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
+ const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
+ long aCurrentCount(0);
+
+ for(sal_Int32 j(aLeft); j <= aRight; j++)
+ {
+ const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
+
+ // Reduce calculations with ignoring weights of 0.0
+ if(fabs(aWeight) < 0.0001)
+ {
+ continue;
+ }
+
+ // Handling on edges
+ const long aPixelIndex(MinMax(j, 0, aSourceSize - 1));
+ const long nIndex(aIndex + aCurrentCount);
+
+ pWeights[nIndex] = aWeight;
+ pPixels[nIndex] = aPixelIndex;
+
+ aCurrentCount++;
+ }
+
+ pCount[i] = aCurrentCount;
+ }
+}
+
+bool ImplScaleConvolutionHor(Bitmap& rSource, Bitmap& rTarget, const double& rScaleX, const Kernel& aKernel)
+{
+ // Do horizontal filtering
+ OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
+ const long nWidth(rSource.GetSizePixel().Width());
+ const long nNewWidth(FRound(nWidth * rScaleX));
+
+ if(nWidth == nNewWidth)
+ {
+ return true;
+ }
+
+ BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
+
+ if(pReadAcc)
+ {
+ double* pWeights = nullptr;
+ long* pPixels = nullptr;
+ long* pCount = nullptr;
+ long aNumberOfContributions(0);
+
+ const long nHeight(rSource.GetSizePixel().Height());
+ ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
+ rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
+ BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
+ bool bResult(nullptr != pWriteAcc);
+
+ if(bResult)
+ {
+ for(long y(0); y < nHeight; y++)
+ {
+ for(long x(0); x < nNewWidth; x++)
+ {
+ const long aBaseIndex(x * aNumberOfContributions);
+ double aSum(0.0);
+ double aValueRed(0.0);
+ double aValueGreen(0.0);
+ double aValueBlue(0.0);
+
+ for(long j(0); j < pCount[x]; j++)
+ {
+ const long aIndex(aBaseIndex + j);
+ const double aWeight(pWeights[aIndex]);
+ BitmapColor aColor;
+
+ aSum += aWeight;
+
+ if(pReadAcc->HasPalette())
+ {
+ aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
+ }
+ else
+ {
+ aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
+ }
+
+ aValueRed += aWeight * aColor.GetRed();
+ aValueGreen += aWeight * aColor.GetGreen();
+ aValueBlue += aWeight * aColor.GetBlue();
+ }
+
+ const BitmapColor aResultColor(
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
+
+ pWriteAcc->SetPixel(y, x, aResultColor);
+ }
+ }
+
+ Bitmap::ReleaseAccess(pWriteAcc);
+ }
+
+ Bitmap::ReleaseAccess(pReadAcc);
+ delete[] pWeights;
+ delete[] pCount;
+ delete[] pPixels;
+
+ if(bResult)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ImplScaleConvolutionVer(Bitmap& rSource, Bitmap& rTarget, const double& rScaleY, const Kernel& aKernel)
+{
+ // Do vertical filtering
+ OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
+ const long nHeight(rSource.GetSizePixel().Height());
+ const long nNewHeight(FRound(nHeight * rScaleY));
+
+ if(nHeight == nNewHeight)
+ {
+ return true;
+ }
+
+ BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
+
+ if(pReadAcc)
+ {
+ double* pWeights = nullptr;
+ long* pPixels = nullptr;
+ long* pCount = nullptr;
+ long aNumberOfContributions(0);
+
+ const long nWidth(rSource.GetSizePixel().Width());
+ ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
+ rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
+ BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
+ bool bResult(nullptr != pWriteAcc);
+
+ if(pWriteAcc)
+ {
+ for(long x(0); x < nWidth; x++)
+ {
+ for(long y(0); y < nNewHeight; y++)
+ {
+ const long aBaseIndex(y * aNumberOfContributions);
+ double aSum(0.0);
+ double aValueRed(0.0);
+ double aValueGreen(0.0);
+ double aValueBlue(0.0);
+
+ for(long j(0); j < pCount[y]; j++)
+ {
+ const long aIndex(aBaseIndex + j);
+ const double aWeight(pWeights[aIndex]);
+ BitmapColor aColor;
+
+ aSum += aWeight;
+
+ if(pReadAcc->HasPalette())
+ {
+ aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
+ }
+ else
+ {
+ aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
+ }
+
+ aValueRed += aWeight * aColor.GetRed();
+ aValueGreen += aWeight * aColor.GetGreen();
+ aValueBlue += aWeight * aColor.GetBlue();
+ }
+
+ const BitmapColor aResultColor(
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
+
+ if(pWriteAcc->HasPalette())
+ {
+ pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
+ }
+ else
+ {
+ pWriteAcc->SetPixel(y, x, aResultColor);
+ }
+ }
+ }
+ }
+
+ Bitmap::ReleaseAccess(pWriteAcc);
+ Bitmap::ReleaseAccess(pReadAcc);
+
+ delete[] pWeights;
+ delete[] pCount;
+ delete[] pPixels;
+
+ if(bResult)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ImplScaleConvolution(Bitmap& rBitmap, const double& rScaleX, const double& rScaleY, const Kernel& aKernel)
+{
+ const bool bMirrorHor(rScaleX < 0.0);
+ const bool bMirrorVer(rScaleY < 0.0);
+ const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
+ const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
+ const long nWidth(rBitmap.GetSizePixel().Width());
+ const long nHeight(rBitmap.GetSizePixel().Height());
+ const long nNewWidth(FRound(nWidth * fScaleX));
+ const long nNewHeight(FRound(nHeight * fScaleY));
+ const bool bScaleHor(nWidth != nNewWidth);
+ const bool bScaleVer(nHeight != nNewHeight);
+ const bool bMirror(bMirrorHor || bMirrorVer);
+
+ if (!bMirror && !bScaleHor && !bScaleVer)
+ {
+ return true;
+ }
+
+ bool bResult(true);
+ BmpMirrorFlags nMirrorFlags(BmpMirrorFlags::NONE);
+ bool bMirrorAfter(false);
+
+ if (bMirror)
+ {
+ if(bMirrorHor)
+ {
+ nMirrorFlags |= BmpMirrorFlags::Horizontal;
+ }
+
+ if(bMirrorVer)
+ {
+ nMirrorFlags |= BmpMirrorFlags::Vertical;
+ }
+
+ const long nStartSize(nWidth * nHeight);
+ const long nEndSize(nNewWidth * nNewHeight);
+
+ bMirrorAfter = nStartSize > nEndSize;
+
+ if(!bMirrorAfter)
+ {
+ bResult = rBitmap.Mirror(nMirrorFlags);
+ }
+ }
+
+ Bitmap aResult;
+
+ if (bResult)
+ {
+ const long nInBetweenSizeHorFirst(nHeight * nNewWidth);
+ const long nInBetweenSizeVerFirst(nNewHeight * nWidth);
+ Bitmap aSource(rBitmap);
+
+ if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
+ {
+ if(bScaleHor)
+ {
+ bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
+ }
+
+ if(bResult && bScaleVer)
+ {
+ if(bScaleHor)
+ {
+ // copy partial result, independent of color depth
+ aSource = aResult;
+ }
+
+ bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
+ }
+ }
+ else
+ {
+ if(bScaleVer)
+ {
+ bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
+ }
+
+ if(bResult && bScaleHor)
+ {
+ if(bScaleVer)
+ {
+ // copy partial result, independent of color depth
+ aSource = aResult;
+ }
+
+ bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
+ }
+ }
+ }
+
+ if(bResult && bMirrorAfter)
+ {
+ bResult = aResult.Mirror(nMirrorFlags);
+ }
+
+ if(bResult)
+ {
+ rBitmap.ImplAdaptBitCount(aResult);
+ rBitmap = aResult;
+ }
+
+ return bResult;
+}
+
+} // end anonymous namespace
+
+bool BitmapScaleConvolution::filter(Bitmap& rBitmap)
+{
+
+ switch(meKernelType)
+ {
+ case ConvolutionKernelType::Box:
+ return ImplScaleConvolution(rBitmap, mrScaleX, mrScaleY, BoxKernel());
+ case ConvolutionKernelType::BiLinear:
+ return ImplScaleConvolution(rBitmap, mrScaleX, mrScaleY, BilinearKernel());
+ case ConvolutionKernelType::BiCubic:
+ return ImplScaleConvolution(rBitmap, mrScaleX, mrScaleY, BicubicKernel());
+ case ConvolutionKernelType::Lanczos3:
+ return ImplScaleConvolution(rBitmap, mrScaleX, mrScaleY, Lanczos3Kernel());
+ default:
+ break;
+ }
+ return false;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index 0c6c50b8c25f..655374836682 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -33,13 +33,7 @@
#include <impvect.hxx>
#include "octree.hxx"
-#include <ResampleKernel.hxx>
-
-using vcl::Kernel;
-using vcl::Lanczos3Kernel;
-using vcl::BicubicKernel;
-using vcl::BilinearKernel;
-using vcl::BoxKernel;
+#include "BitmapScaleConvolution.hxx"
#define RGB15( _def_cR, _def_cG, _def_cB ) (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
#define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
@@ -976,30 +970,26 @@ bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag n
case BmpScaleFlag::Lanczos :
case BmpScaleFlag::BestQuality:
{
- const Lanczos3Kernel kernel;
-
- bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ vcl::BitmapScaleConvolution aScaleConvolution(rScaleX, rScaleY, vcl::ConvolutionKernelType::Lanczos3);
+ bRetval = aScaleConvolution.filter(*this);
break;
}
case BmpScaleFlag::BiCubic :
{
- const BicubicKernel kernel;
-
- bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ vcl::BitmapScaleConvolution aScaleConvolution(rScaleX, rScaleY, vcl::ConvolutionKernelType::BiCubic);
+ bRetval = aScaleConvolution.filter(*this);
break;
}
case BmpScaleFlag::BiLinear :
{
- const BilinearKernel kernel;
-
- bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ vcl::BitmapScaleConvolution aScaleConvolution(rScaleX, rScaleY, vcl::ConvolutionKernelType::BiLinear);
+ bRetval = aScaleConvolution.filter(*this);
break;
}
case BmpScaleFlag::Box :
{
- const BoxKernel kernel;
-
- bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ vcl::BitmapScaleConvolution aScaleConvolution(rScaleX, rScaleY, vcl::ConvolutionKernelType::Box);
+ bRetval = aScaleConvolution.filter(*this);
break;
}
}
@@ -1337,362 +1327,6 @@ bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY
return bRet;
}
-namespace
-{
- void ImplCalculateContributions(
- const sal_uInt32 aSourceSize,
- const sal_uInt32 aDestinationSize,
- sal_uInt32& aNumberOfContributions,
- double*& pWeights,
- sal_uInt32*& pPixels,
- sal_uInt32*& pCount,
- const Kernel& aKernel)
- {
- const double fSamplingRadius(aKernel.GetWidth());
- const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
- const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
- const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
-
- aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
- const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
- pWeights = new double[nAllocSize];
- pPixels = new sal_uInt32[nAllocSize];
- pCount = new sal_uInt32[aDestinationSize];
-
- for(sal_uInt32 i(0); i < aDestinationSize; i++)
- {
- const sal_uInt32 aIndex(i * aNumberOfContributions);
- const double aCenter(i / fScale);
- const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
- const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
- sal_uInt32 aCurrentCount(0);
-
- for(sal_Int32 j(aLeft); j <= aRight; j++)
- {
- const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
-
- // Reduce calculations with ignoring weights of 0.0
- if(fabs(aWeight) < 0.0001)
- {
- continue;
- }
-
- // Handling on edges
- const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
- const sal_uInt32 nIndex(aIndex + aCurrentCount);
-
- pWeights[nIndex] = aWeight;
- pPixels[nIndex] = aPixelIndex;
-
- aCurrentCount++;
- }
-
- pCount[i] = aCurrentCount;
- }
- }
-
- bool ImplScaleConvolutionHor(
- Bitmap& rSource,
- Bitmap& rTarget,
- const double& rScaleX,
- const Kernel& aKernel)
- {
- // Do horizontal filtering
- OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
- const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
- const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
-
- if(nWidth == nNewWidth)
- {
- return true;
- }
-
- BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
-
- if(pReadAcc)
- {
- double* pWeights = nullptr;
- sal_uInt32* pPixels = nullptr;
- sal_uInt32* pCount = nullptr;
- sal_uInt32 aNumberOfContributions(0);
-
- const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
- ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
- rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
- BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
- bool bResult(nullptr != pWriteAcc);
-
- if(bResult)
- {
- for(sal_uInt32 y(0); y < nHeight; y++)
- {
- for(sal_uInt32 x(0); x < nNewWidth; x++)
- {
- const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
- double aSum(0.0);
- double aValueRed(0.0);
- double aValueGreen(0.0);
- double aValueBlue(0.0);
-
- for(sal_uInt32 j(0); j < pCount[x]; j++)
- {
- const sal_uInt32 aIndex(aBaseIndex + j);
- const double aWeight(pWeights[aIndex]);
- BitmapColor aColor;
-
- aSum += aWeight;
-
- if(pReadAcc->HasPalette())
- {
- aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
- }
- else
- {
- aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
- }
-
- aValueRed += aWeight * aColor.GetRed();
- aValueGreen += aWeight * aColor.GetGreen();
- aValueBlue += aWeight * aColor.GetBlue();
- }
-
- const BitmapColor aResultColor(
- static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
- static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
- static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
-
- pWriteAcc->SetPixel(y, x, aResultColor);
- }
- }
-
- Bitmap::ReleaseAccess(pWriteAcc);
- }
-
- Bitmap::ReleaseAccess(pReadAcc);
- delete[] pWeights;
- delete[] pCount;
- delete[] pPixels;
-
- if(bResult)
- {
- return true;
- }
- }
-
- return false;
- }
-
- bool ImplScaleConvolutionVer(
- Bitmap& rSource,
- Bitmap& rTarget,
- const double& rScaleY,
- const Kernel& aKernel)
- {
- // Do vertical filtering
- OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
- const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
- const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
-
- if(nHeight == nNewHeight)
- {
- return true;
- }
-
- BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
-
- if(pReadAcc)
- {
- double* pWeights = nullptr;
- sal_uInt32* pPixels = nullptr;
- sal_uInt32* pCount = nullptr;
- sal_uInt32 aNumberOfContributions(0);
-
- const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
- ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
- rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
- BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
- bool bResult(nullptr != pWriteAcc);
-
- if(pWriteAcc)
- {
- for(sal_uInt32 x(0); x < nWidth; x++)
- {
- for(sal_uInt32 y(0); y < nNewHeight; y++)
- {
- const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
- double aSum(0.0);
- double aValueRed(0.0);
- double aValueGreen(0.0);
- double aValueBlue(0.0);
-
- for(sal_uInt32 j(0); j < pCount[y]; j++)
- {
- const sal_uInt32 aIndex(aBaseIndex + j);
- const double aWeight(pWeights[aIndex]);
- BitmapColor aColor;
-
- aSum += aWeight;
-
- if(pReadAcc->HasPalette())
- {
- aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
- }
- else
- {
- aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
- }
-
- aValueRed += aWeight * aColor.GetRed();
- aValueGreen += aWeight * aColor.GetGreen();
- aValueBlue += aWeight * aColor.GetBlue();
- }
-
- const BitmapColor aResultColor(
- static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
- static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
- static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
-
- if(pWriteAcc->HasPalette())
- {
- pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
- }
- else
- {
- pWriteAcc->SetPixel(y, x, aResultColor);
- }
- }
- }
- }
-
- Bitmap::ReleaseAccess(pWriteAcc);
- Bitmap::ReleaseAccess(pReadAcc);
-
- delete[] pWeights;
- delete[] pCount;
- delete[] pPixels;
-
- if(bResult)
- {
- return true;
- }
- }
-
- return false;
- }
-}
-
-// #i121233# Added BmpScaleFlag::Lanczos, BmpScaleFlag::BiCubic, BmpScaleFlag::BiLinear and
-// BmpScaleFlag::Box derived from the original commit from Tomas Vajngerl (see
-// bugzilla task for details) Thanks!
-bool Bitmap::ImplScaleConvolution(
- const double& rScaleX,
- const double& rScaleY,
- const Kernel& aKernel)
-{
- const bool bMirrorHor(rScaleX < 0.0);
- const bool bMirrorVer(rScaleY < 0.0);
- const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
- const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
- const sal_uInt32 nWidth(GetSizePixel().Width());
- const sal_uInt32 nHeight(GetSizePixel().Height());
- const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
- const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
- const bool bScaleHor(nWidth != nNewWidth);
- const bool bScaleVer(nHeight != nNewHeight);
- const bool bMirror(bMirrorHor || bMirrorVer);
-
- if(!bMirror && !bScaleHor && !bScaleVer)
- {
- return true;
- }
-
- bool bResult(true);
- BmpMirrorFlags nMirrorFlags(BmpMirrorFlags::NONE);
- bool bMirrorAfter(false);
-
- if(bMirror)
- {
- if(bMirrorHor)
- {
- nMirrorFlags |= BmpMirrorFlags::Horizontal;
- }
-
- if(bMirrorVer)
- {
- nMirrorFlags |= BmpMirrorFlags::Vertical;
- }
-
- const sal_uInt32 nStartSize(nWidth * nHeight);
- const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
-
- bMirrorAfter = nStartSize > nEndSize;
-
- if(!bMirrorAfter)
- {
- bResult = Mirror(nMirrorFlags);
- }
- }
-
- Bitmap aResult;
-
- if(bResult)
- {
- const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
- const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
- Bitmap aSource(*this);
-
- if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
- {
- if(bScaleHor)
- {
- bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
- }
-
- if(bResult && bScaleVer)
- {
- if(bScaleHor)
- {
- // copy partial result, independent of color depth
- aSource = aResult;
- }
-
- bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
- }
- }
- else
- {
- if(bScaleVer)
- {
- bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
- }
-
- if(bResult && bScaleHor)
- {
- if(bScaleVer)
- {
- // copy partial result, independent of color depth
- aSource = aResult;
- }
-
- bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
- }
- }
- }
-
- if(bResult && bMirrorAfter)
- {
- bResult = aResult.Mirror(nMirrorFlags);
- }
-
- if(bResult)
- {
- ImplAdaptBitCount(aResult);
- *this = aResult;
- }
-
- return bResult;
-}
-
bool Bitmap::Dither( BmpDitherFlags nDitherFlags )
{
bool bRet = false;