Skip to content

Instantly share code, notes, and snippets.

@niusounds
Last active August 29, 2015 14:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niusounds/9ce18691ce37498f667d to your computer and use it in GitHub Desktop.
Save niusounds/9ce18691ce37498f667d to your computer and use it in GitHub Desktop.
Homography sample
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="handle_size">16dp</dimen>
</resources>
package com.eje_c.matrixtest;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class HomographyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Matrix m = new Matrix();
final float handleSize = getResources().getDimension(R.dimen.handle_size);
final Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.sample);
final float[] originalPoints = new float[] {
0, 0, // left, top
bmp.getWidth(), 0, // right, top
0, bmp.getHeight(), // left, bottom
bmp.getWidth(), bmp.getHeight() // right, bottom
};
final float[] mappedPoints = new float[originalPoints.length];
final GestureDetector gd = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
static final int TOUCH_NONE = -1;
static final int TOUCH_LEFT_TOP = 0;
static final int TOUCH_RIGHT_TOP = 1;
static final int TOUCH_LEFT_BOTTOM = 2;
static final int TOUCH_RIGHT_BOTTOM = 3;
int touch;
@Override
public boolean onDown(MotionEvent e) {
m.mapPoints(mappedPoints, originalPoints);
float x = e.getX();
float y = e.getY();
if (near(mappedPoints[0], mappedPoints[1], x, y)) {
touch = TOUCH_LEFT_TOP;
} else if (near(mappedPoints[2], mappedPoints[3], x, y)) {
touch = TOUCH_RIGHT_TOP;
} else if (near(mappedPoints[4], mappedPoints[5], x, y)) {
touch = TOUCH_LEFT_BOTTOM;
} else if (near(mappedPoints[6], mappedPoints[7], x, y)) {
touch = TOUCH_RIGHT_BOTTOM;
} else {
touch = TOUCH_NONE;
}
return true;
}
private boolean near(float left, float top, float x, float y) {
return Math.hypot(left - x, top - y) < handleSize;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
switch (touch) {
case TOUCH_NONE:
m.postTranslate(-distanceX, -distanceY);
break;
case TOUCH_LEFT_TOP:
transform(0, e2.getX(), e2.getY());
break;
case TOUCH_RIGHT_TOP:
transform(2, e2.getX(), e2.getY());
break;
case TOUCH_LEFT_BOTTOM:
transform(4, e2.getX(), e2.getY());
break;
case TOUCH_RIGHT_BOTTOM:
transform(6, e2.getX(), e2.getY());
break;
}
return true;
}
void transform(int currentPointsIndex, float x, float y) {
m.mapPoints(mappedPoints, originalPoints);
mappedPoints[currentPointsIndex] = x;
mappedPoints[currentPointsIndex + 1] = y;
m.setPolyToPoly(originalPoints, 0, mappedPoints, 0, 4);
}
});
setContentView(new View(this) {
Paint paint = new Paint();
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// init paint
paint.setColor(Color.RED);
paint.setStrokeWidth(handleSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw image with matrix
canvas.drawBitmap(bmp, m, null);
// draw 4 corner points
m.mapPoints(mappedPoints, originalPoints);
canvas.drawPoint(mappedPoints[0], mappedPoints[1], paint);
canvas.drawPoint(mappedPoints[2], mappedPoints[3], paint);
canvas.drawPoint(mappedPoints[4], mappedPoints[5], paint);
canvas.drawPoint(mappedPoints[6], mappedPoints[7], paint);
// continuous drawing
postInvalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
gd.onTouchEvent(event);
return true;
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment