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