LCOV - code coverage report
Current view: top level - vcl/source/bitmap - BitmapFilterStackBlur.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 208 254 81.9 %
Date: 2015-06-13 12:38:46 Functions: 20 33 60.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  */
      10             : 
      11             : #include <vcl/BitmapFilterStackBlur.hxx>
      12             : #include <vcl/bmpacc.hxx>
      13             : 
      14             : namespace
      15             : {
      16             : 
      17             : static const sal_Int16 constMultiplyTable[255] =
      18             : {
      19             :     512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512,
      20             :     454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512,
      21             :     482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456,
      22             :     437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512,
      23             :     497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328,
      24             :     320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456,
      25             :     446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335,
      26             :     329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512,
      27             :     505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405,
      28             :     399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328,
      29             :     324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271,
      30             :     268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456,
      31             :     451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388,
      32             :     385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335,
      33             :     332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,
      34             :     289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259
      35             : };
      36             : 
      37             : static const sal_Int16 constShiftTable[255] =
      38             : {
      39             :      9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
      40             :     17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
      41             :     19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
      42             :     20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
      43             :     21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
      44             :     21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
      45             :     22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
      46             :     22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
      47             :     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
      48             :     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
      49             :     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
      50             :     23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
      51             :     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
      52             :     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
      53             :     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
      54             :     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
      55             : };
      56             : 
      57           1 : class BlurSharedData
      58             : {
      59             : public:
      60             :     long mnRadius;
      61             :     long mnComponentWidth;
      62             :     long mnColorChannels;
      63             :     long mnDiv;
      64             :     std::vector<sal_uInt8> maStackBuffer;
      65             :     std::vector<long> maPositionTable;
      66             :     std::vector<long> maWeightTable;
      67             : 
      68             :     std::vector<long> mnSumVector;
      69             :     std::vector<long> mnInSumVector;
      70             :     std::vector<long> mnOutSumVector;
      71             : 
      72           1 :     BlurSharedData(long aRadius, long nComponentWidth, long nColorChannels)
      73             :         : mnRadius(aRadius)
      74             :         , mnComponentWidth(nComponentWidth)
      75             :         , mnColorChannels(nColorChannels)
      76           1 :         , mnDiv(aRadius + aRadius + 1)
      77           1 :         , maStackBuffer(mnDiv * mnComponentWidth)
      78             :         , maPositionTable(mnDiv)
      79             :         , maWeightTable(mnDiv)
      80             :         , mnSumVector(mnColorChannels)
      81             :         , mnInSumVector(mnColorChannels)
      82           3 :         , mnOutSumVector(mnColorChannels)
      83             :     {
      84           1 :     }
      85             : 
      86           2 :     void calculateWeightAndPositions(long nLastIndex)
      87             :     {
      88          12 :         for (long i = 0; i < mnDiv; i++)
      89             :         {
      90          10 :             maPositionTable[i] = std::min(nLastIndex, std::max(0L, i - mnRadius));
      91          10 :             maWeightTable[i] = mnRadius + 1 - std::abs(i - mnRadius);
      92             :         }
      93           2 :     }
      94             : 
      95           2 :     long getMultiplyValue()
      96             :     {
      97           2 :         return static_cast<long>(constMultiplyTable[mnRadius]);
      98             :     }
      99             : 
     100           2 :     long getShiftValue()
     101             :     {
     102           2 :         return static_cast<long>(constShiftTable[mnRadius]);
     103             :     }
     104             : };
     105             : 
     106             : struct SumFunction24
     107             : {
     108         400 :     static inline void add(long*& pValue1, long nConstant)
     109             :     {
     110         400 :         pValue1[0] += nConstant;
     111         400 :         pValue1[1] += nConstant;
     112         400 :         pValue1[2] += nConstant;
     113         400 :     }
     114             : 
     115         240 :     static inline void set(long*& pValue1, long nConstant)
     116             :     {
     117         240 :         pValue1[0] = nConstant;
     118         240 :         pValue1[1] = nConstant;
     119         240 :         pValue1[2] = nConstant;
     120         240 :     }
     121             : 
     122        6700 :     static inline void add(long*& pValue1, sal_uInt8*& pValue2)
     123             :     {
     124        6700 :         pValue1[0] += pValue2[0];
     125        6700 :         pValue1[1] += pValue2[1];
     126        6700 :         pValue1[2] += pValue2[2];
     127        6700 :     }
     128             : 
     129        3150 :     static inline void add(long*& pValue1, long*& pValue2)
     130             :     {
     131        3150 :         pValue1[0] += pValue2[0];
     132        3150 :         pValue1[1] += pValue2[1];
     133        3150 :         pValue1[2] += pValue2[2];
     134        3150 :     }
     135             : 
     136        6300 :     static inline void sub(long*& pValue1, sal_uInt8*& pValue2)
     137             :     {
     138        6300 :         pValue1[0] -= pValue2[0];
     139        6300 :         pValue1[1] -= pValue2[1];
     140        6300 :         pValue1[2] -= pValue2[2];
     141        6300 :     }
     142             : 
     143        3150 :     static inline void sub(long*& pValue1, long*& pValue2)
     144             :     {
     145        3150 :         pValue1[0] -= pValue2[0];
     146        3150 :         pValue1[1] -= pValue2[1];
     147        3150 :         pValue1[2] -= pValue2[2];
     148        3150 :     }
     149             : 
     150        3550 :     static inline void assignPtr(sal_uInt8*& pValue1, sal_uInt8*& pValue2)
     151             :     {
     152        3550 :         pValue1[0] = pValue2[0];
     153        3550 :         pValue1[1] = pValue2[1];
     154        3550 :         pValue1[2] = pValue2[2];
     155        3550 :     }
     156             : 
     157        3150 :     static inline void assignMulAndShr(sal_uInt8*& result, long*& sum, long multiply, long shift)
     158             :     {
     159        3150 :         result[0] = (multiply * sum[0]) >> shift;
     160        3150 :         result[1] = (multiply * sum[1]) >> shift;
     161        3150 :         result[2] = (multiply * sum[2]) >> shift;
     162        3150 :     }
     163             : };
     164             : 
     165             : struct SumFunction8
     166             : {
     167           0 :     static inline void add(long*& pValue1, long nConstant)
     168             :     {
     169           0 :         pValue1[0] += nConstant;
     170           0 :     }
     171             : 
     172           0 :     static inline void set(long*& pValue1, long nConstant)
     173             :     {
     174           0 :         pValue1[0] = nConstant;
     175           0 :     }
     176             : 
     177           0 :     static inline void add(long*& pValue1, sal_uInt8*& pValue2)
     178             :     {
     179           0 :         pValue1[0] += pValue2[0];
     180           0 :     }
     181             : 
     182           0 :     static inline void add(long*& pValue1, long*& pValue2)
     183             :     {
     184           0 :         pValue1[0] += pValue2[0];
     185           0 :     }
     186             : 
     187           0 :     static inline void sub(long*& pValue1, sal_uInt8*& pValue2)
     188             :     {
     189           0 :         pValue1[0] -= pValue2[0];
     190           0 :     }
     191             : 
     192           0 :     static inline void sub(long*& pValue1, long*& pValue2)
     193             :     {
     194           0 :         pValue1[0] -= pValue2[0];
     195           0 :     }
     196             : 
     197           0 :     static inline void assignPtr(sal_uInt8*& pValue1, sal_uInt8*& pValue2)
     198             :     {
     199           0 :         pValue1[0] = pValue2[0];
     200           0 :     }
     201             : 
     202           0 :     static inline void assignMulAndShr(sal_uInt8*& result, long*& sum, long multiply, long shift)
     203             :     {
     204           0 :         result[0] = (multiply * sum[0]) >> shift;
     205           0 :     }
     206             : };
     207             : 
     208             : template<typename SumFunction>
     209           1 : void stackBlurHorizontal(
     210             :         BitmapReadAccess* pReadAccess,
     211             :         BitmapWriteAccess* pWriteAccess,
     212             :         BlurSharedData& rShared)
     213             : {
     214           1 :     long nWidth = pReadAccess->Width();
     215           1 :     long nHeight = pReadAccess->Height();
     216             : 
     217           1 :     sal_uInt8* pStack = rShared.maStackBuffer.data();
     218             :     sal_uInt8* pStackPtr;
     219             : 
     220           1 :     long nLastIndexX = nWidth - 1;
     221             : 
     222           1 :     long nMultiplyValue = rShared.getMultiplyValue();
     223           1 :     long nShiftValue = rShared.getShiftValue();
     224             : 
     225           1 :     long nRadius = rShared.mnRadius;
     226           1 :     long nComponentWidth = rShared.mnComponentWidth;
     227           1 :     long nDiv = rShared.mnDiv;
     228             : 
     229             :     Scanline pSourcePointer;
     230             :     Scanline pDestinationPointer;
     231             : 
     232             :     long nXPosition;
     233             :     long nStackIndex;
     234             :     long nStackIndexStart;
     235             :     long nWeight;
     236             : 
     237           1 :     long* nSum = rShared.mnSumVector.data();
     238           1 :     long* nInSum = rShared.mnInSumVector.data();
     239           1 :     long* nOutSum = rShared.mnOutSumVector.data();
     240             : 
     241           1 :     rShared.calculateWeightAndPositions(nLastIndexX);
     242           1 :     long* pPositionPointer = rShared.maPositionTable.data();
     243           1 :     long* pWeightPointer = rShared.maWeightTable.data();
     244             : 
     245          36 :     for (long y = 0; y < nHeight; y++)
     246             :     {
     247          35 :         SumFunction::set(nSum, 0L);
     248          35 :         SumFunction::set(nInSum, 0L);
     249          35 :         SumFunction::set(nOutSum, 0L);
     250             : 
     251         210 :         for (long i = 0; i < nDiv; i++)
     252             :         {
     253         175 :             pSourcePointer = pReadAccess->GetScanline(pPositionPointer[i]);
     254             : 
     255         175 :             pStackPtr = &pStack[nComponentWidth * i];
     256             : 
     257         175 :             SumFunction::assignPtr(pStackPtr, pSourcePointer);
     258             : 
     259         175 :             nWeight = pWeightPointer[i];
     260             : 
     261         175 :             SumFunction::add(nSum, pSourcePointer[0] * nWeight);
     262             : 
     263         175 :             if (i - nRadius > 0)
     264             :             {
     265          70 :                 SumFunction::add(nInSum, pSourcePointer);
     266             :             }
     267             :             else
     268             :             {
     269         105 :                 SumFunction::add(nOutSum, pSourcePointer);
     270             :             }
     271             :         }
     272             : 
     273          35 :         nStackIndex = nRadius;
     274          35 :         nXPosition = std::min(nRadius, nLastIndexX);
     275             : 
     276          35 :         pSourcePointer = pReadAccess->GetScanline(y) + nComponentWidth * nXPosition;
     277             : 
     278        1610 :         for (long x = 0; x < nWidth; x++)
     279             :         {
     280        1575 :             pDestinationPointer = pWriteAccess->GetScanline(y) + nComponentWidth * x;
     281             : 
     282        1575 :             SumFunction::assignMulAndShr(pDestinationPointer, nSum, nMultiplyValue, nShiftValue);
     283             : 
     284        1575 :             SumFunction::sub(nSum, nOutSum);
     285             : 
     286        1575 :             nStackIndexStart = nStackIndex + nDiv - nRadius;
     287        1575 :             if (nStackIndexStart >= nDiv)
     288             :             {
     289         945 :                 nStackIndexStart -= nDiv;
     290             :             }
     291        1575 :             pStackPtr = &pStack[nComponentWidth * nStackIndexStart];
     292             : 
     293        1575 :             SumFunction::sub(nOutSum, pStackPtr);
     294             : 
     295        1575 :             if (nXPosition < nLastIndexX)
     296             :             {
     297        1470 :                 nXPosition++;
     298        1470 :                 pSourcePointer = pReadAccess->GetScanline(y) + nComponentWidth * nXPosition;
     299             :             }
     300             : 
     301        1575 :             SumFunction::assignPtr(pStackPtr, pSourcePointer);
     302             : 
     303        1575 :             SumFunction::add(nInSum, pSourcePointer);
     304             : 
     305        1575 :             SumFunction::add(nSum, nInSum);
     306             : 
     307        1575 :             nStackIndex++;
     308        1575 :             if (nStackIndex >= nDiv)
     309             :             {
     310         315 :                 nStackIndex = 0;
     311             :             }
     312             : 
     313        1575 :             pStackPtr = &pStack[nStackIndex * nComponentWidth];
     314             : 
     315        1575 :             SumFunction::add(nOutSum, pStackPtr);
     316        1575 :             SumFunction::sub(nInSum, pStackPtr);
     317             :         }
     318             :     }
     319           1 : }
     320             : 
     321             : template<typename SumFunction>
     322           1 : void stackBlurVertical(
     323             :         BitmapReadAccess* pReadAccess,
     324             :         BitmapWriteAccess* pWriteAccess,
     325             :         BlurSharedData& rShared)
     326             : {
     327           1 :     long nWidth = pReadAccess->Width();
     328           1 :     long nHeight = pReadAccess->Height();
     329             : 
     330           1 :     sal_uInt8* pStack = rShared.maStackBuffer.data();
     331             :     sal_uInt8* pStackPtr;
     332             : 
     333           1 :     long nLastIndexY = nHeight - 1;
     334             : 
     335           1 :     long nMultiplyValue = rShared.getMultiplyValue();
     336           1 :     long nShiftValue = rShared.getShiftValue();
     337             : 
     338           1 :     long nRadius = rShared.mnRadius;
     339           1 :     long nComponentWidth = rShared.mnComponentWidth;
     340           1 :     long nDiv = rShared.mnDiv;
     341             : 
     342             :     Scanline pSourcePointer;
     343             :     Scanline pDestinationPointer;
     344             : 
     345             :     long nYPosition;
     346             :     long nStackIndex;
     347             :     long nStackIndexStart;
     348             :     long nWeight;
     349             : 
     350           1 :     long* nSum = rShared.mnSumVector.data();
     351           1 :     long* nInSum = rShared.mnInSumVector.data();
     352           1 :     long* nOutSum = rShared.mnOutSumVector.data();
     353             : 
     354           1 :     rShared.calculateWeightAndPositions(nLastIndexY);
     355           1 :     long* pPositionPointer = rShared.maPositionTable.data();
     356           1 :     long* pWeightPointer = rShared.maWeightTable.data();
     357             : 
     358          46 :     for (long x = 0; x < nWidth; x++)
     359             :     {
     360          45 :         SumFunction::set(nSum, 0L);
     361          45 :         SumFunction::set(nInSum, 0L);
     362          45 :         SumFunction::set(nOutSum, 0L);
     363             : 
     364         270 :         for (long i = 0; i < nDiv; i++)
     365             :         {
     366         225 :             pSourcePointer = pReadAccess->GetScanline(pPositionPointer[i]);
     367             : 
     368         225 :             pStackPtr = &pStack[nComponentWidth * i];
     369             : 
     370         225 :             SumFunction::assignPtr(pStackPtr, pSourcePointer);
     371             : 
     372         225 :             nWeight = pWeightPointer[i];
     373             : 
     374         225 :             SumFunction::add(nSum, pSourcePointer[0] * nWeight);
     375             : 
     376         225 :             if (i - nRadius > 0)
     377             :             {
     378          90 :                 SumFunction::add(nInSum, pSourcePointer);
     379             :             }
     380             :             else
     381             :             {
     382         135 :                 SumFunction::add(nOutSum, pSourcePointer);
     383             :             }
     384             :         }
     385             : 
     386          45 :         nStackIndex = nRadius;
     387          45 :         nYPosition = std::min(nRadius, nLastIndexY);
     388             : 
     389          45 :         pSourcePointer = pReadAccess->GetScanline(nYPosition) + nComponentWidth * x;
     390             : 
     391        1620 :         for (long y = 0; y < nHeight; y++)
     392             :         {
     393        1575 :             pDestinationPointer = pWriteAccess->GetScanline(y) + nComponentWidth * x;
     394             : 
     395        1575 :             SumFunction::assignMulAndShr(pDestinationPointer, nSum, nMultiplyValue, nShiftValue);
     396             : 
     397        1575 :             SumFunction::sub(nSum, nOutSum);
     398             : 
     399             : 
     400        1575 :             nStackIndexStart = nStackIndex + nDiv - nRadius;
     401        1575 :             if (nStackIndexStart >= nDiv)
     402             :             {
     403         945 :                 nStackIndexStart -= nDiv;
     404             :             }
     405        1575 :             pStackPtr = &pStack[nComponentWidth * nStackIndexStart];
     406             : 
     407        1575 :             SumFunction::sub(nOutSum, pStackPtr);
     408             : 
     409        1575 :             if (nYPosition < nLastIndexY)
     410             :             {
     411        1440 :                 nYPosition++;
     412        1440 :                 pSourcePointer = pReadAccess->GetScanline(nYPosition) + nComponentWidth * x;
     413             :             }
     414             : 
     415        1575 :             SumFunction::assignPtr(pStackPtr, pSourcePointer);
     416             : 
     417        1575 :             SumFunction::add(nInSum, pSourcePointer);
     418             : 
     419        1575 :             SumFunction::add(nSum, nInSum);
     420             : 
     421        1575 :             nStackIndex++;
     422        1575 :             if (nStackIndex >= nDiv)
     423             :             {
     424         315 :                 nStackIndex = 0;
     425             :             }
     426             : 
     427        1575 :             pStackPtr = &pStack[nStackIndex * nComponentWidth];
     428             : 
     429        1575 :             SumFunction::add(nOutSum, pStackPtr);
     430             : 
     431        1575 :             SumFunction::sub(nInSum, pStackPtr);
     432             :         }
     433             :     }
     434           1 : }
     435             : 
     436           1 : void stackBlur24(Bitmap& rBitmap, sal_Int32 nRadius, sal_Int32 nComponentWidth)
     437             : {
     438             :     // Limit radius
     439           1 :     nRadius = std::min<sal_Int32>(254, std::max<sal_Int32>(2, nRadius));
     440           1 :     const long nColorChannels = 3; // 3 color channel
     441           1 :     BlurSharedData aData(nRadius, nComponentWidth, nColorChannels);
     442             : 
     443             :     {
     444           1 :         Bitmap::ScopedReadAccess pReadAccess(rBitmap);
     445           2 :         Bitmap::ScopedWriteAccess pWriteAccess(rBitmap);
     446             : 
     447           2 :         stackBlurHorizontal<SumFunction24>(pReadAccess.get(), pWriteAccess.get(), aData);
     448             :     }
     449             : 
     450             :     {
     451           1 :         Bitmap::ScopedReadAccess pReadAccess(rBitmap);
     452           2 :         Bitmap::ScopedWriteAccess pWriteAccess(rBitmap);
     453             : 
     454           2 :         stackBlurVertical<SumFunction24>(pReadAccess.get(), pWriteAccess.get(), aData);
     455           1 :     }
     456           1 : }
     457             : 
     458           0 : void stackBlur8(Bitmap& rBitmap, sal_Int32 nRadius, sal_Int32 nComponentWidth)
     459             : {
     460             :     // Limit radius
     461           0 :     nRadius = std::min<sal_Int32>(254, std::max<sal_Int32>(2, nRadius));
     462           0 :     const long nColorChannels = 1; // 1 color channel
     463           0 :     BlurSharedData aData(nRadius, nComponentWidth, nColorChannels);
     464             : 
     465             :     {
     466           0 :         Bitmap::ScopedReadAccess pReadAccess(rBitmap);
     467           0 :         Bitmap::ScopedWriteAccess pWriteAccess(rBitmap);
     468             : 
     469           0 :         stackBlurHorizontal<SumFunction8>(pReadAccess.get(), pWriteAccess.get(), aData);
     470             :     }
     471             : 
     472             :     {
     473           0 :         Bitmap::ScopedReadAccess pReadAccess(rBitmap);
     474           0 :         Bitmap::ScopedWriteAccess pWriteAccess(rBitmap);
     475             : 
     476           0 :         stackBlurVertical<SumFunction8>(pReadAccess.get(), pWriteAccess.get(), aData);
     477           0 :     }
     478           0 : }
     479             : 
     480           1 : void centerExtendBitmap(Bitmap& rBitmap, sal_Int32 nExtendSize, Color aColor)
     481             : {
     482           1 :     const Size& rSize = rBitmap.GetSizePixel();
     483           1 :     const Size aNewSize(rSize.Width()  + nExtendSize * 2,
     484           2 :                         rSize.Height() + nExtendSize * 2);
     485             : 
     486           1 :     Bitmap aNewBitmap(aNewSize, rBitmap.GetBitCount());
     487             : 
     488             :     {
     489           1 :         Bitmap::ScopedReadAccess pReadAccess(rBitmap);
     490           2 :         Bitmap::ScopedWriteAccess pWriteAccess(aNewBitmap);
     491             : 
     492           1 :         long nWidthBorder  = nExtendSize + rSize.Width();
     493           1 :         long nHeightBorder = nExtendSize + rSize.Height();
     494             : 
     495          36 :         for (long y = 0; y < aNewSize.Height(); y++)
     496             :         {
     497        1610 :             for (long x = 0; x < aNewSize.Width(); x++)
     498             :             {
     499        1575 :                 if (y < nExtendSize || y >= nHeightBorder
     500        1395 :                  || x < nExtendSize || x >= nWidthBorder)
     501             :                 {
     502         304 :                     pWriteAccess->SetPixel(y, x, aColor);
     503             :                 }
     504             :                 else
     505             :                 {
     506        1271 :                     pWriteAccess->SetPixel(y, x, pReadAccess->GetPixel(y - nExtendSize, x - nExtendSize));
     507             :                 }
     508             :             }
     509           1 :         }
     510             :     }
     511           1 :     rBitmap = aNewBitmap;
     512           1 : }
     513             : 
     514             : } // end anonymous namespace
     515             : 
     516             : /**
     517             :  * Implementation of stack blur - a fast Gaussian blur approximation.
     518             :  * nRadius - blur radious, valid values are between 2 and 254
     519             :  * bExtend - extend the bitmap in all directions by the radius
     520             :  *
     521             :  * Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
     522             :  * (http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html)
     523             :  *
     524             :  * Additionally eferences and implementations:
     525             :  * - Blur.js by Jacob Kelley
     526             :  *   (http://www.blurjs.com)
     527             :  * - BlurEffectForAndroidDesign by Nicolas Pomepuy
     528             :  *   (https://github.com/PomepuyN/BlurEffectForAndroidDesign)
     529             :  * - StackBluriOS by Thomas Landspurg
     530             :  *   (https://github.com/tomsoft1/StackBluriOS)
     531             :  * - stackblur.cpp by Benjamin Yates
     532             :  *   (https://gist.github.com/benjamin9999/3809142)
     533             :  * - stack blur in fog 2D graphic library by Petr Kobalicek
     534             :  *   (https://code.google.com/p/fog/)
     535             :  *
     536             :  */
     537           1 : BitmapFilterStackBlur::BitmapFilterStackBlur(sal_Int32 nRadius, bool bExtend)
     538             :     : mnRadius(nRadius)
     539           1 :     , mbExtend(bExtend)
     540           1 : {}
     541             : 
     542           1 : BitmapFilterStackBlur::~BitmapFilterStackBlur()
     543           1 : {}
     544             : 
     545           1 : bool BitmapFilterStackBlur::filter(Bitmap& rBitmap)
     546             : {
     547             :     sal_uLong nScanlineFormat;
     548             :     {
     549           1 :         Bitmap::ScopedReadAccess pReadAccess(rBitmap);
     550           1 :         nScanlineFormat = pReadAccess->GetScanlineFormat();
     551             :     }
     552             : 
     553           1 :     if (nScanlineFormat == BMP_FORMAT_24BIT_TC_RGB ||
     554           1 :         nScanlineFormat == BMP_FORMAT_24BIT_TC_BGR ||
     555             :         nScanlineFormat == BMP_FORMAT_32BIT_TC_MASK)
     556             :     {
     557           1 :         int nComponentWidth = (nScanlineFormat == BMP_FORMAT_32BIT_TC_MASK) ? 4 : 3;
     558             : 
     559           1 :         if (mbExtend)
     560             :         {
     561           1 :             centerExtendBitmap(rBitmap, mnRadius, COL_WHITE);
     562             :         }
     563             : 
     564           1 :         stackBlur24(rBitmap, mnRadius, nComponentWidth);
     565             :     }
     566           0 :     else if (nScanlineFormat == BMP_FORMAT_8BIT_PAL)
     567             :     {
     568           0 :         int nComponentWidth = 1;
     569             : 
     570           0 :         if (mbExtend)
     571             :         {
     572           0 :             centerExtendBitmap(rBitmap, mnRadius, COL_WHITE);
     573             :         }
     574             : 
     575           0 :         stackBlur8(rBitmap, mnRadius, nComponentWidth);
     576             :     }
     577             : 
     578           1 :     return true;
     579             : }
     580             : 
     581           0 : bool BitmapFilterStackBlur::filter(BitmapEx& rBitmapEx)
     582             : {
     583           0 :     Bitmap aBitmap = rBitmapEx.GetBitmap();
     584           0 :     filter(aBitmap);
     585           0 :     rBitmapEx = BitmapEx(aBitmap);
     586             : 
     587           0 :     return true;
     588             : }
     589             : 
     590             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11