• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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