1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef GRAPHIC_LITE_FILTER_BLUR_H
16 #define GRAPHIC_LITE_FILTER_BLUR_H
17 
18 #include "gfx_utils/diagram/common/common_basics.h"
19 #include "gfx_utils/graphic_math.h"
20 #include "graphic_config.h"
21 #include "securec.h"
22 
23 namespace OHOS {
24 class Filterblur {
25 #if defined(GRAPHIC_ENABLE_BLUR_EFFECT_FLAG) && GRAPHIC_ENABLE_BLUR_EFFECT_FLAG
26 
27 public:
Filterblur()28     Filterblur()
29     {
30         integral_ = nullptr;
31         imageWidth_ = 0;
32         imageHeight_ = 0;
33     }
~Filterblur()34     ~Filterblur()
35     {
36         if (integral_ != nullptr) {
37             free(integral_);
38         }
39     }
40 
41     template <class Img>
BoxBlur(Img & img,uint16_t radius,int32_t channel,int32_t stride)42     void BoxBlur(Img& img, uint16_t radius, int32_t channel, int32_t stride)
43     {
44         if (radius < 1) {
45             return;
46         }
47         int32_t width = img.GetWidth();
48         int32_t height = img.GetHeight();
49         bool isGetRGBAIntegral = false;
50         if (integral_ == nullptr || ((imageWidth_ * imageHeight_) != (width * height))) {
51             if (integral_ != nullptr) {
52                 free(integral_);
53             }
54             integral_ = (int32_t*)malloc((width + 1) * (height + 1) * channel * sizeof(int32_t));
55             isGetRGBAIntegral = true;
56         }
57         if (channel == FOUR_TIMES) {
58             if (isGetRGBAIntegral) {
59                 GetRGBAIntegralImage((uint8_t*)img.PixValuePtr(0, 0), width, height, stride);
60             }
61 #ifndef __ICCARM__
62 #pragma omp parallel for
63 #endif
64             for (int32_t y = 0; y < height; y++) {
65                 int32_t y1 = MATH_MAX(y - radius, 0);
66                 int32_t y2 = MATH_MIN(y + radius + 1, height);
67                 uint8_t* lineImageHeader = (uint8_t*)img.PixValuePtr(0, 0) + y * stride;
68                 uint8_t* linePD = lineImageHeader;
69                 int32_t* lineP1 = integral_ + y1 * ((width + 1) << 2);
70                 int32_t* lineP2 = integral_ + y2 * ((width + 1) << 2);
71 
72                 for (int32_t x = 0; x < width; x++) {
73                     int32_t x1 = MATH_MAX(x - radius, 0);
74                     int32_t x2 = MATH_MIN(x + radius + 1, width);
75                     int32_t index1 = x1 << 2;
76                     int32_t index2 = x2 << 2;
77                     int32_t sumB = lineP2[index2 + 0] - lineP1[index2 + 0] -
78                                lineP2[index1 + 0] + lineP1[index1 + 0];
79                     int32_t sumG = lineP2[index2 + 1] - lineP1[index2 + 1] -
80                                lineP2[index1 + 1] + lineP1[index1 + 1];
81                     int32_t sumR = lineP2[index2 + 2] - lineP1[index2 + 2] -
82                                lineP2[index1 + 2] + lineP1[index1 + 2];
83 
84                     const int32_t pixelCount = (x2 - x1) * (y2 - y1);
85                     linePD[0] = (sumB + (pixelCount >> 1)) / pixelCount;
86                     linePD[1] = (sumG + (pixelCount >> 1)) / pixelCount;
87                     linePD[2] = (sumR + (pixelCount >> 1)) / pixelCount;
88                     uint8_t* alpha = lineImageHeader + (x << 2);
89                     linePD[3] = alpha[3];
90                     linePD += 4;
91                 }
92             }
93         }
94     }
95 private:
GetRGBAIntegralImage(uint8_t * src,uint16_t width,uint16_t height,uint16_t stride)96     void GetRGBAIntegralImage(uint8_t* src, uint16_t width, uint16_t height, uint16_t stride)
97     {
98         int32_t channel = FOUR_TIMES;
99         if (integral_ != nullptr && ((imageWidth_ * imageHeight_) != (width * height))) {
100             int32_t integralSize = (width + 1) * channel * sizeof(int32_t);
101             memset_s(integral_, integralSize, 0, integralSize);
102         }
103         for (int y = 0; y < height; y++) {
104             uint8_t* linePS = src + y * stride;
105             //	last position
106             int32_t* linePL = integral_ + y * (width + 1) * channel + channel;
107             //	curretn position£¬waring the first column of every line row is zero
108             int32_t* linePD = integral_ + (y + 1) * (width + 1) * channel + channel;
109             //	the first column is 0
110             linePD[-4] = 0;
111             linePD[-3] = 0;
112             linePD[-2] = 0;
113             linePD[-1] = 0;
114             for (int x = 0, sumB = 0, sumG = 0, sumR = 0, sumA = 0; x < width; x++) {
115                 sumB += linePS[0];
116                 sumG += linePS[1];
117                 sumR += linePS[2];
118                 sumA += linePS[3];
119                 linePD[0] = linePL[0] + sumB;
120                 linePD[1] = linePL[1] + sumG;
121                 linePD[2] = linePL[2] + sumR;
122                 linePD[3] = linePL[3] + sumA;
123                 linePS += channel;
124                 linePL += channel;
125                 linePD += channel;
126             }
127         }
128     }
129 
130     int32_t* integral_;
131     int32_t imageWidth_;
132     int32_t imageHeight_;
133 #endif
134 };
135 } // namespace OHOS
136 #endif
137