[Libreoffice-commits] core.git: 3 commits - vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/source vcl/win
Tomaž Vajngerl
tomaz.vajngerl at collabora.com
Fri Dec 11 02:50:31 PST 2015
vcl/Library_vcl.mk | 1
vcl/inc/BitmapScaleConvolution.hxx | 62 ++++
vcl/opengl/salbmp.cxx | 116 +++++--
vcl/source/bitmap/BitmapScaleConvolution.cxx | 397 +++++++++++++++++++++++++++
vcl/source/gdi/bitmap3.cxx | 384 --------------------------
vcl/win/gdi/salgdi2.cxx | 32 ++
6 files changed, 579 insertions(+), 413 deletions(-)
New commits:
commit 1cc30679765ce996a009865e6bad3e5b74b96b41
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Thu Dec 10 13:44:05 2015 +0100
tdf#94851 can't use OpenGLSalBitmap with WinSalGraphics
Printing is done with the WinSalGraphics and not with
WinOpenGLSalGraphics on Windows even when OpenGL is enabled, but
the SalBitmap is still using the OpenGLSalBitmap which can't be
used with WinSalGraphics. So detect when the implementation of
SalGraphic is "wrong" and convert.
Change-Id: I99cd6b6403e9bd42d6f5b7d7cb07f48588c17ab8
diff --git a/vcl/win/gdi/salgdi2.cxx b/vcl/win/gdi/salgdi2.cxx
index 64516c2..aa08d91 100644
--- a/vcl/win/gdi/salgdi2.cxx
+++ b/vcl/win/gdi/salgdi2.cxx
@@ -34,6 +34,8 @@
#include "vcl/bmpacc.hxx"
#include "outdata.hxx"
#include "salgdiimpl.hxx"
+#include "opengl/win/gdiimpl.hxx"
+
bool WinSalGraphics::supportsOperation( OutDevSupportType eType ) const
{
@@ -71,7 +73,35 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
void WinSalGraphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap)
{
- mpImpl->drawBitmap( rPosAry, rSalBitmap );
+ if (dynamic_cast<WinOpenGLSalGraphicsImpl*>(mpImpl.get()) == nullptr &&
+ dynamic_cast<const WinSalBitmap*>(&rSalBitmap) == nullptr)
+ {
+ SalBitmap& rConstBitmap = const_cast<SalBitmap&>(rSalBitmap);
+ BitmapBuffer* pRead = rConstBitmap.AcquireBuffer(BITMAP_READ_ACCESS);
+
+ std::unique_ptr<WinSalBitmap> pWinSalBitmap(new WinSalBitmap());
+ pWinSalBitmap->Create(rConstBitmap.GetSize(), rConstBitmap.GetBitCount(), BitmapPalette());
+ BitmapBuffer* pWrite = pWinSalBitmap->AcquireBuffer(BITMAP_WRITE_ACCESS);
+
+ sal_uInt8* pSource(pRead->mpBits);
+ sal_uInt8* pDestination(pWrite->mpBits);
+
+ for (long y = 0; y < pRead->mnHeight; y++)
+ {
+ memcpy(pDestination, pSource, pRead->mnScanlineSize);
+ pSource += pRead->mnScanlineSize;
+ pDestination += pWrite->mnScanlineSize;
+ }
+ pWinSalBitmap->ReleaseBuffer(pWrite, BITMAP_WRITE_ACCESS);
+
+ rConstBitmap.ReleaseBuffer(pRead, BITMAP_READ_ACCESS);
+
+ mpImpl->drawBitmap(rPosAry, *pWinSalBitmap.get());
+ }
+ else
+ {
+ mpImpl->drawBitmap(rPosAry, rSalBitmap);
+ }
}
void WinSalGraphics::drawBitmap( const SalTwoRect& rPosAry,
commit 8a498fad249b3a92f275f33b683f242cb8d68b7b
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Thu Dec 10 13:41:36 2015 +0100
tdf#94851 use BGR color order in Windows
Change-Id: I06dd26caed35bcfdf073abf64035a01e0b45fcce
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 4a05af4..75d4d21 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -38,7 +38,45 @@
namespace
{
-bool isValidBitCount( sal_uInt16 nBitCount )
+inline bool determineTextureFormat(sal_uInt16 nBits, GLenum& nFormat, GLenum& nType)
+{
+ switch(nBits)
+ {
+ case 8:
+ nFormat = GL_LUMINANCE;
+ nType = GL_UNSIGNED_BYTE;
+ return true;
+ case 16:
+#ifdef WNT
+ nFormat = GL_BGR;
+#else
+ nFormat = GL_RGB;
+#endif
+ nType = GL_UNSIGNED_SHORT_5_6_5;
+ return true;
+ case 24:
+#ifdef WNT
+ nFormat = GL_BGR;
+#else
+ nFormat = GL_RGB;
+#endif
+ nType = GL_UNSIGNED_BYTE;
+ return true;
+ case 32:
+#ifdef WNT
+ nFormat = GL_BGRA;
+#else
+ nFormat = GL_RGBA;
+#endif
+ nType = GL_UNSIGNED_BYTE;
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+inline bool isValidBitCount( sal_uInt16 nBitCount )
{
return (nBitCount == 1) || (nBitCount == 4) || (nBitCount == 8) || (nBitCount == 16) || (nBitCount == 24) || (nBitCount == 32);
}
@@ -404,18 +442,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
// no conversion needed for truecolor
pData = maUserBuffer.get();
- switch( mnBits )
- {
- case 16: nFormat = GL_RGB;
- nType = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case 24: nFormat = GL_RGB;
- nType = GL_UNSIGNED_BYTE;
- break;
- case 32: nFormat = GL_RGBA;
- nType = GL_UNSIGNED_BYTE;
- break;
- }
+ determineTextureFormat(mnBits, nFormat, nType);
}
else if( mnBits == 8 && maPalette.IsGreyPalette() )
{
@@ -431,8 +458,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
// convert to 24 bits RGB using palette
pData = new sal_uInt8[mnBufHeight * mnBufWidth * 3];
bAllocated = true;
- nFormat = GL_RGB;
- nType = GL_UNSIGNED_BYTE;
+ determineTextureFormat(24, nFormat, nType);
std::unique_ptr<ImplPixelFormat> pSrcFormat(ImplPixelFormat::GetFormat(mnBits, maPalette));
@@ -479,6 +505,9 @@ bool OpenGLSalBitmap::ReadTexture()
{
sal_uInt8* pData = maUserBuffer.get();
+ GLenum nFormat = GL_RGBA;
+ GLenum nType = GL_UNSIGNED_BYTE;
+
VCL_GL_INFO( "::ReadTexture " << mnWidth << "x" << mnHeight << " bits: " << mnBits);
if( pData == nullptr )
@@ -486,24 +515,7 @@ bool OpenGLSalBitmap::ReadTexture()
if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32)
{
- GLenum nFormat = GL_RGBA;
- GLenum nType = GL_UNSIGNED_BYTE;
-
- switch( mnBits )
- {
- case 8: nFormat = GL_LUMINANCE;
- nType = GL_UNSIGNED_BYTE;
- break;
- case 16: nFormat = GL_RGB;
- nType = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case 24: nFormat = GL_RGB;
- nType = GL_UNSIGNED_BYTE;
- break;
- case 32: nFormat = GL_RGBA;
- nType = GL_UNSIGNED_BYTE;
- break;
- }
+ determineTextureFormat(mnBits, nFormat, nType);
makeSomeOpenGLContextCurrent();
maTexture.Read(nFormat, nType, pData);
@@ -516,7 +528,8 @@ bool OpenGLSalBitmap::ReadTexture()
std::vector<sal_uInt8> aBuffer(mnWidth * mnHeight * 3);
makeSomeOpenGLContextCurrent();
sal_uInt8* pBuffer = aBuffer.data();
- maTexture.Read(GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+ determineTextureFormat(24, nFormat, nType);
+ maTexture.Read(nFormat, nType, pBuffer);
int nShift = 7;
size_t nIndex = 0;
@@ -724,6 +737,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
pBuffer->mnScanlineSize = mnBytesPerRow;
pBuffer->mpBits = maUserBuffer.get();
pBuffer->mnBitCount = mnBits;
+
switch (mnBits)
{
case 1:
@@ -737,21 +751,48 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
break;
case 16:
{
+#ifdef WNT
+ pBuffer->mnFormat = BMP_FORMAT_16BIT_TC_LSB_MASK;
+ ColorMaskElement aRedMask(0x00007c00);
+ aRedMask.CalcMaskShift();
+ ColorMaskElement aGreenMask(0x000003e0);
+ aGreenMask.CalcMaskShift();
+ ColorMaskElement aBlueMask(0x0000001f);
+ aBlueMask.CalcMaskShift();
+ pBuffer->maColorMask = ColorMask(aRedMask, aGreenMask, aBlueMask);
+#else
pBuffer->mnFormat = BMP_FORMAT_16BIT_TC_MSB_MASK;
- ColorMaskElement aRedMask(0xf800);
+ ColorMaskElement aRedMask(0x0000f800);
aRedMask.CalcMaskShift();
- ColorMaskElement aGreenMask(0x07e0);
+ ColorMaskElement aGreenMask(0x000007e0);
aGreenMask.CalcMaskShift();
- ColorMaskElement aBlueMask(0x001f);
+ ColorMaskElement aBlueMask(0x0000001f);
aBlueMask.CalcMaskShift();
pBuffer->maColorMask = ColorMask(aRedMask, aGreenMask, aBlueMask);
+#endif
break;
}
case 24:
+ {
+#ifdef WNT
+ pBuffer->mnFormat = BMP_FORMAT_24BIT_TC_BGR;
+#else
pBuffer->mnFormat = BMP_FORMAT_24BIT_TC_RGB;
+#endif
break;
+ }
case 32:
{
+#ifdef WNT
+ pBuffer->mnFormat = BMP_FORMAT_32BIT_TC_BGRA;
+ ColorMaskElement aRedMask(0x00ff0000);
+ aRedMask.CalcMaskShift();
+ ColorMaskElement aGreenMask(0x0000ff00);
+ aGreenMask.CalcMaskShift();
+ ColorMaskElement aBlueMask(0x000000ff);
+ aBlueMask.CalcMaskShift();
+ pBuffer->maColorMask = ColorMask(aRedMask, aGreenMask, aBlueMask);
+#else
pBuffer->mnFormat = BMP_FORMAT_32BIT_TC_RGBA;
ColorMaskElement aRedMask(0xff000000);
aRedMask.CalcMaskShift();
@@ -760,6 +801,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
ColorMaskElement aBlueMask(0x0000ff00);
aBlueMask.CalcMaskShift();
pBuffer->maColorMask = ColorMask(aRedMask, aGreenMask, aBlueMask);
+#endif
break;
}
}
commit 5919f0bbe82129e25962be88db4156dd7daa2a36
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Thu Dec 10 12:55:47 2015 +0100
vcl: extract scale convolution from bitmap to its own class/file
Change-Id: Ibb10aa7450b78ca2709da38857f095ccbc679c54
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index c7eee7f..7b95621 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -314,6 +314,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 0000000..a026f03
--- /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 0000000..a596603
--- /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 9359fb9..4ffd136 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;
More information about the Libreoffice-commits
mailing list