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