Android matrix 控制图片的旋转、缩放、移动

来源:互联网 发布:机房网络拓扑 编辑:程序博客网 时间:2024/06/11 01:20
[java] view plain copy
  1. /**  
  2.  * 使用矩阵控制图片移动、缩放、旋转  
  3.  */    
  4. public class CommonImgEffectView extends View {    
  5.     private Context context ;    
  6.     private Bitmap mainBmp , controlBmp ;    
  7.     private int mainBmpWidth , mainBmpHeight , controlBmpWidth , controlBmpHeight ;    
  8.     private Matrix matrix ;     
  9.     private float [] srcPs , dstPs ;    
  10.     private RectF srcRect , dstRect ;    
  11.     private Paint paint ,paintRect , paintFrame;    
  12.     private float deltaX = 0, deltaY = 0//位移值    
  13.     private float scaleValue = 1//缩放值    
  14.     private Point lastPoint ;    
  15.     private Point prePivot , lastPivot;    
  16.     private float preDegree , lastDegree ;    
  17.     private short currentSelectedPointindex;        //当前操作点击点    
  18.     private Point symmetricPoint  = new Point();    //当前操作点对称点    
  19.         
  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.     /* 图片控制点  
  31.      * 0---1---2  
  32.      * |       |  
  33.      * 7   8   3  
  34.      * |       |  
  35.      * 6---5---4   
  36.      */    
  37.     public static final int CTR_NONE = -1;    
  38.     public static final int CTR_LEFT_TOP = 0;    
  39.     public static final int CTR_MID_TOP = 1;    
  40.     public static final int CTR_RIGHT_TOP = 2;    
  41.     public static final int CTR_RIGHT_MID = 3;    
  42.     public static final int CTR_RIGHT_BOTTOM = 4;    
  43.     public static final int CTR_MID_BOTTOM = 5;    
  44.     public static final int CTR_LEFT_BOTTOM = 6;    
  45.     public static final int CTR_LEFT_MID = 7;    
  46.     public static final int CTR_MID_MID = 8;    
  47.     public int current_ctr = CTR_NONE;    
  48.         
  49.     public CommonImgEffectView(Context context){    
  50.         super(context);    
  51.         this.context = context ;    
  52.         initData();    
  53.     }    
  54.         
  55.     public CommonImgEffectView(Context context, AttributeSet attrs) {    
  56.         super(context, attrs);    
  57.         this.context = context ;    
  58.         initData();    
  59.     }    
  60.         
  61.     /**  
  62.      * 初始化数据  
  63.      * @author 张进  
  64.      */    
  65.     private void initData(){    
  66.         mainBmp = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.flower);    
  67.         controlBmp = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.control);    
  68.         mainBmpWidth = mainBmp.getWidth();    
  69.         mainBmpHeight = mainBmp.getHeight();    
  70.         controlBmpWidth = controlBmp.getWidth();    
  71.         controlBmpHeight = controlBmp.getHeight();    
  72.             
  73.         srcPs = new float[]{    
  74.                                 0,0,     
  75.                                 mainBmpWidth/2,0,     
  76.                                 mainBmpWidth,0,     
  77.                                 mainBmpWidth,mainBmpHeight/2,    
  78.                                 mainBmpWidth,mainBmpHeight,     
  79.                                 mainBmpWidth/2,mainBmpHeight,     
  80.                                 0,mainBmpHeight,     
  81.                                 0,mainBmpHeight/2,     
  82.                                 mainBmpWidth/2,mainBmpHeight/2    
  83.                             };    
  84.         dstPs = srcPs.clone();    
  85.         srcRect = new RectF(00, mainBmpWidth, mainBmpHeight);    
  86.         dstRect = new RectF();    
  87.             
  88.         matrix = new Matrix();    
  89.             
  90.         prePivot = new Point(mainBmpWidth/2, mainBmpHeight/2);    
  91.         lastPivot = new Point(mainBmpWidth/2, mainBmpHeight/2);    
  92.             
  93.         lastPoint = new Point(0,0);    
  94.             
  95.         paint = new Paint();    
  96.             
  97.         paintRect = new Paint();    
  98.         paintRect.setColor(Color.RED);    
  99.         paintRect.setAlpha(100);    
  100.         paintRect.setAntiAlias(true);    
  101.             
  102.         paintFrame = new Paint();    
  103.         paintFrame.setColor(Color.GREEN);    
  104.         paintFrame.setAntiAlias(true);    
  105.             
  106.         setMatrix(OPER_DEFAULT);    
  107.     }    
  108.         
  109.     /**  
  110.      * 矩阵变换,达到图形平移的目的  
  111.      * @author 张进  
  112.      */    
  113.     private void setMatrix(int operationType){    
  114.         switch (operationType) {    
  115.         case OPER_TRANSLATE:    
  116.             matrix.postTranslate(deltaX , deltaY);    
  117.             break;    
  118.         case OPER_SCALE:    
  119.             matrix.postScale(scaleValue, scaleValue, symmetricPoint.x, symmetricPoint.y);    
  120.             break;    
  121.         case OPER_ROTATE:    
  122.             matrix.postRotate(preDegree - lastDegree, dstPs[CTR_MID_MID * 2], dstPs[CTR_MID_MID * 2 + 1]);    
  123.             break;    
  124.         }    
  125.             
  126.         matrix.mapPoints(dstPs, srcPs);    
  127.         matrix.mapRect(dstRect, srcRect);    
  128.     }    
  129.         
  130.     private boolean isOnPic(int x , int y){    
  131.         if(dstRect.contains(x, y)){    
  132.             return true;    
  133.         }else     
  134.             return false;    
  135.     }    
  136.         
  137.     private int getOperationType(MotionEvent event){    
  138.     
  139.         int evX = (int)event.getX();    
  140.         int evY = (int)event.getY();    
  141.         int curOper = lastOper;    
  142.         switch(event.getAction()) {    
  143.             case MotionEvent.ACTION_DOWN:    
  144.                 current_ctr = isOnCP(evX, evY);    
  145.                 Log.i("img""current_ctr is "+current_ctr);    
  146.                 if(current_ctr != CTR_NONE || isOnPic(evX, evY)){    
  147.                     curOper = OPER_SELECTED;    
  148.                 }    
  149.                 break;    
  150.             case MotionEvent.ACTION_MOVE:    
  151.                     if(current_ctr > CTR_NONE && current_ctr < CTR_MID_MID ){    
  152.                         curOper = OPER_SCALE;    
  153.                     }else if(current_ctr == CTR_MID_MID ){    
  154.                         curOper = OPER_ROTATE;    
  155.                     }else if(lastOper == OPER_SELECTED){    
  156.                         curOper = OPER_TRANSLATE;    
  157.                     }    
  158.                 break;    
  159.             case MotionEvent.ACTION_UP:    
  160.                 curOper = OPER_SELECTED;    
  161.                 break;    
  162.             default:    
  163.                 break;    
  164.         }    
  165.         Log.d("img""curOper is "+curOper);    
  166.         return curOper;    
  167.             
  168.     }    
  169.         
  170.      /**  
  171.      * 判断点所在的控制点  
  172.      * @param evX  
  173.      * @param evY  
  174.      * @return  
  175.      */     
  176.     private int isOnCP(int evx, int evy) {    
  177.         Rect rect = new Rect(evx-controlBmpWidth/2,evy-controlBmpHeight/2,evx+controlBmpWidth/2,evy+controlBmpHeight/2);    
  178.         int res = 0 ;    
  179.         for (int i = 0; i < dstPs.length; i+=2) {    
  180.             if(rect.contains((int)dstPs[i], (int)dstPs[i+1])){    
  181.                 return res ;    
  182.             }    
  183.             ++res ;     
  184.         }    
  185.         return CTR_NONE;    
  186.     }    
  187.         
  188.         
  189.         
  190.     @Override    
  191.     public boolean dispatchTouchEvent(MotionEvent event) {    
  192.         int evX = (int)event.getX();    
  193.         int evY = (int)event.getY();    
  194.             
  195.         int operType = OPER_DEFAULT;    
  196.         operType = getOperationType(event);    
  197.             
  198.         switch (operType) {    
  199.         case OPER_TRANSLATE:    
  200.             translate(evX, evY);    
  201.             break;    
  202.         case OPER_SCALE:    
  203.             scale(event);    
  204.             break;    
  205.         case OPER_ROTATE:    
  206.             rotate(event);    
  207.             break;    
  208.         }    
  209.         
  210.         lastPoint.x = evX;    
  211.         lastPoint.y = evY;      
  212.             
  213.         lastOper = operType;    
  214.         invalidate();//重绘    
  215.         return true;    
  216.     }    
  217.     
  218.     /**  
  219.      * 移动  
  220.      * @param evx  
  221.      * @param evy  
  222.      * @author zhang_jin1  
  223.      */    
  224.     private void translate(int evx , int evy){    
  225.             
  226.         prePivot.x += evx - lastPoint.x;    
  227.         prePivot.y += evy -lastPoint.y;    
  228.             
  229.         deltaX = prePivot.x - lastPivot.x;    
  230.         deltaY = prePivot.y - lastPivot.y;    
  231.             
  232.         lastPivot.x = prePivot.x;    
  233.         lastPivot.y = prePivot.y;    
  234.             
  235.         setMatrix(OPER_TRANSLATE); //设置矩阵    
  236.             
  237.     }    
  238.         
  239.     /**  
  240.      * 缩放  
  241.      * 0---1---2  
  242.      * |       |  
  243.      * 7   8   3  
  244.      * |       |  
  245.      * 6---5---4  
  246.      * @param evX  
  247.      * @param evY  
  248.      */    
  249.     private void scale(MotionEvent event) {    
  250.             
  251.         int pointIndex = current_ctr*2 ;    
  252.             
  253.         float px = dstPs[pointIndex];    
  254.         float py = dstPs[pointIndex+1];    
  255.             
  256.         float evx = event.getX();    
  257.         float evy = event.getY();    
  258.             
  259.         float oppositeX = 0 ;    
  260.         float oppositeY = 0 ;    
  261.         if(current_ctr<4 && current_ctr >= 0){    
  262.              oppositeX = dstPs[pointIndex+8];    
  263.              oppositeY = dstPs[pointIndex+9];    
  264.         }else if(current_ctr >= 4){    
  265.              oppositeX = dstPs[pointIndex-8];    
  266.              oppositeY = dstPs[pointIndex-7];    
  267.         }    
  268.         float temp1 = getDistanceOfTwoPoints(px,py,oppositeX,oppositeY);    
  269.         float temp2 = getDistanceOfTwoPoints(evx,evy,oppositeX,oppositeY);    
  270.             
  271.         this.scaleValue = temp2 / temp1 ;    
  272.         symmetricPoint.x = (int) oppositeX;    
  273.         symmetricPoint.y = (int)oppositeY;    
  274.             
  275.         Log.i("img""scaleValue is "+scaleValue);    
  276.         setMatrix(OPER_SCALE);    
  277.     }    
  278.         
  279.     /**  
  280.      * 旋转图片  
  281.      * 0---1---2  
  282.      * |       |  
  283.      * 7   8   3  
  284.      * |       |  
  285.      * 6---5---4   
  286.      * @param evX  
  287.      * @param evY  
  288.      */    
  289.     private void rotate(MotionEvent event) {    
  290.            
  291.         if(event.getPointerCount() == 2){    
  292.             preDegree = computeDegree(new Point((int)event.getX(0), (int)event.getY(0)), new Point((int)event.getX(1), (int)event.getY(1)));    
  293.         }else{    
  294.             preDegree = computeDegree(new Point((int)event.getX(), (int)event.getY()), new Point((int)dstPs[16], (int)dstPs[17]));    
  295.         }    
  296.         setMatrix(OPER_ROTATE);    
  297.         lastDegree = preDegree;    
  298.     }    
  299.         
  300.         
  301.     /**  
  302.      * 计算两点与垂直方向夹角  
  303.      * @param p1  
  304.      * @param p2  
  305.      * @return  
  306.      */    
  307.     public float computeDegree(Point p1, Point p2){    
  308.         float tran_x = p1.x - p2.x;    
  309.         float tran_y = p1.y - p2.y;    
  310.         float degree = 0.0f;    
  311.         float angle = (float)(Math.asin(tran_x/Math.sqrt(tran_x*tran_x + tran_y* tran_y))*180/Math.PI);    
  312.         if(!Float.isNaN(angle)){    
  313.             if(tran_x >= 0 && tran_y <= 0){//第一象限    
  314.                 degree = angle;    
  315.             }else if(tran_x <= 0 && tran_y <= 0){//第二象限    
  316.                 degree = angle;    
  317.             }else if(tran_x <= 0 && tran_y >= 0){//第三象限    
  318.                 degree = -180 - angle;    
  319.             }else if(tran_x >= 0 && tran_y >= 0){//第四象限    
  320.                 degree = 180 - angle;    
  321.             }    
  322.         }    
  323.         return degree;    
  324.     }    
  325.         
  326.     /**  
  327.      * 计算两个点之间的距离  
  328.      * @param p1  
  329.      * @param p2  
  330.      * @return  
  331.      */    
  332.     private float getDistanceOfTwoPoints(Point p1, Point p2){    
  333.         return (float)(Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));    
  334.     }    
  335.         
  336.     private float getDistanceOfTwoPoints(float x1,float y1,float x2,float y2){    
  337.         return (float)(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));    
  338.     }    
  339.         
  340.         
  341.     @Override    
  342.     public void onDraw(Canvas canvas){    
  343.         drawBackground(canvas);//绘制背景,以便测试矩形的映射    
  344.         canvas.drawBitmap(mainBmp, matrix, paint);//绘制主图片    
  345.         drawFrame(canvas);//绘制边框,以便测试点的映射    
  346.         drawControlPoints(canvas);//绘制控制点图片    
  347.     }    
  348.         
  349.     private void drawBackground(Canvas canvas){    
  350.         canvas.drawRect(dstRect, paintRect);    
  351.     }    
  352.         
  353.     private void drawFrame(Canvas canvas){    
  354.         canvas.drawLine(dstPs[0], dstPs[1], dstPs[4], dstPs[5], paintFrame);    
  355.         canvas.drawLine(dstPs[4], dstPs[5], dstPs[8], dstPs[9], paintFrame);    
  356.         canvas.drawLine(dstPs[8], dstPs[9], dstPs[12], dstPs[13], paintFrame);    
  357.         canvas.drawLine(dstPs[0], dstPs[1], dstPs[12], dstPs[13], paintFrame);    
  358.         canvas.drawPoint(dstPs[16], dstPs[17], paintFrame);    
  359.     }    
  360.         
  361.     private void drawControlPoints(Canvas canvas){    
  362.             
  363.         for (int i = 0; i < dstPs.length; i+=2) {    
  364.             canvas.drawBitmap(controlBmp, dstPs[i]-controlBmpWidth/2, dstPs[i+1]-controlBmpHeight/2, paint);    
  365.         }    
  366.             
  367.     }    
0 0
原创粉丝点击