1. 程式人生 > >Matrix以及圖片適配計算相關

Matrix以及圖片適配計算相關

一、圖片縮放的計算方法

int mScreenWidth; // 螢幕寬度
int mScreenHeight; // 螢幕高度
int mImageWidth; // 圖片寬度
int mImgaeHeight; // 螢幕高度

float imgRatio = (float)mImageWidth / (float) mImgaeHeight;
float screenRatio = (float)mScreenWidth / (float) mScreenHeight;

1.1 圖片壓縮
目的:讓圖片等比壓縮到螢幕內,儘量不讓圖片尺寸超出螢幕,如果圖片剪裁
if (imgRatio < maxRatio) {
   // 實際圖片寬高比小於最大尺寸寬高比時,說明圖片細長,期望圖片高度設定為最大高度,寬度等比壓縮;
   // 含義同兩者的高度比數值小,圖片以高度比為基準等比壓縮
   imgRatio = maxHeight / actualHeight;
   actualWidth = (int) (imgRatio * actualWidth);
   actualHeight = (int) maxHeight;

} else if (imgRatio > maxRatio) {
     // 實際圖片寬高比大於最大尺寸寬高比時,說明圖片寬窄,期望寬度設定為最大寬度,高度等比壓縮;
     // 含義同兩者的寬度比數值小,圖片以寬度比為基準等比壓縮
     imgRatio = maxWidth / actualWidth;
     ctualHeight = (int) (imgRatio * actualHeight);
     actualWidth = (int) maxWidth;

 } else {
      actualHeight = (int) maxHeight;
      actualWidth = (int) maxWidth;
 }

1.2 圖片放大
目的:讓圖片等比放大到超過螢幕尺寸,用於居中裁剪,類似centerCrop

if (imgRatio > maxRatio) {
    // 高度為基準等比放大
    actualWidth = (actualWidth * screenHeight) / actualHeight;
    actualHeight = screenHeight;
} else if (imgRatio < maxRatio) {
    // 寬度為基準等比放大
    actualHeight = (screenWidth * actualHeight) / actualWidth;
    actualWidth = screenWidth;
}

二、setScale,preScale和postScale的區別

1、setScale(sx,sy),首先會將該Matrix設定為對角矩陣,即相當於呼叫reset()方法,然後在設定該Matrix的MSCALE_X和MSCALE_Y直接設定為sx,sy的值

2、preScale(sx,sy),不會重置Matrix,而是直接與Matrix之前的MSCALE_X和MSCALE_Y值結合起來(相乘),M' = M * S(sx, sy)。

3、postScale(sx,sy),不會重置Matrix,而是直接與Matrix之前的MSCALE_X和MSCALE_Y值結合起來(相乘),M' = S(sx, sy) * M。

preScale和post都是與之前的Matrix結合起來,那它們之間又有什麼區別呢?

舉幾個例子測試下關於pre....和post....的區別:

對一個Matrix如下設定

1、pre....的執行順序

[java] view plaincopy

1.    Matrix matrix=new Matrix();  

2.    float[] points=new float[]{10.0f,10.0f};  

3.      

4.    matrix.preScale(2.0f, 3.0f);//  

5.    matrix.preTranslate(8.0f,7.0f);//  

6.    matrix.mapPoints(points);  

7.    Log.i("test", points[0]+"");  

8.    Log.i("test", points[1]+"");  

結果為點座標為(36.0,51.0)

可以得出結論,進行變換的順序是先執行preTranslate(8.0f,7.0f),在執行的preScale(2.0f,3.0f)。這也是為什麼有的人比喻為pre...是向後生長的,即對於一個Matrix的設定中,

所有pre....是倒著向後執行的。

 

2、post...的執行順序

[java] view plaincopy

1.    Matrix matrix=new Matrix();  

2.    float[] points=new float[]{10.0f,10.0f};  

3.      

4.    matrix.postScale(2.0f, 3.0f);//  

5.    matrix.postTranslate(8.0f,7.0f);//  

6.    matrix.mapPoints(points);  

7.    Log.i("test", points[0]+"");  

8.    Log.i("test", points[1]+"");  

結果為點座標為(28.0,37.0)

可以得出結論,進行變換的順序是先執行postScale(2.0f,3.0f),在執行的postTranslate(8.0f,7.0f)。這 也是為什麼有的人比喻為post...是向前生長的,即對於一個Matrix的設定中,所有post....是順著向前執行的。


3、當pre和post交替出現的執行順序

[java] view plaincopy

1.    Matrix matrix=new Matrix();  

2.    float[] points=new float[]{10.0f,10.0f};  

3.      

4.    matrix.postScale(2.0f, 3.0f);  

5.    matrix.preRotate(90);  

6.    matrix.mapPoints(points);  

7.    Log.i("test", points[0]+"");  

8.    Log.i("test", points[1]+"");  

結果為點座標為(-20.0,30.0)

將pre...和post順序換一下

[java] view plaincopy

1.    Matrix matrix=new Matrix();  

2.    float[] points=new float[]{10.0f,10.0f};  

3.      

4.    matrix.preRotate(90);  

5.    matrix.postScale(2.0f, 3.0f);  

6.    matrix.mapPoints(points);  

7.    Log.i("test", points[0]+"");  

8.    Log.i("test", points[1]+"");  

結果為點座標依舊為為(-20.0,30.0)

可見,總是pre先執行的。在看下面的:

[java] view plaincopy

1.    Matrix matrix = new Matrix();  

2.    float[] points = new float[] { 10.0f, 10.0f };  

3.      

4.    matrix.postScale(2.0f, 3.0f);// 第1步  

5.    matrix.preRotate(90);// 第2步  

6.    matrix.postTranslate(8.0f, 7.0f);// 第3步  

7.    matrix.preScale(1.5f, 2.5f);// 第4步  

8.    matrix.mapPoints(points);  

9.    Log.i("test", points[0] + "");  

10.  Log.i("test", points[1] + "");  

結果為點座標依舊為為(-42.0,52.0)
經過前面的結論和推算,可以發現執行的順序是   4----2----1---3


 

 在看下面的,增加了setScale的一段程式碼:

[java] view plaincopy

1.    Matrix matrix = new Matrix();  

2.    float[] points = new float[] { 10.0f, 10.0f };  

3.      

4.    matrix.postScale(2.0f, 3.0f);// 第1步  

5.    matrix.preRotate(90);// 第2步  

6.    matrix.setScale(1.4f, 2.6f);// 第3步  

7.    matrix.postTranslate(8.0f, 7.0f);// 第4步  

8.    matrix.preScale(1.5f, 2.5f);// 第5步  

9.    matrix.mapPoints(points);  

10.  Log.i("test", points[0] + "");  

11.  Log.i("test", points[1] + "");  

結果為點座標依舊為為(29.0,72.0)
經過計算,可以發現,在第3步setScale之前的第1、2步根本就沒有用了,直接被第3步setScale覆蓋,在從第3開始執行的。

順序為2---1----3----5----4,因為2、1被覆蓋了,所以沒有效果,相當於直接執行3-----5----4

 

總結:最後可以得出結論,在對matrix該次變換之前的所有設定中,先檢測有沒有setScale,如果有,直接跳到setScale那一步開始 執行變換,然後在倒著執行下面所有的pre...變換,在順著執行所有post....的變換。所以在對Matrix變換設定的時候,一定要注意順序,不 同的順序,會有不同的結果。

marix來源:https://blog.csdn.net/u011122331/article/details/47149773