Using matrix in Android to control image rotation, scaling, and movement

Source: Internet
Author: User
Tags gety

This article mainly explains how to use Matrix in android to control the rotation, scaling, and movement of images. For details, refer to the Code: Copy codeThe Code is as follows :/**
* Use a matrix to control image movement, scaling, and Rotation
*/
Public class CommonImgEffectView extends View {

Private Context context;
Private Bitmap mainBmp, controlBmp;
Private int mainbmp width, mainBmpHeight, controlbmp width, controlBmpHeight;
Private Matrix matrix;
Private float [] srcPs, dstPs;
Private RectF srcRect, dstRect;
Private Paint paint, paintRect, paintFrame;
Private float deltaX = 0, deltaY = 0; // displacement value
Private float scaleValue = 1; // scaling Value
Private Point lastPoint;
Private Point prefix, lastPivot;
Private float preDegree, lastDegree;
Private short currentSelectedPointindex; // click the current operation
Private Point symmetric ricpoint = new Point (); // The symmetry Point of the current operation Point.

/**
* Image operation type
*/
Public static final int OPER_DEFAULT =-1; // default
Public static final int OPER_TRANSLATE = 0; // move
Public static final int OPER_SCALE = 1; // scale
Public static final int OPER_ROTATE = 2; // rotate
Public static final int OPER_SELECTED = 3; // select
Public int lastOper = OPER_DEFAULT;

/* Image Control Point
* 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 ();
}

/**
* Initialize data
* @ Author zhangjin
*/
Private void initData (){
MainBmp = BitmapFactory. decodeResource (this. context. getResources (), R. drawable. flower );
ControlBmp = BitmapFactory. decodeResource (this. context. getResources (), R. drawable. control );
MainBmp width = mainBmp. getWidth ();
MainBmpHeight = mainBmp. getHeight ();
ControlBmp width = controlBmp. getWidth ();
ControlBmpHeight = controlBmp. getHeight ();

SrcPs = new float [] {
0, 0,
Mainbmp width/2, 0,
Mainbmp width, 0,
Mainbmp width, mainBmpHeight/2,
Mainbmp width, mainBmpHeight,
Mainbmp width/2, mainBmpHeight,
0, mainBmpHeight,
0, mainBmpHeight/2,
Mainbmp width/2, mainBmpHeight/2
};
DstPs = srcPs. clone ();
SrcRect = new RectF (0, 0, mainbmp width, mainBmpHeight );
DstRect = new RectF ();

Matrix = new Matrix ();

Prefill = new Point (mainbmp width/2, mainBmpHeight/2 );
Lastparts = new Point (mainbmp width/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 );
}

/**
* Matrix transformation for graphic Translation
* @ Author zhangjin
*/
Private void setMatrix (int operationType ){
Switch (operationType ){
Case OPER_TRANSLATE:
Matrix. postTranslate (deltaX, deltaY );
Break;
Case OPER_SCALE:
Matrix. postScale (scaleValue, scaleValue, metrics ricpoint. x, metrics ricpoint. 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;

}

/**
* The control point of the judgment point
* @ Param evX
* @ Param evY
* @ Return
*/
Private int isOnCP (int evx, int evy ){
Rect rect = new Rect (evx-controlbmp width/2, evy-controlBmpHeight/2, evx + controlbmp width/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 (); // redraw
Return true;
}

/**
* Mobile
* @ Param evx
* @ Param evy
* @ Author zhang_jin1
*/
Private void translate (int evx, int evy ){

Prefill. x + = evx-lastPoint. x;
Prefill. y + = evy-lastPoint. y;

DeltaX = Preprocessor. x-lastPivot. x;
DeltaY = prefetch. y-lastPivot. y;

LastPivot. x = Preprocessor. x;
Lasttings. y = Preprocessor. y;

SetMatrix (OPER_TRANSLATE); // sets the matrix.

}

/**
* Zoom
* 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;
Repeated ricpoint. x = (int) oppositeX;
Repeated ricpoint. y = (int) oppositeY;

Log. I ("img", "scaleValue is" + scaleValue );
SetMatrix (OPER_SCALE );
}

/**
* Rotating Images
* 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;
}

/**
* Calculate the angle between two points and the vertical direction.
* @ 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) {// First quadrant
Degree = angle;
} Else if (tran_x <= 0 & tran_y <= 0) {// Second quadrant
Degree = angle;
} Else if (tran_x <= 0 & tran_y> = 0) {// third quadrant
Degree =-180-angle;
} Else if (tran_x> = 0 & tran_y> = 0) {// quadrant
Degree = 180-angle;
}
}
Return degree;
}

/**
* Calculate the distance between two points
* @ 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); // draws the background to test the ing of the rectangle.
Canvas. drawBitmap (mainBmp, matrix, paint); // draw the main Image
DrawFrame (canvas); // draw a border for the ing of the test point
DrawControlPoints (canvas); // draw a control point image
}

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]-controlBmp width/2, dstPs [I + 1]-controlBmpHeight/2, paint );
}

}

}

Demo effect:

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.