diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/bitmap/BitmapScaleSuperFilter.cxx | 263 |
1 files changed, 64 insertions, 199 deletions
diff --git a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx index 78249ce1eec6..4b6d8ede851b 100644 --- a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx +++ b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx @@ -32,7 +32,7 @@ namespace { -#define MAP_PRECISION 7 +constexpr int MAP_PRECISION = 7; typedef sal_Int32 BilinearWeightType; @@ -98,215 +98,78 @@ struct ScaleContext constexpr long constScaleThreadStrip = 32; -typedef void (*ScaleRangeFn)(ScaleContext & rContext, long nStartY, long nEndY); +typedef void (*ScaleRangeFn)(const ScaleContext & rContext, long nStartY, long nEndY); -struct ScaleDown24bit +template <size_t nSize> struct ScaleFunc { - static int getColorComponent() { return 3; } + // for scale down - static std::vector<int> sumRowsVector() + static inline void generateSumRows(Scanline& pTmpX, std::array<int, nSize>& sumRows) { - std::vector<int> sumRows(3); - return sumRows; + for (int& n : sumRows) + n += (*pTmpX++) << MAP_PRECISION; } - static std::vector<int> sumNumbersVector() + static inline void generateSumRows(BilinearWeightType const nWeightX, Scanline& pTmpX, + std::array<int, nSize>& sumRows) { - std::vector<int> sumNumbers(3); - return sumNumbers; + for (int& n : sumRows) + n += (nWeightX * (*pTmpX++)); } - static inline void generateSumRows(Scanline& pTmpX, std::vector<int>& sumRows) + static inline void generateSumRows(BilinearWeightType const nTotalWeightX, + std::array<int, nSize>& sumRows) { - sumRows[0] += (*pTmpX) << MAP_PRECISION; pTmpX++; - sumRows[1] += (*pTmpX) << MAP_PRECISION; pTmpX++; - sumRows[2] += (*pTmpX) << MAP_PRECISION; pTmpX++; - } - - static inline void generateSumRows(BilinearWeightType const nWeightX, Scanline& pTmpX, std::vector<int>& sumRows) - { - sumRows[0] += (nWeightX * (*pTmpX)); pTmpX++; - sumRows[1] += (nWeightX * (*pTmpX)); pTmpX++; - sumRows[2] += (nWeightX * (*pTmpX)); pTmpX++; - } - - static inline void generateSumRows(BilinearWeightType const nTotalWeightX, std::vector<int>& sumRows) - { - sumRows[0] /= nTotalWeightX; - sumRows[1] /= nTotalWeightX; - sumRows[2] /= nTotalWeightX; - } - - static inline void generateSumNumbers(BilinearWeightType const nWeightY, std::vector<int>& sumRows, - std::vector<int>& sumNumbers) - { - sumNumbers[0] += nWeightY * sumRows[0]; - sumNumbers[1] += nWeightY * sumRows[1]; - sumNumbers[2] += nWeightY * sumRows[2]; - } - - static inline void generateSumNumbers(BilinearWeightType const nTotalWeightY, std::vector<int>& sumNumbers) { - sumNumbers[0] /= nTotalWeightY; - sumNumbers[1] /= nTotalWeightY; - sumNumbers[2] /= nTotalWeightY; - } - - static inline void calculateDestination(Scanline& pScanDest, std::vector<int>& sumNumbers) { - - *pScanDest = sumNumbers[0]; pScanDest++; - *pScanDest = sumNumbers[1]; pScanDest++; - *pScanDest = sumNumbers[2]; pScanDest++; - } - -}; - -struct ScaleDown32bit -{ - static int getColorComponent() { return 4; } - - static std::vector<int> sumRowsVector() - { - std::vector<int> sumRows(4); - return sumRows; - } - - static std::vector<int> sumNumbersVector() - { - std::vector<int> sumNumbers(4); - return sumNumbers; - } - - static inline void generateSumRows(Scanline& pTmpX, std::vector<int>& sumRows) { - sumRows[0] += (*pTmpX) << MAP_PRECISION; pTmpX++; - sumRows[1] += (*pTmpX) << MAP_PRECISION; pTmpX++; - sumRows[2] += (*pTmpX) << MAP_PRECISION; pTmpX++; - sumRows[3] += (*pTmpX) << MAP_PRECISION; pTmpX++; - } - - static inline void generateSumRows(BilinearWeightType const nWeightX, Scanline& pTmpX, std::vector<int>& sumRows) { - sumRows[0] += (nWeightX * (*pTmpX)); pTmpX++; - sumRows[1] += (nWeightX * (*pTmpX)); pTmpX++; - sumRows[2] += (nWeightX * (*pTmpX)); pTmpX++; - sumRows[3] += (nWeightX * (*pTmpX)); pTmpX++; - } - - static inline void generateSumRows(BilinearWeightType const nTotalWeightX, std::vector<int>& sumRows) { - sumRows[0] /= nTotalWeightX; - sumRows[1] /= nTotalWeightX; - sumRows[2] /= nTotalWeightX; - sumRows[3] /= nTotalWeightX; + for (int& n : sumRows) + n /= nTotalWeightX; } static inline void generateSumNumbers(BilinearWeightType const nWeightY, - std::vector<int>& sumRows, std::vector<int>& sumNumbers) - { - sumNumbers[0] += nWeightY * sumRows[0]; - sumNumbers[1] += nWeightY * sumRows[1]; - sumNumbers[2] += nWeightY * sumRows[2]; - sumNumbers[3] += nWeightY * sumRows[3]; - } - - static inline void generateSumNumbers(BilinearWeightType const nTotalWeightY, std::vector<int>& sumNumbers) { - sumNumbers[0] /= nTotalWeightY; - sumNumbers[1] /= nTotalWeightY; - sumNumbers[2] /= nTotalWeightY; - sumNumbers[3] /= nTotalWeightY; - } - - static inline void calculateDestination(Scanline& pScanDest, std::vector<int>& sumNumbers) { - *pScanDest = sumNumbers[0]; pScanDest++; - *pScanDest = sumNumbers[1]; pScanDest++; - *pScanDest = sumNumbers[2]; pScanDest++; - *pScanDest = sumNumbers[3]; pScanDest++; - } - -}; - -struct ScaleUp24bit -{ - static int getColorComponent() { return 3; } - static std::vector<sal_uInt8> colorComponents1() + std::array<int, nSize>& sumRows, + std::array<int, nSize>& sumNumbers) { - std::vector<sal_uInt8> nComponent(3); - return nComponent; + std::transform(sumRows.begin(), sumRows.end(), sumNumbers.begin(), sumNumbers.begin(), + [nWeightY](int n1, int n2) { return nWeightY * n1 + n2; }); } - static std::vector<sal_uInt8> colorComponents2() + static inline void generateSumNumbers(BilinearWeightType const nTotalWeightY, + std::array<int, nSize>& sumNumbers) { - std::vector<sal_uInt8> nComponent(3); - return nComponent; + for (int& n : sumNumbers) + n /= nTotalWeightY; } - static inline void generateComponent(Scanline & pColorPtr0, Scanline & pColorPtr1, - BilinearWeightType const nTempFX, std::vector<sal_uInt8>& nComponents) + static inline void calculateDestination(Scanline& pScanDest, std::array<int, nSize>& sumNumbers) { - nComponents[0] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); - pColorPtr0++; pColorPtr1++; - nComponents[1] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); - pColorPtr0++; pColorPtr1++; - nComponents[2] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); + pScanDest = std::copy(sumNumbers.begin(), sumNumbers.end(), pScanDest); } - static inline void calculteScanDestination(Scanline& pScanDest, BilinearWeightType const nTempFY, - std::vector<sal_uInt8>& nComponents1, std::vector<sal_uInt8>& nComponents2) - { - *pScanDest = MAP(nComponents1[0], nComponents2[0], nTempFY); - pScanDest++; - *pScanDest = MAP(nComponents1[1], nComponents2[1], nTempFY); - pScanDest++; - *pScanDest = MAP(nComponents1[2], nComponents2[2], nTempFY); - pScanDest++; - } - -}; + // for scale up -struct ScaleUp32bit -{ - static int getColorComponent() { return 4; } - - static std::vector<sal_uInt8> colorComponents1() + static inline void generateComponent(Scanline pColorPtr0, Scanline pColorPtr1, + BilinearWeightType const nTempFX, + std::array<sal_uInt8, nSize>& nComponents) { - std::vector<sal_uInt8> nComponent(4); - return nComponent; + for (sal_uInt8& rComponent : nComponents) + rComponent = MAP(*pColorPtr0++, *pColorPtr1++, nTempFX); } - static std::vector<sal_uInt8> colorComponents2() + static inline void calculateDestination(Scanline& pScanDest, BilinearWeightType const nTempFY, + const std::array<sal_uInt8, nSize>& nComponents1, + const std::array<sal_uInt8, nSize>& nComponents2) { - std::vector<sal_uInt8> nComponent(4); - return nComponent; + pScanDest = std::transform( + nComponents1.begin(), nComponents1.end(), nComponents2.begin(), pScanDest, + [nTempFY](sal_uInt8 c1, sal_uInt8 c2) { return MAP(c1, c2, nTempFY); }); } - - static inline void generateComponent(Scanline & pColorPtr0, Scanline & pColorPtr1, - BilinearWeightType const nTempFX, std::vector<sal_uInt8>& nComponents) - { - nComponents[0] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); - pColorPtr0++; pColorPtr1++; - nComponents[1] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); - pColorPtr0++; pColorPtr1++; - nComponents[2] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); - pColorPtr0++; pColorPtr1++; - nComponents[3] = MAP(*pColorPtr0, *pColorPtr1, nTempFX); - } - - static inline void calculteScanDestination(Scanline& pScanDest, BilinearWeightType const nTempFY, - std::vector<sal_uInt8>& nComponents1, std::vector<sal_uInt8>& nComponents2) - { - *pScanDest = MAP(nComponents1[0], nComponents2[0], nTempFY); - pScanDest++; - *pScanDest = MAP(nComponents1[1], nComponents2[1], nTempFY); - pScanDest++; - *pScanDest = MAP(nComponents1[2], nComponents2[2], nTempFY); - pScanDest++; - *pScanDest = MAP(nComponents1[3], nComponents2[3], nTempFY); - pScanDest++; - } - }; -template<typename ScaleFunction> -void scaleDown (ScaleContext &rCtx, long nStartY, long nEndY) +template <int nColorBits> +void scaleDown (const ScaleContext &rCtx, long nStartY, long nEndY) { - const int constColorComponents = ScaleFunction::getColorComponent(); + constexpr int nColorComponents = nColorBits / 8; + static_assert(nColorComponents * 8 == nColorBits, "nColorBits must be divisible by 8"); + using ScaleFunction = ScaleFunc<nColorComponents>; const long nStartX = 0; const long nEndX = rCtx.mnDestW - 1; @@ -349,15 +212,15 @@ void scaleDown (ScaleContext &rCtx, long nStartY, long nEndY) 1 : (rCtx.maMapIX[nRight] - rCtx.maMapIX[nLeft]); } - std::vector<int> sumNumbers = ScaleFunction::sumNumbersVector(); + std::array<int, nColorComponents> sumNumbers{}; // zero-initialize BilinearWeightType nTotalWeightY = 0; for (long i = 0; i<= nLineRange; i++) { Scanline pTmpY = rCtx.mpSrc->GetScanline(nLineStart + i); - Scanline pTmpX = pTmpY + constColorComponents * nRowStart; + Scanline pTmpX = pTmpY + nColorComponents * nRowStart; - std::vector<int> sumRows = ScaleFunction::sumRowsVector(); + std::array<int, nColorComponents> sumRows{}; // zero-initialize BilinearWeightType nTotalWeightX = 0; for (long j = 0; j <= nRowRange; j++) @@ -416,10 +279,12 @@ void scaleDown (ScaleContext &rCtx, long nStartY, long nEndY) } } -template <typename ScaleFunction> -void scaleUp(ScaleContext &rCtx, long nStartY, long nEndY) +template <int nColorBits> +void scaleUp(const ScaleContext &rCtx, long nStartY, long nEndY) { - const int nColorComponents = ScaleFunction::getColorComponent(); + constexpr int nColorComponents = nColorBits / 8; + static_assert(nColorComponents * 8 == nColorBits, "nColorBits must be divisible by 8"); + using ScaleFunction = ScaleFunc<nColorComponents>; const long nStartX = 0; const long nEndX = rCtx.mnDestW - 1; @@ -432,8 +297,8 @@ void scaleUp(ScaleContext &rCtx, long nStartY, long nEndY) Scanline pLine1 = rCtx.mpSrc->GetScanline(nTempY+1); Scanline pScanDest = rCtx.mpDest->GetScanline(nY); - std::vector<sal_uInt8> nComponents1 = ScaleFunction::colorComponents1(); - std::vector<sal_uInt8> nComponents2 = ScaleFunction::colorComponents2(); + std::array<sal_uInt8, nColorComponents> nComponents1; // no need to initialize since it's + std::array<sal_uInt8, nColorComponents> nComponents2; // initialized in generateComponent Scanline pColorPtr0; Scanline pColorPtr1; @@ -452,7 +317,7 @@ void scaleUp(ScaleContext &rCtx, long nStartY, long nEndY) pColorPtr1 = pColorPtr0 + nColorComponents; ScaleFunction::generateComponent(pColorPtr0, pColorPtr1, nTempFX, nComponents2); - ScaleFunction::calculteScanDestination(pScanDest, nTempFY, nComponents1, nComponents2); + ScaleFunction::calculateDestination(pScanDest, nTempFY, nComponents1, nComponents2); } } } @@ -460,14 +325,14 @@ void scaleUp(ScaleContext &rCtx, long nStartY, long nEndY) class ScaleTask : public comphelper::ThreadTask { ScaleRangeFn mpScaleRangeFunction; - ScaleContext& mrContext; + const ScaleContext& mrContext; long mnStartY; long mnEndY; public: explicit ScaleTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, ScaleRangeFn pScaleRangeFunction, - ScaleContext& rContext, + const ScaleContext& rContext, long nStartY, long nEndY) : comphelper::ThreadTask(pTag) , mpScaleRangeFunction(pScaleRangeFunction) @@ -482,7 +347,7 @@ public: } }; -void scaleUpPalette8bit(ScaleContext &rCtx, long nStartY, long nEndY) +void scaleUpPalette8bit(const ScaleContext &rCtx, long nStartY, long nEndY) { const long nStartX = 0, nEndX = rCtx.mnDestW - 1; @@ -520,7 +385,7 @@ void scaleUpPalette8bit(ScaleContext &rCtx, long nStartY, long nEndY) } } -void scaleUpPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) +void scaleUpPaletteGeneral(const ScaleContext &rCtx, long nStartY, long nEndY) { const long nStartX = 0, nEndX = rCtx.mnDestW - 1; @@ -555,7 +420,7 @@ void scaleUpPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) } } -void scaleUpNonPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) +void scaleUpNonPaletteGeneral(const ScaleContext &rCtx, long nStartY, long nEndY) { const long nStartX = 0, nEndX = rCtx.mnDestW - 1; @@ -590,7 +455,7 @@ void scaleUpNonPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) } } -void scaleDownPalette8bit(ScaleContext &rCtx, long nStartY, long nEndY) +void scaleDownPalette8bit(const ScaleContext &rCtx, long nStartY, long nEndY) { const long nStartX = 0, nEndX = rCtx.mnDestW - 1; @@ -715,7 +580,7 @@ void scaleDownPalette8bit(ScaleContext &rCtx, long nStartY, long nEndY) } } -void scaleDownPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) +void scaleDownPaletteGeneral(const ScaleContext &rCtx, long nStartY, long nEndY) { const long nStartX = 0, nEndX = rCtx.mnDestW - 1; @@ -843,7 +708,7 @@ void scaleDownPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) } } -void scaleDownNonPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY) +void scaleDownNonPaletteGeneral(const ScaleContext &rCtx, long nStartY, long nEndY) { const long nStartX = 0, nEndX = rCtx.mnDestW - 1; @@ -1039,7 +904,7 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const if (pReadAccess && pWriteAccess) { ScaleRangeFn pScaleRangeFn; - ScaleContext aContext( pReadAccess.get(), + const ScaleContext aContext( pReadAccess.get(), pWriteAccess.get(), pReadAccess->Width(), pWriteAccess->Width(), @@ -1082,13 +947,13 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const { case ScanlineFormat::N24BitTcBgr: case ScanlineFormat::N24BitTcRgb: - pScaleRangeFn = bScaleUp ? scaleUp<ScaleUp24bit> : scaleDown<ScaleDown24bit>; + pScaleRangeFn = bScaleUp ? scaleUp<24> : scaleDown<24>; break; case ScanlineFormat::N32BitTcRgba: case ScanlineFormat::N32BitTcBgra: case ScanlineFormat::N32BitTcArgb: case ScanlineFormat::N32BitTcAbgr: - pScaleRangeFn = bScaleUp ? scaleUp<ScaleUp32bit> : scaleDown<ScaleDown32bit>; + pScaleRangeFn = bScaleUp ? scaleUp<32> : scaleDown<32>; break; default: pScaleRangeFn = bScaleUp ? scaleUpNonPaletteGeneral |