• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 
16 #include "post_proc_slr.h"
17 
18 #include <cstdint>
19 #include <memory>
20 #include <unistd.h>
21 #include <vector>
22 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
23 #include "ffrt.h"
24 #endif
25 #include "image_log.h"
26 #include "image_trace.h"
27 #include "image_utils.h"
28 #include "memory_manager.h"
29 
30 namespace OHOS {
31 namespace Media {
32 using namespace std;
33 
34 constexpr float PI = 3.14159265;
35 constexpr float EPSILON = 1e-6;
36 constexpr int FFRT_THREAD_LIMIT = 8;
37 
GetSLRFactor(float x,int a)38 float GetSLRFactor(float x, int a)
39 {
40     if (a <= 0) {
41         return 1.0f;
42     }
43     if (std::fabs(x) < EPSILON) {
44         return 1.0f;
45     }
46     if (x > a || x < -a) {
47         return 0.0f;
48     }
49 
50     x *= PI;
51     return a * std::sin(x) * std::sin(x / a) / (x * x);
52 }
53 
GetWeights(float coeff,int n)54 SLRWeightMat SLRProc::GetWeights(float coeff, int n)
55 {
56     if (std::fabs(coeff) < EPSILON || coeff < .0f || n <= 0) {
57         return nullptr;
58     }
59     float tao = 1.0f / coeff;
60     int a = std::max(2, static_cast<int>(std::floor(tao))); // 2 max SLR box size
61     SLRWeightMat weights = std::make_shared<SLRWeightVec>(n, std::vector<float>(2 * a, 0));
62     float beta = 1.0f;
63     if (coeff > 0.8999f && coeff < 1.0f) { // 0.8999f adjust low pass filter
64         beta = 1.2f; // 1.2f adjust low pass filter
65     } else if (coeff < 0.9f && coeff > 0.8f) { // 0.9f adjust low pass filter
66         beta = 1.1f; // 1.1f adjust low pass filter
67     }
68     float scale = coeff > 1.0f ? 1.0f : coeff;
69 
70     for (int i = 0; i < n; i++) {
71         float etaf = (i + 0.5) / coeff - 0.5;
72         int eta = std::floor(etaf);
73         for (int k = eta - a + 1; k < eta + a + 1; k++) {
74             float factor = GetSLRFactor(scale / beta * (etaf - k), a);
75             (*weights)[i][k - eta + a - 1] = factor;
76         }
77     }
78     std::vector<float> rowSum(n, 0);
79     for (int i = 0; i < n; i++) {
80         for (int j = 0; j < 2 * a; j++) { // 2 max SLR box size
81             rowSum[i] += (*weights)[i][j];
82         }
83         if (std::fabs(rowSum[i]) < EPSILON) {
84             rowSum[i] = 1.0f; // 1.0f default weight
85         }
86         for (int j = 0; j < 2 * a; j++) { // 2 max SLR box size
87             (*weights)[i][j] /= rowSum[i];
88         }
89     }
90     return weights;
91 }
92 
SLRCheck(const SLRMat & src,const SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)93 bool SLRCheck(const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
94 {
95     if (x == nullptr || y == nullptr) {
96         return false;
97     }
98     if (src.size_.width == 0 || src.size_.height == 0) {
99         return false;
100     }
101     if (dst.size_.width == 0 || dst.size_.height == 0) {
102         return false;
103     }
104     return true;
105 }
106 
SLRCast(float v)107 inline uint32_t SLRCast(float v)
108 {
109     v = std::clamp(v, 0.0f, 255.0f); // 255.0f rgba max value
110     uint32_t uv = static_cast<uint32_t>(v);
111     return uv;
112 }
113 
114 struct SLRSliceKey {
SLRSliceKeyOHOS::Media::SLRSliceKey115     SLRSliceKey(int v1, int v2) : x(v1), y(v2) {}
116     int x;
117     int y;
118 };
119 
SLRBoxCheck(const SLRSliceKey & key,const SLRMat & src,const SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)120 bool SLRBoxCheck(const SLRSliceKey &key, const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x,
121     const SLRWeightMat &y)
122 {
123     if (key.x < 0 || key.y < 0) {
124         IMAGE_LOGE("SLRBoxCheck Key error:%{public}d, %{public}d", key.x, key.y);
125         return false;
126     }
127     uint32_t* srcArr = static_cast<uint32_t*>(src.data_);
128     if (srcArr == nullptr) {
129         IMAGE_LOGE("SLRBoxCheck srcArr null");
130         return false;
131     }
132     uint32_t* dstArr = static_cast<uint32_t*>(dst.data_);
133     if (dstArr == nullptr) {
134         IMAGE_LOGE("SLRBoxCheck dstArr null");
135         return false;
136     }
137     int srcM = src.size_.height;
138     int srcN = src.size_.width;
139     int dstM = dst.size_.height;
140     int dstN = dst.size_.width;
141     float coeffX = static_cast<float>(dstM) / srcM;
142     float coeffY = static_cast<float>(dstN) / srcN;
143     float taoX = 1 / coeffX;
144     float taoY = 1 / coeffY;
145     int aX = std::max(2, static_cast<int>(std::floor(taoX)));
146     int aY = std::max(2, static_cast<int>(std::floor(taoY))); // 2 default size
147     if (static_cast<int>((*x).size()) < key.y || static_cast<int>((*x)[0].size()) < 2 * aY) { // 2 max slr box size
148         IMAGE_LOGE("SLRBoxCheck h_y error:%{public}zu, %{public}d", (*x).size(), aY);
149         return false;
150     }
151     if (static_cast<int>((*y).size()) < key.x || static_cast<int>((*y)[0].size()) < 2 * aX) { // 2 max slr box size
152         IMAGE_LOGE("SLRBoxCheck h_x error:%{public}zu, %{public}d", (*y).size(), aX);
153         return false;
154     }
155     int dstIndex = key.x * dst.rowStride_ + key.y;
156     int maxDstSize = dstM * dstN;
157     if (dstIndex >= maxDstSize) {
158         IMAGE_LOGE("SLRBoxCheck dst index error:%{public}d, %{public}d", dstIndex, maxDstSize);
159         return false;
160     }
161     return true;
162 }
163 
SLRBox(const SLRSliceKey & key,const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)164 void SLRBox(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
165 {
166     if (!SLRBoxCheck(key, src, dst, x, y)) {
167         return;
168     }
169     uint32_t* srcArr = static_cast<uint32_t*>(src.data_);
170     uint32_t* dstArr = static_cast<uint32_t*>(dst.data_);
171     int srcM = src.size_.height;
172     int srcN = src.size_.width;
173     int dstM = dst.size_.height;
174     int dstN = dst.size_.width;
175     float coeffX = static_cast<float>(dstM) / srcM;
176     float coeffY = static_cast<float>(dstN) / srcN;
177     float taoX = 1 / coeffX;
178     float taoY = 1 / coeffY;
179     int aX = std::max(2, static_cast<int>(std::floor(taoX)));
180     int aY = std::max(2, static_cast<int>(std::floor(taoY))); // 2 default size
181     int etaI = static_cast<int>((key.x + 0.5) * taoX - 0.5); // 0.5 middle index
182     int etaJ = static_cast<int>((key.y + 0.5) * taoY - 0.5); // 0.5 middle index
183     int rStart = etaI - aX + 1;
184     int rEnd = etaI + aX;
185     int cStart = etaJ - aY + 1;
186     int cEnd = etaJ + aY;
187     float rgba[4]{ .0f, .0f, .0f, .0f };
188     int maxSrcSize = srcM * srcN;
189     for (int r = rStart; r <= rEnd; ++r) {
190         int nR = min(max(0, r), srcM - 1);
191         for (int c = cStart; c <= cEnd; ++c) {
192             int nC = min(max(0, c), srcN - 1);
193             auto w = (*x)[key.y][c - cStart];
194             w *= (*y)[key.x][r - rStart];
195             int srcIndex = nR *  src.rowStride_ + nC;
196             if (srcIndex < 0 || srcIndex >= maxSrcSize) {
197                 IMAGE_LOGE("SLRBox src index error:%{public}d, %{public}d", srcIndex, maxSrcSize);
198                 return;
199             }
200             uint32_t color = *(srcArr + srcIndex);
201             rgba[0] += ((color >> 24) & 0xFF) * w; // 24 rgba r
202             rgba[1] += ((color >> 16) & 0xFF) * w; // 16 rgba g
203             rgba[2] += ((color >> 8) & 0xFF) * w;  // 2 8 rgba b
204             rgba[3] += (color & 0xFF) * w;         // 3 rgba a
205         }
206     }
207     uint32_t r = SLRCast(rgba[0]);
208     uint32_t g = SLRCast(rgba[1]);
209     uint32_t b = SLRCast(rgba[2]); // 2 rgba
210     uint32_t a = SLRCast(rgba[3]); // 3 rgba
211     dstArr[key.x * dst.rowStride_ + key.y] = (r << 24) | (g << 16) | (b << 8) | a; // 24 16 8 rgba
212 }
213 
Laplacian(SLRMat & srcMat,void * data,float alpha)214 void SLRProc::Laplacian(SLRMat &srcMat, void* data, float alpha)
215 {
216     IMAGE_LOGD("Laplacian pixelMap SLR:width=%{public}d,height=%{public}d,alpha=%{public}f", srcMat.size_.width,
217         srcMat.size_.height, alpha);
218     if (data == nullptr) {
219         IMAGE_LOGE("SLRProc::Laplacian create memory failed");
220         return;
221     }
222     const int m = srcMat.size_.height;
223     const int n = srcMat.size_.width;
224     const int stride = srcMat.rowStride_;
225     uint32_t* srcArr = static_cast<uint32_t*>(srcMat.data_);
226     uint32_t* dstArr = static_cast<uint32_t*>(data);
227 
228     auto getPixel = [&](int i, int j) ->uint32_t {
229         i = std::clamp(i, 0, m - 1);
230         j = std::clamp(j, 0, n - 1);
231         return *(srcArr + i * stride + j);
232     };
233 
234     auto extract = [](uint32_t color, int shift) -> uint32_t {
235         return (color >> shift) & 0xFF;
236     };
237     for (int i = 0; i < m; i++) {
238         for (int j = 0; j < n; j++) {
239             const uint32_t pixels[5] = {
240                 getPixel(i, j),       // center
241                 getPixel(i, j - 1),     // left
242                 getPixel(i, j + 1),     // right
243                 getPixel(i - 1, j),     // up
244                 getPixel(i + 1, j)      // down
245             };
246             const uint32_t cr = extract(pixels[0], 24); // 24 r
247             const uint32_t cg = extract(pixels[0], 16); // 16 g
248             const uint32_t cb = extract(pixels[0], 8); // 8 b
249             const uint32_t ca = pixels[0] & 0xFF;
250 
251             auto delta = [&](uint32_t c, int shift) -> uint32_t {
252                 return 4 * c
253                      - extract(pixels[1], shift) // l left
254                      - extract(pixels[2], shift) // 2 right
255                      - extract(pixels[3], shift) // 3 up
256                      - extract(pixels[4], shift); // 4 down
257             };
258             dstArr[i * stride + j] =
259                 (SLRCast(cr + alpha * delta(cr, 24)) << 24) | // 24 r
260                 (SLRCast(cg + alpha * delta(cg, 16)) << 16) | // 16 g
261                 (SLRCast(cb + alpha * delta(cb, 8))  << 8)  | // 8 b
262                 ca;
263         }
264     }
265 }
266 
Serial(const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)267 void SLRProc::Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
268 {
269     if (!SLRCheck(src, dst, x, y)) {
270         IMAGE_LOGE("SLRProc::Serial param error");
271         return;
272     }
273 
274     int m = dst.size_.height;
275     int n = dst.size_.width;
276     for (int i = 0; i < m; i++) {
277         for (int j = 0; j < n; j++) {
278             SLRSliceKey key(i, j);
279             SLRBox(key, src, dst, x, y);
280         }
281     }
282 }
283 
SLRSubtask(const SLRSliceKey & key,const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)284 inline void SLRSubtask(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst,
285     const SLRWeightMat &x, const SLRWeightMat &y)
286 {
287     int start = key.x;
288     int end = key.y;
289     int n = dst.size_.width;
290     for (int i = start; i < end; i++) {
291         for (int j = 0; j < n; j++) {
292             SLRSliceKey boxKey(i, j);
293             SLRBox(boxKey, src, dst, x, y);
294         }
295     }
296 }
297 
Parallel(const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)298 void SLRProc::Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
299 {
300 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
301     if (!SLRCheck(src, dst, x, y)) {
302         IMAGE_LOGE("SLRProc::Parallel param error");
303         return;
304     }
305     const int maxThread = 16; // 16 max thread size
306     int m = dst.size_.height;
307     int n = dst.size_.width;
308     int step = m / maxThread;
309     int stepMod = (m % maxThread == 0) ? 1 : 0;
310     std::vector<ffrt::dependence> ffrtHandles;
311     std::vector<ffrt::dependence> ffrtHandles1;
312     for (int k = 0; k < maxThread - stepMod; k++) {
313         int start = k * step;
314         int end = (k + 1) * step;
315         auto func = [&src, &dst, &x, &y, start, end, n] {
316             SLRSliceKey key(start, end);
317             SLRSubtask(key, src, dst, x, y);
318         };
319         auto handler = ffrt::submit_h(func, {}, {}, ffrt::task_attr().qos(5)); // 5 max ffrt qos value
320         if (ffrtHandles.size() < FFRT_THREAD_LIMIT) {
321             ffrtHandles.emplace_back(handler);
322         } else {
323             ffrtHandles1.emplace_back(handler);
324         }
325     }
326 
327     for (int i = (maxThread - stepMod) * step; i < m; i++) {
328         for (int j = 0; j < n; j++) {
329             SLRSliceKey key(i, j);
330             SLRBox(key, src, dst, x, y);
331         }
332     }
333 
334     ffrt::wait(ffrtHandles);
335     ffrt::wait(ffrtHandles1);
336 #else
337     SLRProc::Serial(src, dst, x, y);
338 #endif
339 }
340 } // namespace Media
341 } // namespace OHOS
342