1 /*
2 * Copyright (c) 2023 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 "effect/color_matrix.h"
17
18 #include <securec.h>
19
20 #include "utils/log.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 namespace Drawing {
25 // Hue RGB constant
26 constexpr static float HUE_R = 0.213f;
27 constexpr static float HUE_G = 0.715f;
28 constexpr static float HUE_B = 0.072f;
29
ColorMatrix()30 ColorMatrix::ColorMatrix() noexcept
31 {
32 SetIdentity();
33 }
34
~ColorMatrix()35 ColorMatrix::~ColorMatrix() {}
36
SetIdentity()37 void ColorMatrix::SetIdentity()
38 {
39 for (size_t i = 0; i < MATRIX_SIZE; i = i + 6) {
40 array_[i] = 1; // identity matrix, the value of the elements on the main diagonal is 1
41 }
42 }
43
SetArray(const scalar src[MATRIX_SIZE])44 void ColorMatrix::SetArray(const scalar src[MATRIX_SIZE])
45 {
46 auto ret = memcpy_s(array_, sizeof(array_), src, sizeof(array_));
47 if (ret != EOK) {
48 LOGE("Drawing: ColorMatrix memcpy_s failed");
49 }
50 }
51
GetArray(scalar dst[MATRIX_SIZE]) const52 void ColorMatrix::GetArray(scalar dst[MATRIX_SIZE]) const
53 {
54 auto ret = memcpy_s(dst, sizeof(array_), array_, sizeof(array_));
55 if (ret != EOK) {
56 LOGE("Drawing: ColorMatrix memcpy_s failed");
57 }
58 }
59
SetConcat(const ColorMatrix & m1,const ColorMatrix & m2)60 void ColorMatrix::SetConcat(const ColorMatrix& m1, const ColorMatrix& m2)
61 {
62 scalar tmp[MATRIX_SIZE] = { 0 };
63 scalar* target;
64
65 if (array_ == m1.array_ || array_ == m2.array_) {
66 target = tmp;
67 } else {
68 target = array_;
69 }
70
71 int index = 0;
72 for (int j = 0; j < MATRIX_SIZE; j = j + 5) {
73 for (int i = 0; i < 4; i++) { // Color matrix is a 4x5 float type matrix.
74 target[index++] = m1.array_[j + 0] * m2.array_[i + 0] + m1.array_[j + 1] * m2.array_[i + 5] +
75 m1.array_[j + 2] * m2.array_[i + 10] + m1.array_[j + 3] * m2.array_[i + 15];
76 }
77 target[index++] = m1.array_[j + 0] * m2.array_[4] + m1.array_[j + 1] * m2.array_[9] +
78 m1.array_[j + 2] * m2.array_[14] + m1.array_[j + 3] * m2.array_[19] + m1.array_[j + 4];
79 }
80
81 if (target != array_) {
82 auto ret = memcpy_s(array_, sizeof(array_), target, sizeof(array_));
83 if (ret != EOK) {
84 LOGE("Drawing: ColorMatrix memcpy_s failed");
85 }
86 }
87 }
88
PreConcat(const ColorMatrix & m)89 void ColorMatrix::PreConcat(const ColorMatrix& m)
90 {
91 SetConcat(*this, m);
92 }
93
PostConcat(const ColorMatrix & m)94 void ColorMatrix::PostConcat(const ColorMatrix& m)
95 {
96 SetConcat(m, *this);
97 }
98
SetScale(scalar sr,scalar sg,scalar sb,scalar sa)99 void ColorMatrix::SetScale(scalar sr, scalar sg, scalar sb, scalar sa)
100 {
101 auto ret = memset_s(array_, sizeof(array_), 0, sizeof(array_));
102 if (ret != EOK) {
103 LOGE("Drawing: ColorMatrix memset_s failed");
104 return;
105 }
106 array_[0] = sr; // red vector scale
107 array_[6] = sg; // green vector scale
108 array_[12] = sb; // blue vector scale
109 array_[18] = sa; // alpha vetor scale
110 }
111
SetSaturation(scalar sat)112 void ColorMatrix::SetSaturation(scalar sat)
113 {
114 auto ret = memset_s(array_, sizeof(array_), 0, sizeof(array_));
115 if (ret != EOK) {
116 LOGE("Drawing: ColorMatrix memset_s failed");
117 return;
118 }
119
120 const float R = HUE_R * (1 - sat);
121 const float G = HUE_G * (1 - sat);
122 const float B = HUE_B * (1 - sat);
123
124 // red channel
125 array_[SCALE_FACTOR_FOR_R] = R + sat;
126 array_[G_FACTOR_FOR_R] = G;
127 array_[B_FACTOR_FOR_R] = B;
128 // green channel
129 array_[R_FACTOR_FOR_G] = R;
130 array_[SCALE_FACTOR_FOR_G] = G + sat;
131 array_[B_FACTOR_FOR_G] = B;
132 // blue channel
133 array_[R_FACTOR_FOR_B] = R;
134 array_[G_FACTOR_FOR_B] = G;
135 array_[SCALE_FACTOR_FOR_B] = B + sat;
136 // alpha vetor scale
137 array_[SCALE_FACTOR_FOR_A] = 1;
138 }
139 } // namespace Drawing
140 } // namespace Rosen
141 } // namespace OHOS
142