20#include <osl/diagnose.h>
35void ImplCalculateContributions(
36 const sal_Int32 aSourceSize,
37 const sal_Int32 aDestinationSize,
38 sal_Int32& aNumberOfContributions,
39 std::vector<sal_Int16>& rWeights,
40 std::vector<sal_Int32>& rPixels,
41 std::vector<sal_Int32>& rCounts,
42 const Kernel& aKernel)
44 const double fSamplingRadius(aKernel.GetWidth());
45 const double fScale(aDestinationSize /
static_cast< double >(aSourceSize));
46 const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
47 const double fFilterFactor(std::min(fScale, 1.0));
49 aNumberOfContributions = (sal_Int32(fabs(ceil(fScaledRadius))) * 2) + 1;
50 const sal_Int32 nAllocSize(aDestinationSize * aNumberOfContributions);
51 rWeights.resize(nAllocSize);
52 rPixels.resize(nAllocSize);
53 rCounts.resize(aDestinationSize);
55 for(sal_Int32
i(0);
i < aDestinationSize;
i++)
57 const sal_Int32
aIndex(i * aNumberOfContributions);
58 const double aCenter(i / fScale);
59 const sal_Int32 aLeft(
static_cast< sal_Int32
>(floor(aCenter - fScaledRadius)));
60 const sal_Int32 aRight(
static_cast< sal_Int32
>(ceil(aCenter + fScaledRadius)));
61 sal_Int32 aCurrentCount(0);
63 for(sal_Int32 j(aLeft); j <= aRight; j++)
65 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter -
static_cast< double>(j))));
68 if(fabs(aWeight) < 0.0001)
74 const sal_Int32 aPixelIndex(
MinMax(j, 0, aSourceSize - 1));
75 const sal_Int32
nIndex(aIndex + aCurrentCount);
78 rWeights[
nIndex] = aWeight * 255;
79 rPixels[
nIndex] = aPixelIndex;
84 rCounts[
i] = aCurrentCount;
88bool ImplScaleConvolutionHor(
Bitmap& rSource,
Bitmap& rTarget,
const double& rScaleX,
const Kernel& aKernel)
91 OSL_ENSURE(rScaleX > 0.0,
"Error in scaling: Mirror given in non-mirror-capable method (!)");
93 const sal_Int32 nNewWidth(
FRound(nWidth * rScaleX));
95 if(nWidth == nNewWidth)
104 std::vector<sal_Int16> aWeights;
105 std::vector<sal_Int32> aPixels;
106 std::vector<sal_Int32> aCounts;
107 sal_Int32 aNumberOfContributions(0);
110 ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, aWeights, aPixels, aCounts, aKernel);
113 bool bResult(pWriteAcc);
117 for(sal_Int32
y(0);
y < nHeight;
y++)
119 Scanline pScanline = pWriteAcc->GetScanline( y );
120 Scanline pScanlineRead = pReadAcc->GetScanline( y );
121 for(sal_Int32
x(0);
x < nNewWidth;
x++)
123 const sal_Int32 aBaseIndex(x * aNumberOfContributions);
125 sal_Int32 aValueRed(0);
126 sal_Int32 aValueGreen(0);
127 sal_Int32 aValueBlue(0);
129 for(sal_Int32 j(0); j < aCounts[
x]; j++)
131 const sal_Int32
aIndex(aBaseIndex + j);
132 const sal_Int16 aWeight(aWeights[aIndex]);
137 if(pReadAcc->HasPalette())
139 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, aPixels[aIndex]));
143 aColor = pReadAcc->GetPixelFromData(pScanlineRead, aPixels[aIndex]);
146 aValueRed += aWeight * aColor.
GetRed();
147 aValueGreen += aWeight * aColor.
GetGreen();
148 aValueBlue += aWeight * aColor.
GetBlue();
154 static_cast< sal_uInt8 >(
MinMax(
static_cast< sal_Int32
>(aValueRed / aSum), 0, 255)),
155 static_cast< sal_uInt8 >(
MinMax(
static_cast< sal_Int32
>(aValueGreen / aSum), 0, 255)),
156 static_cast< sal_uInt8 >(
MinMax(
static_cast< sal_Int32
>(aValueBlue / aSum), 0, 255)));
158 pWriteAcc->SetPixelOnData(pScanline, x, aResultColor);
178bool ImplScaleConvolutionVer(
Bitmap& rSource,
Bitmap& rTarget,
const double& rScaleY,
const Kernel& aKernel)
181 OSL_ENSURE(rScaleY > 0.0,
"Error in scaling: Mirror given in non-mirror-capable method (!)");
183 const sal_Int32 nNewHeight(
FRound(nHeight * rScaleY));
185 if(nHeight == nNewHeight)
194 std::vector<sal_Int16> aWeights;
195 std::vector<sal_Int32> aPixels;
196 std::vector<sal_Int32> aCounts;
197 sal_Int32 aNumberOfContributions(0);
200 ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, aWeights, aPixels, aCounts, aKernel);
206 std::vector<BitmapColor> aScanline(nHeight);
207 for(sal_Int32
x(0);
x < nWidth;
x++)
209 for(sal_Int32
y(0);
y < nHeight;
y++)
210 if(pReadAcc->HasPalette())
211 aScanline[
y] = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, x));
213 aScanline[
y] = pReadAcc->GetPixel(y, x);
214 for(sal_Int32
y(0);
y < nNewHeight;
y++)
216 const sal_Int32 aBaseIndex(y * aNumberOfContributions);
218 sal_Int32 aValueRed(0);
219 sal_Int32 aValueGreen(0);
220 sal_Int32 aValueBlue(0);
222 for(sal_Int32 j(0); j < aCounts[
y]; j++)
224 const sal_Int32
aIndex(aBaseIndex + j);
225 const sal_Int16 aWeight(aWeights[aIndex]);
228 aValueRed += aWeight * aColor.
GetRed();
229 aValueGreen += aWeight * aColor.
GetGreen();
230 aValueBlue += aWeight * aColor.
GetBlue();
236 static_cast< sal_uInt8 >(
MinMax(
static_cast< sal_Int32
>(aValueRed / aSum), 0, 255)),
237 static_cast< sal_uInt8 >(
MinMax(
static_cast< sal_Int32
>(aValueGreen / aSum), 0, 255)),
238 static_cast< sal_uInt8 >(
MinMax(
static_cast< sal_Int32
>(aValueBlue / aSum), 0, 255)));
240 if(pWriteAcc->HasPalette())
242 pWriteAcc->SetPixelIndex(y, x,
static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
246 pWriteAcc->SetPixel(y, x, aResultColor);
258bool ImplScaleConvolution(
Bitmap& rBitmap,
const double& rScaleX,
const double& rScaleY,
const Kernel& aKernel)
260 const bool bMirrorHor(rScaleX < 0.0);
261 const bool bMirrorVer(rScaleY < 0.0);
262 const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
263 const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
266 const sal_Int32 nNewWidth(
FRound(nWidth * fScaleX));
267 const sal_Int32 nNewHeight(
FRound(nHeight * fScaleY));
268 const bool bScaleHor(nWidth != nNewWidth);
269 const bool bScaleVer(nHeight != nNewHeight);
270 const bool bMirror(bMirrorHor || bMirrorVer);
272 if (!bMirror && !bScaleHor && !bScaleVer)
279 bool bMirrorAfter(
false);
293 const sal_Int32 nStartSize(nWidth * nHeight);
294 const sal_Int32 nEndSize(nNewWidth * nNewHeight);
296 bMirrorAfter = nStartSize > nEndSize;
300 bResult = rBitmap.
Mirror(nMirrorFlags);
308 const sal_Int32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
309 const sal_Int32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
312 if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
316 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
319 if(bResult && bScaleVer)
327 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
334 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
337 if(bResult && bScaleHor)
345 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
350 if(bResult && bMirrorAfter)
352 bResult = aResult.
Mirror(nMirrorFlags);
368 bool bRetval =
false;
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Size GetSizePixel() const
void AdaptBitCount(Bitmap &rNew) const
bool Mirror(BmpMirrorFlags nMirrorFlags)
Mirror the bitmap.
sal_uInt8 GetBlue() const
sal_uInt8 GetGreen() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
std::unique_ptr< Kernel > mxKernel
virtual BitmapEx execute(BitmapEx const &rBitmap) const override
std::deque< AttacherIndex_Impl > aIndex
tools::Long FRound(double fVal)
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)