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) { // 6 means color vector scale
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 LOGD("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 LOGD("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 // Color matrix is a 4x5 float type matrix.
73 for (int j = 0; j < MATRIX_SIZE; j = j + 5) { // 5 means color matrix cols
74 for (int i = 0; i < 4; i++) { // 4 means color matrix rows
75 target[index++] = m1.array_[j + 0] * m2.array_[i + 0] + // 0 means color matrix offset
76 m1.array_[j + 1] * m2.array_[i + 5] + //1 5 means color matrix offset
77 m1.array_[j + 2] * m2.array_[i + 10] + //2 10 means color matrix offset
78 m1.array_[j + 3] * m2.array_[i + 15]; //3 15 means color matrix offset
79 }
80 target[index++] = m1.array_[j + 0] * m2.array_[4] + //0 4 means color matrix offset
81 m1.array_[j + 1] * m2.array_[9] + //1 9 means color matrix offset
82 m1.array_[j + 2] * m2.array_[14] + //2 14 means color matrix offset
83 m1.array_[j + 3] * m2.array_[19] + //3 19 means color matrix offset
84 m1.array_[j + 4]; //4 means color matrix offset
85 }
86
87 if (target != array_) {
88 auto ret = memcpy_s(array_, sizeof(array_), target, sizeof(array_));
89 if (ret != EOK) {
90 LOGD("Drawing: ColorMatrix memcpy_s failed");
91 }
92 }
93 }
94
PreConcat(const ColorMatrix & m)95 void ColorMatrix::PreConcat(const ColorMatrix& m)
96 {
97 SetConcat(*this, m);
98 }
99
PostConcat(const ColorMatrix & m)100 void ColorMatrix::PostConcat(const ColorMatrix& m)
101 {
102 SetConcat(m, *this);
103 }
104
SetScale(scalar sr,scalar sg,scalar sb,scalar sa)105 void ColorMatrix::SetScale(scalar sr, scalar sg, scalar sb, scalar sa)
106 {
107 auto ret = memset_s(array_, sizeof(array_), 0, sizeof(array_));
108 if (ret != EOK) {
109 LOGD("Drawing: ColorMatrix memset_s failed");
110 return;
111 }
112 array_[0] = sr; // 0 means red vector scale
113 array_[6] = sg; // 6 means green vector scale
114 array_[12] = sb; // 12 means blue vector scale
115 array_[18] = sa; // 18 means alpha vetor scale
116 }
117
SetSaturation(scalar sat)118 void ColorMatrix::SetSaturation(scalar sat)
119 {
120 auto ret = memset_s(array_, sizeof(array_), 0, sizeof(array_));
121 if (ret != EOK) {
122 LOGD("Drawing: ColorMatrix memset_s failed");
123 return;
124 }
125
126 const float R = HUE_R * (1 - sat);
127 const float G = HUE_G * (1 - sat);
128 const float B = HUE_B * (1 - sat);
129
130 // red channel
131 array_[SCALE_FACTOR_FOR_R] = R + sat;
132 array_[G_FACTOR_FOR_R] = G;
133 array_[B_FACTOR_FOR_R] = B;
134 // green channel
135 array_[R_FACTOR_FOR_G] = R;
136 array_[SCALE_FACTOR_FOR_G] = G + sat;
137 array_[B_FACTOR_FOR_G] = B;
138 // blue channel
139 array_[R_FACTOR_FOR_B] = R;
140 array_[G_FACTOR_FOR_B] = G;
141 array_[SCALE_FACTOR_FOR_B] = B + sat;
142 // alpha vetor scale
143 array_[SCALE_FACTOR_FOR_A] = 1;
144 }
145 } // namespace Drawing
146 } // namespace Rosen
147 } // namespace OHOS
148