上章我們描述了Matrix的四個(gè)操作分別是:旋轉(zhuǎn)伟众,平移秽浇,縮放,扭曲
那么假設(shè)現(xiàn)在我們有一個(gè)需求:根據(jù)已有圖片生成這個(gè)分別使用了這四個(gè)操作的圖片弹惦。
那么思路很簡單,如果使用Matrix操作那么代碼應(yīng)該是這樣的:
public Bitmap postMatrix(Matrix matrix, Bitmap bitmap) {
Bitmap resource = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, false);
return resource;
}
根據(jù)上面的代碼我們重新生成了使用矩陣matrix的一張圖片悄但,而生成圖片的寬高仍然保持不變棠隐。那么問題來了,如果需要生成一張對應(yīng)變化寬高的一張圖片呢檐嚣?例如:
下面逐一分析:
1.translate
平移操作的時(shí)候,先計(jì)算移除空白區(qū)域的圖片寬高助泽,生成新圖之后從負(fù)的偏移坐標(biāo)開始繪制圖片,則生成的圖片就是完整移動過后的圖片
/**
* 真實(shí)偏移,圖片寬高會根據(jù)圖片的偏移距離重新生成寬高
*
* @param bitmap,目標(biāo)圖片
* @param preX,偏移X軸百分比
* @param preY,偏移Y軸百分比
* @param isRecycle,是否回收目標(biāo)圖
* @return
*/
public static Bitmap translate(Bitmap bitmap, float preX, float preY, boolean isRecycle) {
Matrix matrix = new Matrix();
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int disX = (int) (width * preX);
int disY = (int) (height * preY);
matrix.postTranslate(disX, disY);
Bitmap resource = Bitmap.createBitmap(bitmap.getWidth() - disX, bitmap.getHeight() - disY, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resource);
// canvas.drawColor(Color.BLACK);//模擬空白
canvas.concat(matrix);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(bitmap, -disX, -disY, paint);//從負(fù)偏移點(diǎn)開始畫嗡贺,那么如果進(jìn)行了translate操作隐解,那么圖片不會留白
if (isRecycle) destroyBitmap(bitmap);
return resource;
}
效果圖如下:
2.scale
和translate的差不多也需要重新計(jì)算寬高,但是需要保證繪制中心必須是新圖的中心诫睬。這樣等比放大的時(shí)候才不會缺失煞茫。
/**
* 真實(shí)縮放,圖片寬高會根據(jù)圖片的縮放比例重新生成寬高
*
* @param bitmap,目標(biāo)
* @param scale,縮放比例
* @param isRecycle摄凡,是否回收目標(biāo)圖
* @return
*/
public static Bitmap scale(Bitmap bitmap, float scale, boolean isRecycle) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix matrix = new Matrix();
int reWidth, reHeight;
reWidth = (int) (width * scale);
reHeight = (int) (height * scale);
matrix.postScale(scale, scale);
Bitmap resource = Bitmap.createBitmap(reWidth, reHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resource);
canvas.drawColor(Color.BLUE);
canvas.concat(matrix);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(bitmap, (float) ((reWidth - width) * 1.0 / 2), (float) ((reHeight - height) * 1.0 / 2), paint);
if (isRecycle) destroyBitmap(bitmap);
return resource;
}
3.rotate
計(jì)算旋轉(zhuǎn)之后新圖的寬高续徽,這個(gè)還挺復(fù)雜的,之前查找了很多資料亲澡,最后還是問了底層的同事炸宵,搞到了一片描述這類問題的文章 【OpenCV】圖像幾何變換:旋轉(zhuǎn),縮放谷扣,斜切
文章里面關(guān)于的旋轉(zhuǎn)的數(shù)學(xué)模型如圖:
新圖的寬高則為(widthcos(a)+heightsin(a) , heightcos(a)+widthsin(a)) 這里 的 ‘a(chǎn)’ 指的是角度對應(yīng)的弧度哦土全!
/**
* 真實(shí)旋轉(zhuǎn),圖片寬高會根據(jù)圖片的旋轉(zhuǎn)角度重新生成寬高
*
* @param bitmap,目標(biāo)
* @param degree,旋轉(zhuǎn)角度
* @param isRecycle会涎,是否回收目標(biāo)圖
* @return
*/
public static Bitmap rotate(Bitmap bitmap, float degree, boolean isRecycle) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix matrix = new Matrix();
int reWidth, reHeight;
// 以弧度為計(jì)算方式則新圖size為(width*cos(a)+height*sin(a), height*cos(a)+width*sin(a))
double angle = (degree * Math.PI) / 180;//生成degree對應(yīng)的弧度
double a = Math.abs(Math.sin(angle)), b = Math.abs(Math.cos(angle));
reWidth = (int) (width * b + height * a);
reHeight = (int) (height * b + width * a);
Log.i(Tag, "width: " + width + " reWidth :" + reWidth);
Log.i(Tag, "height: " + height + " reHeight :" + reHeight);
Bitmap resource = Bitmap.createBitmap(reWidth, reHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resource);
canvas.drawColor(Color.BLACK);
matrix.postRotate(degree, reWidth / 2, reHeight / 2);
canvas.concat(matrix);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(bitmap, (float) ((reWidth - width) * 1.0 / 2), (float) ((reHeight - height) * 1.0 / 2), paint);
if (isRecycle) destroyBitmap(bitmap);
return resource;
}
效果如圖:
3.skew
額···這個(gè)還沒有寫的裹匙,這兩天坐火車做懵了,后期再補(bǔ)上來把末秃;如果有需要也可以參考 文章 《【OpenCV】圖像幾何變換:旋轉(zhuǎn)概页,縮放,斜切》中的 實(shí)踐:圖像放射變換(通過三點(diǎn)確定變換矩陣)
以上的demo地址: https://github.com/MartinBZDQSM/Matrix