summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/bitmap3.cxx
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.com>2015-12-10 12:55:47 +0100
committerTomaž Vajngerl <tomaz.vajngerl@collabora.com>2015-12-11 11:49:02 +0100
commit5919f0bbe82129e25962be88db4156dd7daa2a36 (patch)
tree48a7d5f8eda42fe2422a0ad66a511e971941cec5 /vcl/source/gdi/bitmap3.cxx
parentba659f71f482dd74a83aaa9710ea65fff27ac274 (diff)
vcl: extract scale convolution from bitmap to its own class/file
Change-Id: Ibb10aa7450b78ca2709da38857f095ccbc679c54
Diffstat (limited to 'vcl/source/gdi/bitmap3.cxx')
-rw-r--r--vcl/source/gdi/bitmap3.cxx384
1 files changed, 9 insertions, 375 deletions
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index 9359fb981308..4ffd136ac683 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))
@@ -959,30 +953,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;
}
}
@@ -1320,362 +1310,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;