1 /*
2  * Copyright (C) 2021 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 "matrix.h"
17 
18 #include "image_log.h"
19 
20 #undef LOG_DOMAIN
21 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
22 
23 #undef LOG_TAG
24 #define LOG_TAG "Matrix"
25 
26 namespace OHOS {
27 namespace Media {
28 
Reset()29 Matrix &Matrix::Reset()
30 {
31     *this = Matrix();
32     return *this;
33 }
34 
SetTranslate(const float tx,const float ty)35 Matrix &Matrix::SetTranslate(const float tx, const float ty)
36 {
37     *this = Matrix(1, 0, tx, 0, 1, ty, 0, 1, 1, (tx == 0 || ty == 0) ? IDENTITY : TRANSLATE);
38     return *this;
39 }
40 
SetScale(const float sx,const float sy)41 Matrix &Matrix::SetScale(const float sx, const float sy)
42 {
43     *this = Matrix(sx, 0, 0, 0, sy, 0, 0, 0, 1, (sx == 1 && sy == 1) ? IDENTITY : SCALE);
44     return *this;
45 }
46 
SetRotate(const float degrees,const float px,const float py)47 Matrix &Matrix::SetRotate(const float degrees, const float px, const float py)
48 {
49     float radians = DegreesToRadians(degrees);
50     return SetSinCos(ValueNearToZero(radians, true), ValueNearToZero(radians, false), px, py);
51 }
52 
SetSinCos(const float sinValue,const float cosValue,const float px,const float py)53 Matrix &Matrix::SetSinCos(const float sinValue, const float cosValue, const float px, const float py)
54 {
55     const float reverseCosValue = 1.0f - cosValue;
56 
57     fMat_[IMAGE_SCALEX] = cosValue;
58     fMat_[IMAGE_SKEWX] = -sinValue;
59     fMat_[IMAGE_TRANSX] = sinValue * py + reverseCosValue * px;
60 
61     fMat_[IMAGE_SKEWY] = sinValue;
62     fMat_[IMAGE_SCALEY] = cosValue;
63     fMat_[IMAGE_TRANSY] = -sinValue * px + reverseCosValue * py;
64 
65     fMat_[IMAGE_PERSP0] = fMat_[IMAGE_PERSP1] = 0;
66     fMat_[IMAGE_PERSP2] = 1;
67 
68     operType_ = ROTATEORSKEW;
69 
70     return *this;
71 }
72 
SetConcat(const Matrix & m)73 Matrix &Matrix::SetConcat(const Matrix &m)
74 {
75     OperType aOperType = this->GetOperType();
76     OperType bOperType = m.GetOperType();
77 
78     if ((static_cast<uint8_t>(aOperType) & OPERTYPE_MASK) == 0) {
79         *this = m;
80     } else if (((static_cast<uint8_t>(aOperType) | static_cast<uint8_t>(bOperType)) & ROTATEORSKEW) == 0) {
81         SetTranslateAndScale(fMat_[IMAGE_TRANSX] * m.fMat_[IMAGE_TRANSX] + fMat_[IMAGE_TRANSX],
82                              fMat_[IMAGE_TRANSY] * m.fMat_[IMAGE_TRANSY] + fMat_[IMAGE_TRANSY],
83                              fMat_[IMAGE_SCALEX] * m.fMat_[IMAGE_SCALEX], fMat_[IMAGE_SCALEY] * m.fMat_[IMAGE_SCALEY]);
84     } else {
85         Matrix src = *this;
86         fMat_[IMAGE_SCALEX] = static_cast<float>(
87             MulAddMul(src.fMat_[IMAGE_SCALEX], m.fMat_[IMAGE_SCALEX], src.fMat_[IMAGE_SKEWX], m.fMat_[IMAGE_SKEWY]));
88 
89         fMat_[IMAGE_SKEWX] = static_cast<float>(
90             MulAddMul(src.fMat_[IMAGE_SCALEX], m.fMat_[IMAGE_SKEWX], src.fMat_[IMAGE_SKEWX], m.fMat_[IMAGE_SCALEY]));
91 
92         fMat_[IMAGE_TRANSX] = static_cast<float>(
93             MulAddMul(src.fMat_[IMAGE_SCALEX], m.fMat_[IMAGE_TRANSX], src.fMat_[IMAGE_SKEWX], m.fMat_[IMAGE_TRANSY]) +
94             src.fMat_[IMAGE_TRANSX]);
95 
96         fMat_[IMAGE_SKEWY] = static_cast<float>(
97             MulAddMul(src.fMat_[IMAGE_SKEWY], m.fMat_[IMAGE_SCALEX], src.fMat_[IMAGE_SCALEY], m.fMat_[IMAGE_SKEWY]));
98 
99         fMat_[IMAGE_SCALEY] = static_cast<float>(
100             MulAddMul(src.fMat_[IMAGE_SKEWY], m.fMat_[IMAGE_SKEWX], src.fMat_[IMAGE_SCALEY], m.fMat_[IMAGE_SCALEY]));
101 
102         fMat_[IMAGE_TRANSY] = static_cast<float>(
103             MulAddMul(src.fMat_[IMAGE_SKEWY], m.fMat_[IMAGE_TRANSX], src.fMat_[IMAGE_SCALEY], m.fMat_[IMAGE_TRANSY]) +
104             src.fMat_[IMAGE_TRANSY]);
105 
106         fMat_[IMAGE_PERSP0] = fMat_[IMAGE_PERSP1] = 0;
107         fMat_[IMAGE_PERSP2] = 1;
108 
109         operType_ = ROTATEORSKEW;
110     }
111     return *this;
112 }
113 
GetOperType() const114 Matrix::OperType Matrix::GetOperType() const
115 {
116     return (OperType)(operType_ & OPERTYPE_MASK);
117 }
118 
SetTranslateAndScale(const float tx,const float ty,const float sx,const float sy)119 void Matrix::SetTranslateAndScale(const float tx, const float ty, const float sx, const float sy)
120 {
121     fMat_[IMAGE_SCALEX] = sx;
122     fMat_[IMAGE_SKEWX] = 0;
123     fMat_[IMAGE_TRANSX] = tx;
124 
125     fMat_[IMAGE_SKEWY] = 0;
126     fMat_[IMAGE_SCALEY] = sy;
127     fMat_[IMAGE_TRANSY] = ty;
128 
129     fMat_[IMAGE_PERSP0] = fMat_[IMAGE_PERSP1] = 0;
130     fMat_[IMAGE_PERSP2] = 1;
131 
132     if (sx != 1 || sy != 1) {
133         operType_ |= SCALE;
134     }
135     if (tx != 0 || ty != 0) {
136         operType_ |= TRANSLATE;
137     }
138 }
139 
Invert(Matrix & invMatrix)140 bool Matrix::Invert(Matrix &invMatrix)
141 {
142     invMatrix.operType_ = operType_;
143     if (IsIdentity()) {
144         invMatrix.Reset();
145         return true;
146     }
147 
148     if ((operType_ & (~(TRANSLATE | SCALE))) == 0) {
149         if (operType_ & SCALE) {
150             float invScaleX = fMat_[IMAGE_SCALEX];
151             float invScaleY = fMat_[IMAGE_SCALEY];
152             if (std::fabs(invScaleX) < MATRIX_EPSILON || std::fabs(invScaleY) < MATRIX_EPSILON) {
153                 return false;
154             }
155 
156             // 1.0f used when calculating the inverse matrix
157             invScaleX = FDivide(1.0f, invScaleX);
158             invScaleY = FDivide(1.0f, invScaleY);
159 
160             invMatrix.fMat_[IMAGE_SCALEX] = invScaleX;
161             invMatrix.fMat_[IMAGE_SCALEY] = invScaleY;
162 
163             invMatrix.fMat_[IMAGE_TRANSX] = -fMat_[IMAGE_TRANSX] * invScaleX;
164             invMatrix.fMat_[IMAGE_TRANSY] = -fMat_[IMAGE_TRANSY] * invScaleY;
165 
166             invMatrix.fMat_[IMAGE_SKEWX] = invMatrix.fMat_[IMAGE_SKEWY] = invMatrix.fMat_[IMAGE_PERSP0] =
167                 invMatrix.fMat_[IMAGE_PERSP1] = 0;
168             invMatrix.fMat_[IMAGE_PERSP2] = 1;
169         } else {
170             invMatrix.SetTranslate(-fMat_[IMAGE_TRANSX], -fMat_[IMAGE_TRANSY]);
171         }
172         return true;
173     }
174 
175     return InvertForRotate(invMatrix);
176 }
177 
InvertForRotate(Matrix & invMatrix)178 bool Matrix::InvertForRotate(Matrix &invMatrix)
179 {
180     double invDet = MulSubMul(fMat_[IMAGE_SCALEX], fMat_[IMAGE_SCALEY], fMat_[IMAGE_SKEWX], fMat_[IMAGE_SKEWY]);
181     if (fabsf(static_cast<float>(invDet)) < (FLOAT_NEAR_ZERO * FLOAT_NEAR_ZERO * FLOAT_NEAR_ZERO)) {
182         return false;
183     } else {
184         invDet = 1.0 / invDet;  // 1.0 used when calculating the inverse matrix
185     }
186 
187     invMatrix.fMat_[IMAGE_SCALEX] = static_cast<float>(fMat_[IMAGE_SCALEY] * invDet);
188     invMatrix.fMat_[IMAGE_SKEWX] = static_cast<float>(-fMat_[IMAGE_SKEWX] * invDet);
189     invMatrix.fMat_[IMAGE_TRANSX] = static_cast<float>(
190         MulSubMul(fMat_[IMAGE_SKEWX], fMat_[IMAGE_TRANSY], fMat_[IMAGE_SCALEY], fMat_[IMAGE_TRANSX]) * invDet);
191 
192     invMatrix.fMat_[IMAGE_SKEWY] = static_cast<float>(-fMat_[IMAGE_SKEWY] * invDet);
193     invMatrix.fMat_[IMAGE_SCALEY] = static_cast<float>(fMat_[IMAGE_SCALEX] * invDet);
194     invMatrix.fMat_[IMAGE_TRANSY] = static_cast<float>(
195         MulSubMul(fMat_[IMAGE_SKEWY], fMat_[IMAGE_TRANSX], fMat_[IMAGE_SCALEX], fMat_[IMAGE_TRANSY]) * invDet);
196 
197     invMatrix.fMat_[IMAGE_PERSP0] = invMatrix.fMat_[IMAGE_PERSP1] = 0;
198     invMatrix.fMat_[IMAGE_PERSP2] = 1;
199 
200     return true;
201 }
202 
IdentityXY(const Matrix & m,const float sx,const float sy,Point & pt)203 void Matrix::IdentityXY(const Matrix &m, const float sx, const float sy, Point &pt)
204 {
205     if (m.GetOperType() == 0) {
206         pt.x = sx;
207         pt.y = sy;
208     }
209 }
210 
ScaleXY(const Matrix & m,const float sx,const float sy,Point & pt)211 void Matrix::ScaleXY(const Matrix &m, const float sx, const float sy, Point &pt)
212 {
213     if ((static_cast<uint8_t>(m.GetOperType()) & SCALE) == SCALE) {
214         pt.x = sx * m.fMat_[IMAGE_SCALEX] + m.fMat_[IMAGE_TRANSX];
215         pt.y = sy * m.fMat_[IMAGE_SCALEY] + m.fMat_[IMAGE_TRANSY];
216     }
217 }
218 
TransXY(const Matrix & m,const float tx,const float ty,Point & pt)219 void Matrix::TransXY(const Matrix &m, const float tx, const float ty, Point &pt)
220 {
221     if (m.GetOperType() == TRANSLATE) {
222         pt.x = tx + m.fMat_[IMAGE_TRANSX];
223         pt.y = ty + m.fMat_[IMAGE_TRANSY];
224     }
225 }
226 
RotXY(const Matrix & m,const float rx,const float ry,Point & pt)227 void Matrix::RotXY(const Matrix &m, const float rx, const float ry, Point &pt)
228 {
229     if ((static_cast<uint8_t>(m.GetOperType()) & ROTATEORSKEW) == ROTATEORSKEW) {
230         pt.x = rx * m.fMat_[IMAGE_SCALEX] + ry * m.fMat_[IMAGE_SKEWX] + m.fMat_[IMAGE_TRANSX];
231         pt.y = rx * m.fMat_[IMAGE_SKEWY] + ry * m.fMat_[IMAGE_SCALEY] + m.fMat_[IMAGE_TRANSY];
232     }
233 }
234 
235 const Matrix::CalcXYProc Matrix::gCalcXYProcs[] = { Matrix::IdentityXY, Matrix::TransXY, Matrix::ScaleXY,
236                                                     Matrix::ScaleXY,    Matrix::RotXY,   Matrix::RotXY,
237                                                     Matrix::RotXY,      Matrix::RotXY };
238 
239 // Matrix print function, including 9 elements
Print()240 void Matrix::Print()
241 {
242     IMAGE_LOGD("[Matrix][%{public}8.4f %{public}8.4f %{public}8.4f]"
243         "[%{public}8.4f %{public}8.4f %{public}8.4f][%{public}8.4f %{public}8.4f %{public}8.4f].",
244         fMat_[IMAGE_SCALEX], fMat_[IMAGE_SKEWX], fMat_[IMAGE_TRANSX], fMat_[IMAGE_SKEWY],
245         fMat_[IMAGE_SCALEY], fMat_[IMAGE_TRANSY], fMat_[IMAGE_PERSP0], fMat_[IMAGE_PERSP1], fMat_[IMAGE_PERSP2]);
246 }
247 } // namespace Media
248 } // namespace OHOS
249