亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

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

2020-04-11 12:08:31
字體:
來源:轉載
供稿:網友
本文主要講解利用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效果:


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产成人综合精品在线| 最近更新的2019中文字幕| 亚洲第一福利在线观看| 国产视频福利一区| 欧美丝袜美女中出在线| 亚洲自拍偷拍在线| 中文字幕在线亚洲| www.欧美精品一二三区| 亚洲视频一区二区三区| 欧美激情精品久久久久久久变态| 国产成人一区二区三区小说| 97国产一区二区精品久久呦| 欧美精品video| 95av在线视频| 亚洲免费av网址| 欧美在线视频一二三| 欧美一级免费视频| 亚洲国产97在线精品一区| 91精品国产综合久久香蕉最新版| 国产97在线|亚洲| 亚洲高清一二三区| 国产精品高潮呻吟久久av无限| 欧美精品日韩www.p站| 日韩在线播放视频| 久久久久久久色| 91精品视频免费看| 色999日韩欧美国产| 欧美成人午夜激情| 69av视频在线播放| 欧美日韩性视频在线| 欧美国产日本高清在线| 欧美精品久久久久久久久久| 国产91|九色| 成人免费看吃奶视频网站| 亚洲开心激情网| 欧美一区二区三区精品电影| 全亚洲最色的网站在线观看| 色噜噜狠狠狠综合曰曰曰88av| 午夜精品久久久久久久99热| 国产自摸综合网| 日本高清不卡在线| 久久久久久亚洲精品| 欧美日韩裸体免费视频| 91九色视频在线| 欧美日韩国产页| 国产精品成人在线| 国产女同一区二区| 日韩在线视频二区| 久久久久久久久久久免费| 国产精品自拍偷拍| 亚洲国产天堂网精品网站| 亚洲iv一区二区三区| 日韩中文有码在线视频| 韩国国内大量揄拍精品视频| 亚洲成在人线av| 青青在线视频一区二区三区| 亚洲人成欧美中文字幕| 777午夜精品福利在线观看| 国产亚洲美女久久| 国产精品久久婷婷六月丁香| 91影院在线免费观看视频| 精品国产31久久久久久| 日本一欧美一欧美一亚洲视频| 91在线视频成人| 欧美多人爱爱视频网站| 91在线免费看网站| 隔壁老王国产在线精品| 亚洲三级 欧美三级| 日韩欧美成人网| 亚洲视频一区二区| 欧美色欧美亚洲高清在线视频| 欧美在线视频一区| 欧美理论电影在线播放| 成人情趣片在线观看免费| 国产精品久在线观看| 久久成人国产精品| 精品国产精品三级精品av网址| 91手机视频在线观看| 欧美贵妇videos办公室| 国产精品日韩久久久久| 4388成人网| 久久激情视频免费观看| 欧美一区二区色| 8090成年在线看片午夜| 欧美黑人狂野猛交老妇| 亚洲a区在线视频| 久久久国产精品免费| 91中文字幕在线观看| 欧洲精品在线视频| 中文字幕日韩精品有码视频| 亚洲精品视频免费| 中文字幕亚洲一区在线观看| 国产主播喷水一区二区| 日韩中文字幕在线看| 久久精品免费电影| 亚洲免费av片| 中文字幕欧美亚洲| 国产91成人video| 久久99亚洲热视| 国产999视频| 欧美性猛交xxxxx水多| 欧美国产高跟鞋裸体秀xxxhd| 91美女片黄在线观看游戏| 91精品国产一区| 亚洲精品一区二三区不卡| 欧美激情视频在线免费观看 欧美视频免费一| 久热精品视频在线| 欧美巨乳在线观看| 久久夜精品va视频免费观看| 在线性视频日韩欧美| 性日韩欧美在线视频| 久久久久国产精品免费| 日韩成人中文字幕| 日韩在线一区二区三区免费视频| 国产精品久久久久久搜索| 狠狠躁18三区二区一区| 久久综合九色九九| 91麻豆国产语对白在线观看| 日本在线观看天堂男亚洲| 久久精品国产一区二区三区| 亚洲综合一区二区不卡| 日韩精品在线观看一区| 91精品久久久久久久久久久| 国产一区二区激情| 亚洲国模精品私拍| 色婷婷av一区二区三区在线观看| 中文字幕亚洲欧美日韩在线不卡| 日韩欧美999| 色噜噜国产精品视频一区二区| 黑人巨大精品欧美一区二区免费| 欧美日韩在线免费| 亚洲成人av资源网| 欧美性猛交xxxx| 国产日韩欧美视频在线| 欧美日韩在线视频首页| 欧美一级高清免费| 韩国日本不卡在线| 成人免费在线网址| 国产日韩欧美在线播放| 精品国产精品三级精品av网址| 日韩欧美中文在线| 国产精品久久久久久久久久小说| 91精品国产乱码久久久久久蜜臀| 精品日本高清在线播放| 日韩在线激情视频| 97视频在线观看成人| 国产精品一区久久久| 日韩大胆人体377p| 国产91|九色| 国模吧一区二区| 欧美男插女视频| 九九久久综合网站| 欧美激情精品久久久久久久变态| 日韩网站在线观看| 欧美最猛性xxxxx亚洲精品| 久久天天躁夜夜躁狠狠躁2022| 91精品91久久久久久| 91极品女神在线| 亚洲区bt下载| 国产精品久久久久久超碰| 色偷偷噜噜噜亚洲男人的天堂| 欧美日韩亚洲高清| 国产精品日日摸夜夜添夜夜av| 国产在线观看一区二区三区|