/**
* Use matrix to control image movement, zoom, and rotation
*/
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; //displacement value
private float scaleValue = 1; //Scaling value
private Point lastPoint ;
private Point prePivot , lastPivot;
private float preDegree , lastDegree ;
private short currentSelectedPointindex; //Click the current operation
private Point symmetricPoint = new Point(); //The current operation point symmetric point
/**
* Image operation type
*/
public static final int OPER_DEFAULT = -1; //Default
public static final int OPER_TRANSLATE = 0; //Mobile
public static final int OPER_SCALE = 1; //Scaling
public static final int OPER_ROTATE = 2; //Rotate
public static final int OPER_SELECTED = 3; //Select
public int lastOper = OPER_DEFAULT;
/* Picture 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);
= context ;
}
public CommonImgEffectView(Context context, AttributeSet attrs) {
super(context, attrs);
= context ;
initData();
}
/**
* Initialize data
* @author Zhang Jin
*/
private void initData(){
mainBmp = ((), );
controlBmp = ((), );
mainBmpWidth = ();
mainBmpHeight = ();
controlBmpWidth = ();
controlBmpHeight = ();
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 = ();
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();
();
(100);
(true);
paintFrame = new Paint();
();
(true);
setMatrix(OPER_DEFAULT);
}
/**
* Matrix transformation to achieve the purpose of graph translation
* @author Zhang Jin
*/
private void setMatrix(int operationType){
switch (operationType) {
case OPER_TRANSLATE:
(deltaX , deltaY);
break;
case OPER_SCALE:
(scaleValue, scaleValue, , );
break;
case OPER_ROTATE:
(preDegree - lastDegree, dstPs[CTR_MID_MID * 2], dstPs[CTR_MID_MID * 2 + 1]);
break;
}
(dstPs, srcPs);
(dstRect, srcRect);
}
private boolean isOnPic(int x , int y){
if((x, y)){
return true;
}else
return false;
}
private int getOperationType(MotionEvent event){
int evX = (int)();
int evY = (int)();
int curOper = lastOper;
switch(()) {
case MotionEvent.ACTION_DOWN:
current_ctr = isOnCP(evX, evY);
("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;
}
("img", "curOper is "+curOper);
return curOper;
}
/**
* The control point where the judgment point is located
* @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 < ; i+=2) {
if(((int)dstPs[i], (int)dstPs[i+1])){
return res ;
}
++res ;
}
return CTR_NONE;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int evX = (int)();
int evY = (int)();
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;
}
= evX;
= evY;
lastOper = operType;
invalidate();//Repaint
return true;
}
/**
* move
* @param evx
* @param evy
* @author zhang_jin1
*/
private void translate(int evx , int evy){
+= evx - ;
+= evy -;
deltaX = - ;
deltaY = - ;
= ;
= ;
setMatrix(OPER_TRANSLATE); //Set 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 = ();
float evy = ();
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);
= temp2 / temp1 ;
= (int) oppositeX;
= (int)oppositeY;
("img", "scaleValue is "+scaleValue);
setMatrix(OPER_SCALE);
}
/**
* Rotate picture
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
* @param evX
* @param evY
*/
private void rotate(MotionEvent event) {
if(() == 2){
preDegree = computeDegree(new Point((int)(0), (int)(0)), new Point((int)(1), (int)(1)));
}else{
preDegree = computeDegree(new Point((int)(), (int)()), new Point((int)dstPs[16], (int)dstPs[17]));
}
setMatrix(OPER_ROTATE);
lastDegree = preDegree;
}
/**
* Calculate the angle between the two points and the vertical direction
* @param p1
* @param p2
* @return
*/
public float computeDegree(Point p1, Point p2){
float tran_x = - ;
float tran_y = - ;
float degree = 0.0f;
float angle = (float)((tran_x/(tran_x*tran_x + tran_y* tran_y))*180/);
if(!(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){//The fourth 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)((( - ) * ( - ) + ( - ) * ( - )));
}
private float getDistanceOfTwoPoints(float x1,float y1,float x2,float y2){
return (float)(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
@Override
public void onDraw(Canvas canvas){
drawBackground(canvas);//Draw the background to test the mapping of the rectangle.
(mainBmp, matrix, paint);//Draw the main picture
drawFrame(canvas);//Draw the border to test the mapping of points
drawControlPoints(canvas);//Draw control point pictures
}
private void drawBackground(Canvas canvas){
(dstRect, paintRect);
}
private void drawFrame(Canvas canvas){
(dstPs[0], dstPs[1], dstPs[4], dstPs[5], paintFrame);
(dstPs[4], dstPs[5], dstPs[8], dstPs[9], paintFrame);
(dstPs[8], dstPs[9], dstPs[12], dstPs[13], paintFrame);
(dstPs[0], dstPs[1], dstPs[12], dstPs[13], paintFrame);
(dstPs[16], dstPs[17], paintFrame);
}
private void drawControlPoints(Canvas canvas){
for (int i = 0; i < ; i+=2) {
(controlBmp, dstPs[i]-controlBmpWidth/2, dstPs[i+1]-controlBmpHeight/2, paint);
}
}
}