在Android中,对图片的处理需要使用到Matrix类,Matrix是一个3 x 3的矩阵,他对图片的处理分为四个基本类型:

1、Translate————平移变换

2、Scale————缩放变换

3、Rotate————旋转变换

4、Skew————错切变换

在Android的API里对于每一种变换都提供了三种操作方式:set(用于设置Matrix中的值)、post(后乘,根据矩阵的原理,相当于左乘)、pre(先乘,相当于矩阵中的右乘)。默认时,这四种变换都是围绕(0,0)点变换的,当然可以自定义围绕的中心点,通常围绕中心点。

首先说说平移,在对图片处理的过程中,最常用的就是对图片进行平移操作,该方法为setTranslate(),平移意味着在x轴和y轴上简单地移动图像。setTranslate方法采用两个浮点数作为参数,表示在每个轴上移动的数量。第一个参数是图像将在x轴上移动的数量,而第二个参数是图像将在y轴上移动的数量。在x轴上使用正数进行平移将向右移动图像,而使用负数将向左移动图像。在y轴上使用正数进行平移将向下移动图像,而使用负数将向上移动图像。

再看缩放,Matrix类中另一个有用的方法是setScale方法。它采用两个浮点数作为参数,分别表示在每个轴上所产生的缩放量。第一个参数是x轴的缩放比例,而第二个参数是y轴的缩放比例。如:matrix.setScale(1.5f,1);
比较复杂的就是图片的旋转了,内置的方法之一是setRotate方法。它采用一个浮点数表示旋转的角度。围绕默认点(0,0),正数将顺时针旋转图像,而负数将逆时针旋转图像,其中默认点是图像的左上角,如:

Matrix matrix = new Matrix();
matrix.setRotate(15);

另外,也可以使用旋转的角度及围绕的旋转点作为参数调用setRotate方法。选择图像的中心点作为旋转点,如:
matrix.setRotate(15,bmp.getWidth()/2,bmp.getHeight()/2);

对于错切变换,在数学上又称为Shear mapping(可译为“剪切变换”)或者Transvection(缩并),它是一种比较特殊的线性变换。错切变换的效果就是让所有点的x坐标(或者y坐标)保持不变,而对应的y坐标(或者x坐标)则按比例发生平移,且平移的大小和该点到x轴(或y轴)的垂直距离成正比。错切变换,属于等面积变换,即一个形状在错切变换的前后,其面积是相等的。

对于程序中,一个特别有用的方法对是setScale和postTranslate,它们允许跨单个轴(或者两个轴)翻转图像。如果以一个负数缩放,那么会将该图像绘制到坐标系统的负值空间。由于(0,0)点位于左上角,使用x轴上的负数会导致向左绘制图像。因此我们需要使用postTranslate方法,将图像向右移动,如:

matrix.setScale(-1, 1);
matrix.postTranslate(bmp.getWidth(),0);

可以在y轴上做同样的事情,翻转图像以使其倒置。通过将图像围绕两个轴上的中心点旋转180°,可以实现相同的效果,如
matrix.setScale(1, -1);
matrix.postTranslate(0, bmp.getHeight());


下面是对Android中利用matrix 控制图片的旋转、缩放、移动进行了详细的分析介绍,需要的朋友参考下

本文主要讲解利用android中Matrix控制图形的旋转缩放移动

/**  * 使用矩阵控制图片移动、缩放、旋转  */  public class CommonImgEffectView extends View {      private Context context ;      private Bitmap mainBmp , controlBmp ;      private int mainBmpWidth , mainBmpHeight , controlBmpWidth , controlBmpHeight ;      private Matrix matrix ;       private float [] srcPs , dstPs ;      private RectF srcRect , dstRect ;      private Paint paint ,paintRect , paintFrame;      private float deltaX = 0, deltaY = 0; //位移值      private float scaleValue = 1; //缩放值      private Point lastPoint ;      private Point prePivot , lastPivot;      private float preDegree , lastDegree ;      private short currentSelectedPointindex;        //当前操作点击点      private Point symmetricPoint  = new Point();    //当前操作点对称点      /**      * 图片操作类型      */      public static final int OPER_DEFAULT = -1;      //默认      public static final int OPER_TRANSLATE = 0;     //移动      public static final int OPER_SCALE = 1;         //缩放      public static final int OPER_ROTATE = 2;        //旋转      public static final int OPER_SELECTED = 3;      //选择      public int lastOper = OPER_DEFAULT;      /* 图片控制点      * 0---1---2      * |       |      * 7   8   3      * |       |      * 6---5---4       */      public static final int CTR_NONE = -1;      public static final int CTR_LEFT_TOP = 0;      public static final int CTR_MID_TOP = 1;      public static final int CTR_RIGHT_TOP = 2;      public static final int CTR_RIGHT_MID = 3;      public static final int CTR_RIGHT_BOTTOM = 4;      public static final int CTR_MID_BOTTOM = 5;      public static final int CTR_LEFT_BOTTOM = 6;      public static final int CTR_LEFT_MID = 7;      public static final int CTR_MID_MID = 8;      public int current_ctr = CTR_NONE;      public CommonImgEffectView(Context context){          super(context);          this.context = context ;      }      public CommonImgEffectView(Context context, AttributeSet attrs) {          super(context, attrs);          this.context = context ;          initData();      }      /**      * 初始化数据      * @author 张进      */      private void initData(){          mainBmp = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.flower);          controlBmp = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.control);          mainBmpWidth = mainBmp.getWidth();          mainBmpHeight = mainBmp.getHeight();          controlBmpWidth = controlBmp.getWidth();          controlBmpHeight = controlBmp.getHeight();          srcPs = new float[]{                                  0,0,                                   mainBmpWidth/2,0,                                   mainBmpWidth,0,                                   mainBmpWidth,mainBmpHeight/2,                                  mainBmpWidth,mainBmpHeight,                                   mainBmpWidth/2,mainBmpHeight,                                   0,mainBmpHeight,                                   0,mainBmpHeight/2,                                   mainBmpWidth/2,mainBmpHeight/2                              };          dstPs = srcPs.clone();          srcRect = new RectF(0, 0, mainBmpWidth, mainBmpHeight);          dstRect = new RectF();          matrix = new Matrix();          prePivot = new Point(mainBmpWidth/2, mainBmpHeight/2);          lastPivot = new Point(mainBmpWidth/2, mainBmpHeight/2);          lastPoint = new Point(0,0);          paint = new Paint();          paintRect = new Paint();          paintRect.setColor(Color.RED);          paintRect.setAlpha(100);          paintRect.setAntiAlias(true);          paintFrame = new Paint();          paintFrame.setColor(Color.GREEN);          paintFrame.setAntiAlias(true);          setMatrix(OPER_DEFAULT);      }      /**      * 矩阵变换,达到图形平移的目的      * @author 张进      */      private void setMatrix(int operationType){          switch (operationType) {          case OPER_TRANSLATE:              matrix.postTranslate(deltaX , deltaY);              break;          case OPER_SCALE:              matrix.postScale(scaleValue, scaleValue, symmetricPoint.x, symmetricPoint.y);              break;          case OPER_ROTATE:              matrix.postRotate(preDegree - lastDegree, dstPs[CTR_MID_MID * 2], dstPs[CTR_MID_MID * 2 + 1]);              break;          }          matrix.mapPoints(dstPs, srcPs);          matrix.mapRect(dstRect, srcRect);      }      private boolean isOnPic(int x , int y){          if(dstRect.contains(x, y)){              return true;          }else               return false;      }      private int getOperationType(MotionEvent event){          int evX = (int)event.getX();          int evY = (int)event.getY();          int curOper = lastOper;          switch(event.getAction()) {              case MotionEvent.ACTION_DOWN:                  current_ctr = isOnCP(evX, evY);                  Log.i("img", "current_ctr is "+current_ctr);                  if(current_ctr != CTR_NONE || isOnPic(evX, evY)){                      curOper = OPER_SELECTED;                  }                  break;              case MotionEvent.ACTION_MOVE:                      if(current_ctr > CTR_NONE && current_ctr < CTR_MID_MID ){                          curOper = OPER_SCALE;                      }else if(current_ctr == CTR_MID_MID ){                          curOper = OPER_ROTATE;                      }else if(lastOper == OPER_SELECTED){                          curOper = OPER_TRANSLATE;                      }                  break;              case MotionEvent.ACTION_UP:                  curOper = OPER_SELECTED;                  break;              default:                  break;          }          Log.d("img", "curOper is "+curOper);          return curOper;      }       /**      * 判断点所在的控制点      * @param evX      * @param evY      * @return      */       private int isOnCP(int evx, int evy) {          Rect rect = new Rect(evx-controlBmpWidth/2,evy-controlBmpHeight/2,evx+controlBmpWidth/2,evy+controlBmpHeight/2);          int res = 0 ;          for (int i = 0; i < dstPs.length; i+=2) {              if(rect.contains((int)dstPs[i], (int)dstPs[i+1])){                  return res ;              }              ++res ;           }          return CTR_NONE;      }            @Override      public boolean dispatchTouchEvent(MotionEvent event) {          int evX = (int)event.getX();          int evY = (int)event.getY();          int operType = OPER_DEFAULT;          operType = getOperationType(event);          switch (operType) {          case OPER_TRANSLATE:              translate(evX, evY);              break;          case OPER_SCALE:              scale(event);              break;          case OPER_ROTATE:              rotate(event);              break;          }          lastPoint.x = evX;          lastPoint.y = evY;            lastOper = operType;          invalidate();//重绘          return true;      }      /**      * 移动      * @param evx      * @param evy      * @author zhang_jin1      */      private void translate(int evx , int evy){          prePivot.x += evx - lastPoint.x;          prePivot.y += evy -lastPoint.y;          deltaX = prePivot.x - lastPivot.x;          deltaY = prePivot.y - lastPivot.y;          lastPivot.x = prePivot.x;          lastPivot.y = prePivot.y;          setMatrix(OPER_TRANSLATE); //设置矩阵      }      /**      * 缩放      * 0---1---2      * |       |      * 7   8   3      * |       |      * 6---5---4      * @param evX      * @param evY      */      private void scale(MotionEvent event) {          int pointIndex = current_ctr*2 ;          float px = dstPs[pointIndex];          float py = dstPs[pointIndex+1];          float evx = event.getX();          float evy = event.getY();          float oppositeX = 0 ;          float oppositeY = 0 ;          if(current_ctr<4 && current_ctr >= 0){               oppositeX = dstPs[pointIndex+8];               oppositeY = dstPs[pointIndex+9];          }else if(current_ctr >= 4){               oppositeX = dstPs[pointIndex-8];               oppositeY = dstPs[pointIndex-7];          }          float temp1 = getDistanceOfTwoPoints(px,py,oppositeX,oppositeY);          float temp2 = getDistanceOfTwoPoints(evx,evy,oppositeX,oppositeY);          this.scaleValue = temp2 / temp1 ;          symmetricPoint.x = (int) oppositeX;          symmetricPoint.y = (int)oppositeY;          Log.i("img", "scaleValue is "+scaleValue);          setMatrix(OPER_SCALE);      }      /**      * 旋转图片      * 0---1---2      * |       |      * 7   8   3      * |       |      * 6---5---4       * @param evX      * @param evY      */      private void rotate(MotionEvent event) {          if(event.getPointerCount() == 2){              preDegree = computeDegree(new Point((int)event.getX(0), (int)event.getY(0)), new Point((int)event.getX(1), (int)event.getY(1)));          }else{              preDegree = computeDegree(new Point((int)event.getX(), (int)event.getY()), new Point((int)dstPs[16], (int)dstPs[17]));          }          setMatrix(OPER_ROTATE);          lastDegree = preDegree;      }            /**      * 计算两点与垂直方向夹角      * @param p1      * @param p2      * @return      */      public float computeDegree(Point p1, Point p2){          float tran_x = p1.x - p2.x;          float tran_y = p1.y - p2.y;          float degree = 0.0f;          float angle = (float)(Math.asin(tran_x/Math.sqrt(tran_x*tran_x + tran_y* tran_y))*180/Math.PI);          if(!Float.isNaN(angle)){              if(tran_x >= 0 && tran_y <= 0){//第一象限                  degree = angle;              }else if(tran_x <= 0 && tran_y <= 0){//第二象限                  degree = angle;              }else if(tran_x <= 0 && tran_y >= 0){//第三象限                  degree = -180 - angle;              }else if(tran_x >= 0 && tran_y >= 0){//第四象限                  degree = 180 - angle;              }          }          return degree;      }      /**      * 计算两个点之间的距离      * @param p1      * @param p2      * @return      */      private float getDistanceOfTwoPoints(Point p1, Point p2){          return (float)(Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));      }      private float getDistanceOfTwoPoints(float x1,float y1,float x2,float y2){          return (float)(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));      }            @Override      public void onDraw(Canvas canvas){          drawBackground(canvas);//绘制背景,以便测试矩形的映射          canvas.drawBitmap(mainBmp, matrix, paint);//绘制主图片          drawFrame(canvas);//绘制边框,以便测试点的映射          drawControlPoints(canvas);//绘制控制点图片      }      private void drawBackground(Canvas canvas){          canvas.drawRect(dstRect, paintRect);      }      private void drawFrame(Canvas canvas){          canvas.drawLine(dstPs[0], dstPs[1], dstPs[4], dstPs[5], paintFrame);          canvas.drawLine(dstPs[4], dstPs[5], dstPs[8], dstPs[9], paintFrame);          canvas.drawLine(dstPs[8], dstPs[9], dstPs[12], dstPs[13], paintFrame);          canvas.drawLine(dstPs[0], dstPs[1], dstPs[12], dstPs[13], paintFrame);          canvas.drawPoint(dstPs[16], dstPs[17], paintFrame);      }      private void drawControlPoints(Canvas canvas){          for (int i = 0; i < dstPs.length; i+=2) {              canvas.drawBitmap(controlBmp, dstPs[i]-controlBmpWidth/2, dstPs[i+1]-controlBmpHeight/2, paint);          }      }  }  
Demo效果:






更多相关文章

  1. Android(安卓)matrix 控制图片的旋转、缩放、移动
  2. Android异步加载图像小结 (含线程池,缓存方法)
  3. android WebView 图片缩放功能小结
  4. android camera(一):camera模组CMM介绍
  5. android从服务器下载文件(php+apache+win7+MySql)
  6. android camera(一):camera模组CMM介绍
  7. android图像处理系统1.3
  8. android使用inSampleSize、inScaled、inDensity、inTargetDensit
  9. Android(安卓)webview记住账号密码

随机推荐

  1. android loggin
  2. Android读写XML(下)——创建XML文档
  3. Android应用开发学习笔记之播放音频
  4. 在Android中加入GOOGLE统计系统
  5. android textview 中超出屏幕宽度的字符
  6. Delphi XE5的Android开发平台搭建
  7. android命令行启动
  8. android启动界面说明
  9. Android(安卓)TabHost学习笔记
  10. Android(安卓)Data Binder 的一个bug