The mathematical principles of Matrix

Translational transform

Rotation transformation

Scaling transformation

Shear transformation

Symmetry transform

Code validation

 

The mathematical principles of Matrix

In Android, if you’ve ever done image manipulation with Matrix, you probably know the Matrix class. Android Matrix is a 3 x 3 Matrix, and its contents are as follows:

 

Image processing of Matrix can be divided into four basic transformations:

Translate translation

Rotate Rotate

Scale transformation

Skew tangent transformation

 

Literally, MSCALE in a matrix is used for scaling, MSKEW for splicing, MTRANS for translation, and MPERSP for perspective. In practice, of course, Matrix cannot be understood literally. At the same time, in the Android documentation, there is no related description of Matrix perspective transformation, so this paper will not discuss this aspect.

 

Android provides pre, Set, and POST operations for each transformation. Among them

Set is used to set values in the Matrix.

Pre is multiplication first, because matrix multiplication does not satisfy the commutative law, so multiplication first and multiplication after must be strictly distinguished. Multiplying first is equivalent to multiplying right in matrix operations.

Post is the product after, because matrix multiplication does not satisfy the commutative law, so the product before and after must be strictly distinguished. Backward multiplication is equivalent to left multiplication in matrix operations.

 

In addition to Translate, the Rotate, Scale, and Skew transformations can all be performed around a central point. If not specified, the corresponding transformations are performed around (0, 0) by default.

 

Now let’s look at the specific cases of the four transformations. Since all graphs are composed of points, we only need to examine a point-dependent transformation.

 

A,Translational transform

Let’s say I have a point whose coordinates are theta, move it to, and suppose thatxAxis andyThe magnitude of axial movement is as follows:



As shown below:



It’s not hard to know:



If expressed as a matrix, it can be written as:

 

 

Second,Rotation transformation

 

2.1 Rotation around the origin of coordinates:

Let’s say I have a point, the origin of relative coordinates rotates clockwiseAfter the case, also assumePThe distance between the point and the origin is zeror, as shown below:



So,



If a matrix is used, it can be expressed as:



 

2.2 Rotation around a point

If I go around some pointClockwise rotation, can be expressed by the matrix as:



Can be reduced to:



Obviously,

1.   

  It’s moving the origin to the pointLater,The new coordinates of.

2.     



It’s the transformation of the last stepRotates clockwise around the origin of the new coordinates 。

3.     



After the rotation transformation in the previous step, the coordinate origin is moved back to the original coordinate origin.

 

Therefore, the rotation transformation around a point can be divided into three steps, that is, first move the coordinate origin to that point, then rotate the transformation around the new coordinate origin, and then move the coordinate origin back to the original coordinate origin.

 

Three,Scaling transformation

Theoretically, there’s no scaling for a point, but given that all images are made up of points, so if the image is atxAxis andyZoom in on each axisk1andk2Times theta, then theta of all the points in the graphxCoordinates andyThe coordinates will be amplified separatelyk1andk2Times, that is,



In matrix form:



Scaling is a little bit easier to understand, but I won’t go into that.

 

Four,Shear transformation

Skew, also known as Shear mapping or Transvection in mathematics, is a special linear transformation. The effect of the tangent transformation is to make all the pointsxCoordinates (oryCoordinates) remain constant while corresponding toyCoordinates (orxCoordinates) are translated proportionally, and the size of the translation and the point toxThe vertical distance of the axis (or y axis) is proportional. Tangent transformation belongs to equal area transformation, that is, the area of a shape is the same before and after the tangent transformation.

Like the picture belowyThe coordinates stay the same, but it’sxThe coordinates have been shifted proportionally. This would be a horizontal miscut.



For each point in the picture belowxThe coordinates stay the same, but it’syThe coordinates have been shifted proportionally. This situation is called vertical miscut.

 

Let’s say I have a pointIt’s going to be given by the tangent transformation, for horizontal miscut, there should be the following relationship:



In matrix form:



The matrix that extends to 3 x 3 looks like this:

 

Similarly, for vertical mistangent, we can have:



The mathematically rigorous tangent transformation looks something like this. In Android, in addition to the above mentioned situation, you can also carry out horizontal and vertical fault cutting at the same time, so the form is:



 

Five,Symmetry transform

In addition to the basic transformations described above in 4, we can actually use the Matrix to perform symmetric transformations. The so-called symmetric transformation is that the changed image and the original image are symmetric about a certain axis of symmetry. For example, some pointIt’s going to be a symmetric transformation.

If the axis of symmetry is the x axis,



In matrix form:



If the axis of symmetry is the Y-axis,



In matrix form:



If the axis of symmetry is PIy = xAs shown in figure:



So,



It can be easily solved as:



In matrix form:



Same thing if the axis of symmetry is PIy = -x, then it can be expressed by matrix:

 

In particular, if the axis of symmetry isy = kx, as shown below:



So,



It can be easily solved:



In matrix form:



whenk = 0When, that is,y = 0, which is the axis of symmetryxShaft condition; whenkAs it approaches infinity, that isx = 0, which is the axis of symmetryyShaft condition; whenk =1, namelyy = x, which is the axis of symmetryy = xThe situation; whenk = –1, namelyy = -x, which is the axis of symmetryy = -xIn the case. It is not difficult to verify that this is consistent with the specific situation mentioned in 4.

 

If the axis of symmetry is PIy = kx + bIn this case, we only need to add two translation transformations on the basis of the above, that is, first move the coordinate origin to (0, b) and then do the above abouty = kxAnd then move the coordinate origin back to the original coordinate origin. The matrix looks something like this:



Special note: in actual programming, we know about screensyCoordinate forward sum in mathematicsyThe coordinates are just opposite, so mathematicallyy = xAnd on the screeny = -xIs really the same thing, and vice versa. That is, if you want to make the picture on the screen look like a mathematical sensey = xSymmetric, then use this conversion:



Make the picture on the screen look like a mathematical sensey = -xSymmetric, then use this conversion:

 

The same is true for symmetry y = kx or y = kx + b.

The second partCode validation

The verification codes for various image transformations described in the first part are as follows, and a total of 10 cases are listed. If you want to validate one of these cases, simply uncomment the corresponding code. Images used in the experiment:



Its dimensions are 162 x 251.

 

The result of each transformation is described below.

  1. <span style=“font-size:13px;”></span><pre name=“code” class= “java”>package com.pat.testtransformmatrix;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.BitmapFactory;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.Matrix;  
  9. import android.os.Bundle;  
  10. import android.util.Log;  
  11. import android.view.MotionEvent;  
  12. import android.view.View;  
  13. import android.view.Window;  
  14. import android.view.WindowManager;  
  15. import android.view.View.OnTouchListener;  
  16. import android.widget.ImageView;  
  17.   
  18. public class TestTransformMatrixActivity extends Activity  
  19. implements  
  20. OnTouchListener  
  21. {  
  22.     private TransformMatrixView view;  
  23.     @Override  
  24.     public void onCreate(Bundle savedInstanceState)  
  25.     {  
  26.         super.onCreate(savedInstanceState);  
  27.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  28.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  29.   
  30.         view = new TransformMatrixView(this);  
  31.         view.setScaleType(ImageView.ScaleType.MATRIX);  
  32.         view.setOnTouchListener(this);  
  33.           
  34.         setContentView(view);  
  35.     }  
  36.       
  37.     class TransformMatrixView extends ImageView  
  38.     {  
  39.         private Bitmap bitmap;  
  40.         private Matrix matrix;  
  41.         public TransformMatrixView(Context context)  
  42.         {  
  43.             super(context);  
  44.             bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);  
  45.             matrix = new Matrix();  
  46.         }  
  47.   
  48.         @Override  
  49.         protected void onDraw(Canvas canvas)  
  50.         {  
  51.             // Draw the original image  
  52.             canvas.drawBitmap(bitmap, 0.0. null);  
  53.             // Draw the transformed image  
  54.             canvas.drawBitmap(bitmap, matrix, null);  
  55.             super.onDraw(canvas);  
  56.         }  
  57.   
  58.         @Override  
  59.         public void setImageMatrix(Matrix matrix)  
  60.         {  
  61.             this.matrix.set(matrix);  
  62.             super.setImageMatrix(matrix);  
  63.         }  
  64.           
  65.         public Bitmap getImageBitmap()  
  66.         {  
  67.             return bitmap;  
  68.         }  
  69.     }  
  70.   
  71.     public boolean onTouch(View v, MotionEvent e)  
  72.     {  
  73.         if(e.getAction() == MotionEvent.ACTION_UP)  
  74.         {  
  75.             Matrix matrix = new Matrix();  
  76.             // Output image width and height (162 x 251)  
  77.             Log.e(“TestTransformMatrixActivity”.“image size: width x height = “ +  view.getImageBitmap().getWidth() +  ” x “ + view.getImageBitmap().getHeight());  
  78.             / / 1. Translation  
  79.             matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());  
  80.             GetImageBitmap ().getwidth (), view.getimageBitmap ().getheight ()  
  81.             view.setImageMatrix(matrix);  
  82.               
  83.             // The following code is used to view elements in matrix  
  84.             float[] matrixValues = new  float[9];  
  85.             matrix.getValues(matrixValues);  
  86.             for(int i = 0; i <  3; ++i)  
  87.             {  
  88.                 String temp = new String();  
  89.                 for(int j =  0; j < 3; ++j)  
  90.                 {  
  91.                     temp += matrixValues[3 * i + j ] +  “\t”;  
  92.                 }  
  93.                 Log.e(“TestTransformMatrixActivity”, temp);  
  94.             }  
  95.               
  96.   
  97. // // 2. Rotation (around the center of the image)  
  98. //          matrix.setRotate(45f, view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);  
  99. //            
  100. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  101. PostTranslate (view.getimagebitmap ().getwidth () * 1.5f, 0f); // matrix.posttranslate (view.getimagebitmap ().getwidth () * 1.5f, 0f);  
  102. //          view.setImageMatrix(matrix);  
  103. //  
  104. // // The code below is to view the elements in the matrix  
  105. //          float[] matrixValues = new float[9];  
  106. //          matrix.getValues(matrixValues);  
  107. //          for(int i = 0; i < 3; ++i)  
  108. / / {  
  109. //              String temp = new String();  
  110. //              for(int j = 0; j < 3; ++j)  
  111. / / {  
  112. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  113. //              }  
  114. //              Log.e(“TestTransformMatrixActivity”, temp);  
  115. //          }  
  116.               
  117.               
  118. // // 3. Rotation (around the origin of coordinates) + translation (effect the same as 2)  
  119. //          matrix.setRotate(45f);  
  120. //          matrix.preTranslate(-1f * view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight() / 2f);  
  121. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() / 2f, (float)view.getImageBitmap().getHeight() / 2f);  
  122. //            
  123. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  124. PostTranslate ((float) view.getimagebitmap ().getwidth () * 1.5f, 0f); // matrix.posttranslate ((float) view.getimagebitmap ().getwidth () * 1.5f, 0f);  
  125. //          view.setImageMatrix(matrix);  
  126. //            
  127. // // The code below is to view the elements in the matrix  
  128. //          float[] matrixValues = new float[9];  
  129. //          matrix.getValues(matrixValues);  
  130. //          for(int i = 0; i < 3; ++i)  
  131. / / {  
  132. //              String temp = new String();  
  133. //              for(int j = 0; j < 3; ++j)  
  134. / / {  
  135. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  136. //              }  
  137. //              Log.e(“TestTransformMatrixActivity”, temp);  
  138. //          }             
  139.               
  140. // // 4. Zoom  
  141. //          matrix.setScale(2f, 2f);  
  142. // // The code below is to view the elements in the matrix  
  143. //          float[] matrixValues = new float[9];  
  144. //          matrix.getValues(matrixValues);  
  145. //          for(int i = 0; i < 3; ++i)  
  146. / / {  
  147. //              String temp = new String();  
  148. //              for(int j = 0; j < 3; ++j)  
  149. / / {  
  150. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  151. //              }  
  152. //              Log.e(“TestTransformMatrixActivity”, temp);  
  153. //          }  
  154. //            
  155. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  156. //          matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());  
  157. //          view.setImageMatrix(matrix);  
  158. //            
  159. // // The code below is to view the elements in the matrix  
  160. //          matrixValues = new float[9];  
  161. //          matrix.getValues(matrixValues);  
  162. //          for(int i = 0; i < 3; ++i)  
  163. / / {  
  164. //              String temp = new String();  
  165. //              for(int j = 0; j < 3; ++j)  
  166. / / {  
  167. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  168. //              }  
  169. //              Log.e(“TestTransformMatrixActivity”, temp);  
  170. //          }  
  171.   
  172.               
  173. // // 5. Wrong cut – level  
  174. / / matrix. SetSkew (0.5 f, 0 f);  
  175. // // The code below is to view the elements in the matrix  
  176. //          float[] matrixValues = new float[9];  
  177. //          matrix.getValues(matrixValues);  
  178. //          for(int i = 0; i < 3; ++i)  
  179. / / {  
  180. //              String temp = new String();  
  181. //              for(int j = 0; j < 3; ++j)  
  182. / / {  
  183. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  184. //              }  
  185. //              Log.e(“TestTransformMatrixActivity”, temp);  
  186. //          }  
  187. //            
  188. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  189. //          matrix.postTranslate(view.getImageBitmap().getWidth(), 0f);  
  190. //          view.setImageMatrix(matrix);  
  191. //            
  192. // // The code below is to view the elements in the matrix  
  193. //          matrixValues = new float[9];  
  194. //          matrix.getValues(matrixValues);  
  195. //          for(int i = 0; i < 3; ++i)  
  196. / / {  
  197. //              String temp = new String();  
  198. //              for(int j = 0; j < 3; ++j)  
  199. / / {  
  200. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  201. //              }  
  202. //              Log.e(“TestTransformMatrixActivity”, temp);  
  203. //          }  
  204.               
  205. // // 6. Wrong cut – vertical  
  206. / / matrix. SetSkew (0 f, 0.5 f);  
  207. // // The code below is to view the elements in the matrix  
  208. //          float[] matrixValues = new float[9];  
  209. //          matrix.getValues(matrixValues);  
  210. //          for(int i = 0; i < 3; ++i)  
  211. / / {  
  212. //              String temp = new String();  
  213. //              for(int j = 0; j < 3; ++j)  
  214. / / {  
  215. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  216. //              }  
  217. //              Log.e(“TestTransformMatrixActivity”, temp);  
  218. //          }  
  219. //            
  220. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  221. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());  
  222. //          view.setImageMatrix(matrix);  
  223. //            
  224. // // The code below is to view the elements in the matrix  
  225. //          matrixValues = new float[9];  
  226. //          matrix.getValues(matrixValues);  
  227. //          for(int i = 0; i < 3; ++i)  
  228. / / {  
  229. //              String temp = new String();  
  230. //              for(int j = 0; j < 3; ++j)  
  231. / / {  
  232. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  233. //              }  
  234. //              Log.e(“TestTransformMatrixActivity”, temp);  
  235. //          }             
  236.               
  237. // 7. Wrong cut – horizontal + vertical  
  238. / / matrix. SetSkew (0.5 0.5 f, f);  
  239. // // The code below is to view the elements in the matrix  
  240. //          float[] matrixValues = new float[9];  
  241. //          matrix.getValues(matrixValues);  
  242. //          for(int i = 0; i < 3; ++i)  
  243. / / {  
  244. //              String temp = new String();  
  245. //              for(int j = 0; j < 3; ++j)  
  246. / / {  
  247. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  248. //              }  
  249. //              Log.e(“TestTransformMatrixActivity”, temp);  
  250. //          }  
  251. //            
  252. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  253. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());  
  254. //          view.setImageMatrix(matrix);  
  255. //            
  256. // // The code below is to view the elements in the matrix  
  257. //          matrixValues = new float[9];  
  258. //          matrix.getValues(matrixValues);  
  259. //          for(int i = 0; i < 3; ++i)  
  260. / / {  
  261. //              String temp = new String();  
  262. //              for(int j = 0; j < 3; ++j)  
  263. / / {  
  264. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  265. //              }  
  266. //              Log.e(“TestTransformMatrixActivity”, temp);  
  267. //          }  
  268.               
  269. // // 8. Symmetry (horizontal symmetry)  
  270. //          float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};  
  271. //          matrix.setValues(matrix_values);  
  272. // // The code below is to view the elements in the matrix  
  273. //          float[] matrixValues = new float[9];  
  274. //          matrix.getValues(matrixValues);  
  275. //          for(int i = 0; i < 3; ++i)  
  276. / / {  
  277. //              String temp = new String();  
  278. //              for(int j = 0; j < 3; ++j)  
  279. / / {  
  280. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  281. //              }  
  282. //              Log.e(“TestTransformMatrixActivity”, temp);  
  283. //          }  
  284. //            
  285. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  286. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight() * 2f);  
  287. //          view.setImageMatrix(matrix);  
  288. //            
  289. // // The code below is to view the elements in the matrix  
  290. //          matrixValues = new float[9];  
  291. //          matrix.getValues(matrixValues);  
  292. //          for(int i = 0; i < 3; ++i)  
  293. / / {  
  294. //              String temp = new String();  
  295. //              for(int j = 0; j < 3; ++j)  
  296. / / {  
  297. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  298. //              }  
  299. //              Log.e(“TestTransformMatrixActivity”, temp);  
  300. //          }             
  301.               
  302. // // 9. Symmetrical – vertical  
  303. //          float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};  
  304. //          matrix.setValues(matrix_values);  
  305. // // The code below is to view the elements in the matrix  
  306. //          float[] matrixValues = new float[9];  
  307. //          matrix.getValues(matrixValues);  
  308. //          for(int i = 0; i < 3; ++i)  
  309. / / {  
  310. //              String temp = new String();  
  311. //              for(int j = 0; j < 3; ++j)  
  312. / / {  
  313. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  314. //              }  
  315. //              Log.e(“TestTransformMatrixActivity”, temp);  
  316. //          }     
  317. //            
  318. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  319. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 2f, 0f);  
  320. //          view.setImageMatrix(matrix);  
  321. //            
  322. // // The code below is to view the elements in the matrix  
  323. //          matrixValues = new float[9];  
  324. //          matrix.getValues(matrixValues);  
  325. //          for(int i = 0; i < 3; ++i)  
  326. / / {  
  327. //              String temp = new String();  
  328. //              for(int j = 0; j < 3; ++j)  
  329. / / {  
  330. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  331. //              }  
  332. //              Log.e(“TestTransformMatrixActivity”, temp);  
  333. //          }  
  334.   
  335.               
  336. // // 10. Symmetry (axis of symmetry is straight line y = x)  
  337. //          float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};  
  338. //          matrix.setValues(matrix_values);  
  339. // // The code below is to view the elements in the matrix  
  340. //          float[] matrixValues = new float[9];  
  341. //          matrix.getValues(matrixValues);  
  342. //          for(int i = 0; i < 3; ++i)  
  343. / / {  
  344. //              String temp = new String();  
  345. //              for(int j = 0; j < 3; ++j)  
  346. / / {  
  347. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  348. //              }  
  349. //              Log.e(“TestTransformMatrixActivity”, temp);  
  350. //          }  
  351. //            
  352. // // do the following translation transformation, purely to make the transformed image and the original image do not overlap  
  353. //          matrix.postTranslate(view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(),   
  354. //                  view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth());  
  355. //          view.setImageMatrix(matrix);  
  356. //            
  357. // // The code below is to view the elements in the matrix  
  358. //          matrixValues = new float[9];  
  359. //          matrix.getValues(matrixValues);  
  360. //          for(int i = 0; i < 3; ++i)  
  361. / / {  
  362. //              String temp = new String();  
  363. //              for(int j = 0; j < 3; ++j)  
  364. / / {  
  365. //                  temp += matrixValues[3 * i + j ] + “\t”;  
  366. //              }  
  367. //              Log.e(“TestTransformMatrixActivity”, temp);  
  368. //          }  
  369.               
  370.             view.invalidate();  
  371.         }  
  372.         return true;  
  373.     }  
  374. }  





 

The specific results of various transformations in the above code and their corresponding transformation matrices are given below

1. The translation

Output results:

Please check the correctness of the above matrix against the case described in part 1: translation transformation.

 

2. Rotate (around the center of the image)

Output results:

It’s actually

matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);

Matrix. PostTranslate (view. GetImageBitmap () getWidth () * 1.5 f, 0 f);

The result of the combination of these two statements. According to the formula for rotation around a point in Part 1,

matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);

The resulting transformation matrix is:

And the matrix. PostTranslate (the getImageBitmap (.) getWidth () * 1.5 f, 0 f); To the left of the above matrix multiply by the following matrix:

The fact that post is left multiplied was mentioned earlier in the theory section, and we’ll talk more about it later.

 

So it’s actually:

When we go out to calculate the accuracy error, we can see that the result we calculated is consistent with the result directly output by the program.

 

3. Rotation (rotation around the origin of coordinates, plus two translations, the effect is the same as 2)

According to the explanation about rotation around a point in part 1, “Ii. Rotation Transformation”, it is not difficult to know:

matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);

Is equivalent to

matrix.setRotate(45f);

matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f *view.getImageBitmap().getHeight() / 2f);

matrix.postTranslate((float)view.getImageBitmap().getWidth()/ 2f, (float)view.getImageBitmap().getHeight() / 2f);

 

The corresponding matrix of matrix. SetRotate (45f) is:

Matrix. PreTranslate (-1f* view.getimagebitmap ().getwidth ()/ 2f, -1f* view.getimagebitmap ().getheight ()/ 2f)

Since it is preTranslate, it is multiply first, that is, multiply right, that is, it should appear on the right side of the matrix corresponding to matrix.setrotate (45f).

 

PostTranslate ((float) view.getimageBitmap ().getwidth ()/ 2f, (float) view.getimagebitmap ().getheight ()/ 2f)

This time, since it’s postTranslate, it’s a back multiplier, that is, a left multiplier, which means it should appear on the left side of the matrix corresponding to matrix.setrotate (45f).

 

So put it all together,

matrix.setRotate(45f);

matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f *view.getImageBitmap().getHeight() / 2f);

matrix.postTranslate((float)view.getImageBitmap().getWidth()/ 2f, (float)view.getImageBitmap().getHeight() / 2f);

The corresponding matrix is:

This is the same as the following matrix (rotated 45 degrees clockwise around the center of the image) :

Therefore, the transformed image here is the same as the transformed image in 2.

 

4. Scale transformation

The two matrices output by the program are:

The second matrix is actually the product of two matrices:

 

You can compare the first part of the “three, scaling transformation” and “one, translation transformation” statement, verify the results.

 

5. Miscut transformation (horizontal miscut)

The two matrices output from this code are:

Where the second matrix is actually the product of the following two matrices:

 

You can compare the first part of the “four, wrong tangent transformation” and “one, translation transformation” related statements, verify the results.

 

6. Miscut transformation (vertical miscut)

The two matrices output from this code are:

Where the second matrix is actually the product of the following two matrices:

You can compare the first part of the “four, wrong tangent transformation” and “one, translation transformation” related statements, verify the results.

 

7. Miscut transformation (horizontal + vertical miscut)

The two matrices output from this code are:

Where, the latter is the product of the following two matrices:

You can compare the first part of the “four, wrong tangent transformation” and “one, translation transformation” related statements, verify the results.

 

8. Symmetric transformation (horizontal symmetry)

The two matrices output from the code are:

Where, the latter is the product of the following two matrices:

 

You can compare the first part of the “five, symmetric transformation” and “one, translation transformation” related statements, verify the results.

 

9. Symmetric transformation (vertical symmetry)

The two matrices output from this code are:

Where, the latter is the product of the following two matrices:

 

You can compare the first part of the “five, symmetric transformation” and “one, translation transformation” related statements, verify the results.

 

10. Symmetry transformation (the axis of symmetry is a straight liney = x)

The two matrices output from this code are:

Where, the latter is the product of the following two matrices:

 

You can compare the first part of the “five, symmetric transformation” and “one, translation transformation” related statements, verify the results.

 

11. The question of first and last multiplying

Because the matrix multiplication operation does not satisfy the commutative law, we have mentioned the problem of first multiplication and then multiplication many times in front, that is, first multiplication is the right multiplication in matrix operation, and then multiplication is the left multiplication in matrix operation. In fact, the concept of multiply first and multiply later is for the time sequence of transformation operations, while left and right multiply are for the left and right positions of matrix operations. Take the case of rotation around a point in the first part “Ii. Rotation Transformation” as an example:

 

The closer it is to the matrix of pixels in the original image, the closer it is to the matrix of pixels in the original image, the more backward it is multiplied. In fact, in the image processing, the matrix operation goes from the right to the left. This forms a matrix that is more to the right (multiply by right), more first (multiply by first), and vice versa.

 

Of course, in practice, if we specify a matrix first, such as setRotate(), that is, specify the middle matrix in the above transformation matrix, so whether the subsequent matrix is pre or post operation depends on the middle matrix.