歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android matrix 控制圖片的旋轉、縮放、移動

Android matrix 控制圖片的旋轉、縮放、移動

日期:2017/3/1 10:45:26   编辑:Linux編程

本文主要講解利用Android中Matrix控制圖形的旋轉縮放移動,具體參見一下代碼:

  1. /**
  2. * 使用矩陣控制圖片移動、縮放、旋轉
  3. * @author 張進
  4. */
  5. public class CommonImgEffectView extends View {
  6. private Context context ;
  7. private Bitmap mainBmp , controlBmp ;
  8. private int mainBmpWidth , mainBmpHeight , controlBmpWidth , controlBmpHeight ;
  9. private Matrix matrix ;
  10. private float [] srcPs , dstPs ;
  11. private RectF srcRect , dstRect ;
  12. private Paint paint ,paintRect , paintFrame;
  13. private float deltaX = 0, deltaY = 0; //位移值
  14. private float scaleValue = 1; //縮放值
  15. private Point lastPoint ;
  16. private Point prePivot , lastPivot;
  17. private float preDegree , lastDegree ;
  18. private short currentSelectedPointindex; //當前操作點擊點
  19. private Point symmetricPoint = new Point(); //當前操作點對稱點
  20. /**
  21. * 圖片操作類型
  22. */
  23. public static final int OPER_DEFAULT = -1; //默認
  24. public static final int OPER_TRANSLATE = 0; //移動
  25. public static final int OPER_SCALE = 1; //縮放
  26. public static final int OPER_ROTATE = 2; //旋轉
  27. public static final int OPER_SELECTED = 3; //選擇
  28. public int lastOper = OPER_DEFAULT;
  29. /* 圖片控制點
  30. * 0---1---2
  31. * | |
  32. * 7 8 3
  33. * | |
  34. * 6---5---4
  35. */
  36. public static final int CTR_NONE = -1;
  37. public static final int CTR_LEFT_TOP = 0;
  38. public static final int CTR_MID_TOP = 1;
  39. public static final int CTR_RIGHT_TOP = 2;
  40. public static final int CTR_RIGHT_MID = 3;
  41. public static final int CTR_RIGHT_BOTTOM = 4;
  42. public static final int CTR_MID_BOTTOM = 5;
  43. public static final int CTR_LEFT_BOTTOM = 6;
  44. public static final int CTR_LEFT_MID = 7;
  45. public static final int CTR_MID_MID = 8;
  46. public int current_ctr = CTR_NONE;
  47. public CommonImgEffectView(Context context){
  48. super(context);
  49. this.context = context ;
  50. }
  51. public CommonImgEffectView(Context context, AttributeSet attrs) {
  52. super(context, attrs);
  53. this.context = context ;
  54. initData();
  55. }
  56. /**
  57. * 初始化數據
  58. * @author 張進
  59. */
  60. private void initData(){
  61. mainBmp = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.flower);
  62. controlBmp = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.control);
  63. mainBmpWidth = mainBmp.getWidth();
  64. mainBmpHeight = mainBmp.getHeight();
  65. controlBmpWidth = controlBmp.getWidth();
  66. controlBmpHeight = controlBmp.getHeight();
  67. srcPs = new float[]{
  68. 0,0,
  69. mainBmpWidth/2,0,
  70. mainBmpWidth,0,
  71. mainBmpWidth,mainBmpHeight/2,
  72. mainBmpWidth,mainBmpHeight,
  73. mainBmpWidth/2,mainBmpHeight,
  74. 0,mainBmpHeight,
  75. 0,mainBmpHeight/2,
  76. mainBmpWidth/2,mainBmpHeight/2
  77. };
  78. dstPs = srcPs.clone();
  79. srcRect = new RectF(0, 0, mainBmpWidth, mainBmpHeight);
  80. dstRect = new RectF();
  81. matrix = new Matrix();
  82. prePivot = new Point(mainBmpWidth/2, mainBmpHeight/2);
  83. lastPivot = new Point(mainBmpWidth/2, mainBmpHeight/2);
  84. lastPoint = new Point(0,0);
  85. paint = new Paint();
  86. paintRect = new Paint();
  87. paintRect.setColor(Color.RED);
  88. paintRect.setAlpha(100);
  89. paintRect.setAntiAlias(true);
  90. paintFrame = new Paint();
  91. paintFrame.setColor(Color.GREEN);
  92. paintFrame.setAntiAlias(true);
  93. setMatrix(OPER_DEFAULT);
  94. }
  95. /**
  96. * 矩陣變換,達到圖形平移的目的
  97. * @author 張進
  98. */
  99. private void setMatrix(int operationType){
  100. switch (operationType) {
  101. case OPER_TRANSLATE:
  102. matrix.postTranslate(deltaX , deltaY);
  103. break;
  104. case OPER_SCALE:
  105. matrix.postScale(scaleValue, scaleValue, symmetricPoint.x, symmetricPoint.y);
  106. break;
  107. case OPER_ROTATE:
  108. matrix.postRotate(preDegree - lastDegree, dstPs[CTR_MID_MID * 2], dstPs[CTR_MID_MID * 2 + 1]);
  109. break;
  110. }
  111. matrix.mapPoints(dstPs, srcPs);
  112. matrix.mapRect(dstRect, srcRect);
  113. }
  114. private boolean isOnPic(int x , int y){
  115. if(dstRect.contains(x, y)){
  116. return true;
  117. }else
  118. return false;
  119. }
  120. private int getOperationType(MotionEvent event){
  121. int evX = (int)event.getX();
  122. int evY = (int)event.getY();
  123. int curOper = lastOper;
  124. switch(event.getAction()) {
  125. case MotionEvent.ACTION_DOWN:
  126. current_ctr = isOnCP(evX, evY);
  127. Log.i("img", "current_ctr is "+current_ctr);
  128. if(current_ctr != CTR_NONE || isOnPic(evX, evY)){
  129. curOper = OPER_SELECTED;
  130. }
  131. break;
  132. case MotionEvent.ACTION_MOVE:
  133. if(current_ctr > CTR_NONE && current_ctr < CTR_MID_MID ){
  134. curOper = OPER_SCALE;
  135. }else if(current_ctr == CTR_MID_MID ){
  136. curOper = OPER_ROTATE;
  137. }else if(lastOper == OPER_SELECTED){
  138. curOper = OPER_TRANSLATE;
  139. }
  140. break;
  141. case MotionEvent.ACTION_UP:
  142. curOper = OPER_SELECTED;
  143. break;
  144. default:
  145. break;
  146. }
  147. Log.d("img", "curOper is "+curOper);
  148. return curOper;
  149. }
  150. /**
  151. * 判斷點所在的控制點
  152. * @param evX
  153. * @param evY
  154. * @return
  155. */
  156. private int isOnCP(int evx, int evy) {
  157. Rect rect = new Rect(evx-controlBmpWidth/2,evy-controlBmpHeight/2,evx+controlBmpWidth/2,evy+controlBmpHeight/2);
  158. int res = 0 ;
  159. for (int i = 0; i < dstPs.length; i+=2) {
  160. if(rect.contains((int)dstPs[i], (int)dstPs[i+1])){
  161. return res ;
  162. }
  163. ++res ;
  164. }
  165. return CTR_NONE;
  166. }
  167. @Override
  168. public boolean dispatchTouchEvent(MotionEvent event) {
  169. int evX = (int)event.getX();
  170. int evY = (int)event.getY();
  171. int operType = OPER_DEFAULT;
  172. operType = getOperationType(event);
  173. switch (operType) {
  174. case OPER_TRANSLATE:
  175. translate(evX, evY);
  176. break;
  177. case OPER_SCALE:
  178. scale(event);
  179. break;
  180. case OPER_ROTATE:
  181. rotate(event);
  182. break;
  183. }
  184. lastPoint.x = evX;
  185. lastPoint.y = evY;
  186. lastOper = operType;
  187. invalidate();//重繪
  188. return true;
  189. }
  190. /**
  191. * 移動
  192. * @param evx
  193. * @param evy
  194. * @author zhang_jin1
  195. */
  196. private void translate(int evx , int evy){
  197. prePivot.x += evx - lastPoint.x;
  198. prePivot.y += evy -lastPoint.y;
  199. deltaX = prePivot.x - lastPivot.x;
  200. deltaY = prePivot.y - lastPivot.y;
  201. lastPivot.x = prePivot.x;
  202. lastPivot.y = prePivot.y;
  203. setMatrix(OPER_TRANSLATE); //設置矩陣
  204. }
  205. /**
  206. * 縮放
  207. * 0---1---2
  208. * | |
  209. * 7 8 3
  210. * | |
  211. * 6---5---4
  212. * @param evX
  213. * @param evY
  214. */
  215. private void scale(MotionEvent event) {
  216. int pointIndex = current_ctr*2 ;
  217. float px = dstPs[pointIndex];
  218. float py = dstPs[pointIndex+1];
  219. float evx = event.getX();
  220. float evy = event.getY();
  221. float oppositeX = 0 ;
  222. float oppositeY = 0 ;
  223. if(current_ctr<4 && current_ctr >= 0){
  224. oppositeX = dstPs[pointIndex+8];
  225. oppositeY = dstPs[pointIndex+9];
  226. }else if(current_ctr >= 4){
  227. oppositeX = dstPs[pointIndex-8];
  228. oppositeY = dstPs[pointIndex-7];
  229. }
  230. float temp1 = getDistanceOfTwoPoints(px,py,oppositeX,oppositeY);
  231. float temp2 = getDistanceOfTwoPoints(evx,evy,oppositeX,oppositeY);
  232. this.scaleValue = temp2 / temp1 ;
  233. symmetricPoint.x = (int) oppositeX;
  234. symmetricPoint.y = (int)oppositeY;
  235. Log.i("img", "scaleValue is "+scaleValue);
  236. setMatrix(OPER_SCALE);
  237. }
  238. /**
  239. * 旋轉圖片
  240. * 0---1---2
  241. * | |
  242. * 7 8 3
  243. * | |
  244. * 6---5---4
  245. * @param evX
  246. * @param evY
  247. */
  248. private void rotate(MotionEvent event) {
  249. if(event.getPointerCount() == 2){
  250. preDegree = computeDegree(new Point((int)event.getX(0), (int)event.getY(0)), new Point((int)event.getX(1), (int)event.getY(1)));
  251. }else{
  252. preDegree = computeDegree(new Point((int)event.getX(), (int)event.getY()), new Point((int)dstPs[16], (int)dstPs[17]));
  253. }
  254. setMatrix(OPER_ROTATE);
  255. lastDegree = preDegree;
  256. }
  257. /**
  258. * 計算兩點與垂直方向夾角
  259. * @param p1
  260. * @param p2
  261. * @return
  262. */
  263. public float computeDegree(Point p1, Point p2){
  264. float tran_x = p1.x - p2.x;
  265. float tran_y = p1.y - p2.y;
  266. float degree = 0.0f;
  267. float angle = (float)(Math.asin(tran_x/Math.sqrt(tran_x*tran_x + tran_y* tran_y))*180/Math.PI);
  268. if(!Float.isNaN(angle)){
  269. if(tran_x >= 0 && tran_y <= 0){//第一象限
  270. degree = angle;
  271. }else if(tran_x <= 0 && tran_y <= 0){//第二象限
  272. degree = angle;
  273. }else if(tran_x <= 0 && tran_y >= 0){//第三象限
  274. degree = -180 - angle;
  275. }else if(tran_x >= 0 && tran_y >= 0){//第四象限
  276. degree = 180 - angle;
  277. }
  278. }
  279. return degree;
  280. }
  281. /**
  282. * 計算兩個點之間的距離
  283. * @param p1
  284. * @param p2
  285. * @return
  286. */
  287. private float getDistanceOfTwoPoints(Point p1, Point p2){
  288. return (float)(Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));
  289. }
  290. private float getDistanceOfTwoPoints(float x1,float y1,float x2,float y2){
  291. return (float)(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
  292. }
  293. @Override
  294. public void onDraw(Canvas canvas){
  295. drawBackground(canvas);//繪制背景,以便測試矩形的映射
  296. canvas.drawBitmap(mainBmp, matrix, paint);//繪制主圖片
  297. drawFrame(canvas);//繪制邊框,以便測試點的映射
  298. drawControlPoints(canvas);//繪制控制點圖片
  299. }
  300. private void drawBackground(Canvas canvas){
  301. canvas.drawRect(dstRect, paintRect);
  302. }
  303. private void drawFrame(Canvas canvas){
  304. canvas.drawLine(dstPs[0], dstPs[1], dstPs[4], dstPs[5], paintFrame);
  305. canvas.drawLine(dstPs[4], dstPs[5], dstPs[8], dstPs[9], paintFrame);
  306. canvas.drawLine(dstPs[8], dstPs[9], dstPs[12], dstPs[13], paintFrame);
  307. canvas.drawLine(dstPs[0], dstPs[1], dstPs[12], dstPs[13], paintFrame);
  308. canvas.drawPoint(dstPs[16], dstPs[17], paintFrame);
  309. }
  310. private void drawControlPoints(Canvas canvas){
  311. for (int i = 0; i < dstPs.length; i+=2) {
  312. canvas.drawBitmap(controlBmp, dstPs[i]-controlBmpWidth/2, dstPs[i+1]-controlBmpHeight/2, paint);
  313. }
  314. }
  315. }

Demo效果:


Copyright © Linux教程網 All Rights Reserved