Get touch screen location inside imageview in Android - android

I'm working on Android project.
I'm using custom View class to showing image and (move, scale, rotate) the image by using matrix.
This is the code I'm using:
public class CustomView extends View implements OnTouchListener {
private Bitmap bitmap;
private float imgWidth;
private float imgHeight;
private float screenWidth;
private float screenHeight;
private Matrix matrix = new Matrix();
private Vector2D position = new Vector2D();
private float scale=1;
private float angle = 0;
private TouchManager touchManager = new TouchManager(2);
private boolean isInitialized = false;
// Debug helpers to draw lines between the two touch points
Vector2D vca;
Vector2D vcb;
Vector2D vpa;
Vector2D vpb;
int PressCount=0;
Paint paint;
public CustomView(Context context, Bitmap bitmap)
{
super(context);
this.bitmap = bitmap;
this.imgWidth = bitmap.getWidth();
this.imgHeight = bitmap.getHeight();
setOnTouchListener(this);
}
private float GetTheta(){
return (float) (angle*180/Math.PI);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!isInitialized)
{
screenWidth = getWidth();
screenHeight = getHeight();
position.set(screenWidth / 2, screenHeight / 2);
scale=1;
paint=new Paint();
isInitialized = true;
}
// Drawing the image
matrix.reset();
matrix.postTranslate(-imgWidth / 2.0f, -imgHeight / 2.0f);
matrix.postRotate(GetTheta());
matrix.postScale(scale, scale);
matrix.postTranslate(position.getX(), position.getY());
canvas.drawBitmap(bitmap, matrix, paint);
}
Vector2D DistancePoint;
#Override
public boolean onTouch(View v, MotionEvent event) {
vca = null;
vcb = null;
vpa = null;
vpb = null;
try {
touchManager.update(event);
PressCount=touchManager.getPressCount();
if (PressCount == 1)
{
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
DistancePoint=touchManager.moveDelta(0);
position.add(DistancePoint);
}
else if (PressCount == 2)
{
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0)
{
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
return true;
}
}
Above code is working perfect!
My question is how to convert screen touch coordinates to image coordinates?
In another word: when touching down on screen the (event.getX, event.getY) are relative to screen coordinates; Okay: I wanna correspond these coordinates to be relative to the image.
Also this image to explain what I want exactly:
Please comment me for any inquiry.
Will be appreciated for any help.

Related

How to move and scale added on canvas bitmaps with MotionEvent.MOVE

I have custom image view that can be zoomed in and out. But also I have "canvas.drawBitmap" in onDraw method:
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (isPinShouldBeDrawn) {
Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pin_raster_64);
canvas.drawBitmap(marker, lastTouchX, lastTouchY, null);
}
isPinShouldBeDrawn = false;
}
In "onTouchEvent" method I can move the image:
#SuppressWarnings("deprecation")
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mDetector.onTouchEvent(event)) {
return true;
}
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
if (touchCount >= 2) {
float distance = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
mPrevDistance = distance;
isScaling = true;
} else {
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
}
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaling) {
float dist = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
float scale = (dist - mPrevDistance) / dispDistance();
mPrevDistance = dist;
scale += 1;
scale = scale * scale;
zoomTo(scale, mWidth / 2, mHeight / 2);
cutting();
} else if (!isScaling) {
int distanceX = mPrevMoveX - (int) event.getX();
int distanceY = mPrevMoveY - (int) event.getY();
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
mMatrix.postTranslate(-distanceX, -distanceY);
cutting();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
if (event.getPointerCount() <= 1) {
isScaling = false;
}
break;
}
return true;
}
But bitmaps from onDraw not moving. If i'm trying to save new bitmap, it's saving only visible area, and after that I can't zoom it at all or move; Save method:
public void save() {
Bitmap returnedBitmap = Bitmap.createBitmap(
getWidth(),
getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
draw(canvas);
setImageBitmap(returnedBitmap);
}
How to synchronized move and scale the image and added bitmaps? Please help!
Whole class:
import android.annotation.SuppressLint;
import android.content.Context;
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.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import androidx.appcompat.widget.AppCompatImageView;
import com.signalsense.signalsenseapp.R;
public class ScaleImageView extends AppCompatImageView implements OnTouchListener {
static final float STROKE_WIDTH = 10f;
static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
public static Path path = new Path();
public static int imageheight, imagewidth;
private static Matrix mMatrix;
final RectF dirtyRect = new RectF();
private final Context mContext;
private final float MAX_SCALE = 2f;
private final float[] mMatrixValues = new float[9];
float lastTouchX;
float lastTouchY;
Paint paint = new Paint();
String TAG = "ScaleImageView";
private boolean isPinShouldBeDrawn = false;
// display width height.
private int mWidth;
private int mHeight;
private int mIntrinsicWidth;
private int mIntrinsicHeight;
private float mScale;
private float mMinScale;
private float mPrevDistance;
private boolean isScaling;
private int mPrevMoveX;
private int mPrevMoveY;
private GestureDetector mDetector;
public ScaleImageView(Context context, AttributeSet attr) {
super(context, attr);
this.mContext = context;
initialize();
}
public ScaleImageView(Context context) {
super(context);
this.mContext = context;
initialize();
}
private void resetDirtyRect(float eventX, float eventY) {
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
this.initialize();
}
#Override
public void setImageResource(int resId) {
super.setImageResource(resId);
this.initialize();
}
private void initialize() {
this.setScaleType(ScaleType.MATRIX);
mMatrix = new Matrix();
Drawable d = getDrawable();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
if (d != null) {
mIntrinsicWidth = d.getIntrinsicWidth();
mIntrinsicHeight = d.getIntrinsicHeight();
setOnTouchListener(this);
}
mDetector = new GestureDetector(mContext,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDoubleTap(MotionEvent e) {
maxZoomTo((int) e.getX(), (int) e.getY());
cutting();
return super.onDoubleTap(e);
}
#Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
lastTouchX = e.getX();
lastTouchY = e.getY();
isPinShouldBeDrawn = true;
invalidate();
save();
}
});
}
#Override
protected boolean setFrame(int l, int t, int r, int b) {
mWidth = r - l;
mHeight = b - t;
mMatrix.reset();
int r_norm = r - l;
mScale = (float) r_norm / (float) mIntrinsicWidth;
int paddingHeight = 0;
int paddingWidth = 0;
// scaling vertical
if (mScale * mIntrinsicHeight > mHeight) {
mScale = (float) mHeight / (float) mIntrinsicHeight;
mMatrix.postScale(mScale, mScale);
paddingWidth = (r - mWidth) / 2;
paddingHeight = 0;
// scaling horizontal
} else {
mMatrix.postScale(mScale, mScale);
paddingHeight = (b - mHeight) / 2;
paddingWidth = 0;
}
mMatrix.postTranslate(paddingWidth, paddingHeight);
setImageMatrix(mMatrix);
mMinScale = mScale;
zoomTo(mScale, mWidth / 2, mHeight / 2);
cutting();
return super.setFrame(l, t, r, b);
}
protected float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
return mMatrixValues[whichValue];
}
protected float getScale() {
return getValue(mMatrix, Matrix.MSCALE_X);
}
public float getTranslateX() {
return getValue(mMatrix, Matrix.MTRANS_X);
}
protected float getTranslateY() {
return getValue(mMatrix, Matrix.MTRANS_Y);
}
protected void maxZoomTo(int x, int y) {
if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) {
// threshold 0.1f
float scale = mMinScale / getScale();
zoomTo(scale, x, y);
} else {
float scale = MAX_SCALE / getScale();
zoomTo(scale, x, y);
}
}
public void zoomTo(float scale, int x, int y) {
if (getScale() * scale < mMinScale) {
return;
}
if (scale >= 1 && getScale() * scale > MAX_SCALE) {
return;
}
mMatrix.postScale(scale, scale);
// move to center
mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2,
-(mHeight * scale - mHeight) / 2);
// move x and y distance
mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
setImageMatrix(mMatrix);
}
public void cutting() {
int width = (int) (mIntrinsicWidth * getScale());
int height = (int) (mIntrinsicHeight * getScale());
imagewidth = width;
imageheight = height;
if (getTranslateX() < -(width - mWidth)) {
mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
}
if (getTranslateX() > 0) {
mMatrix.postTranslate(-getTranslateX(), 0);
}
if (getTranslateY() < -(height - mHeight)) {
mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));
}
if (getTranslateY() > 0) {
mMatrix.postTranslate(0, -getTranslateY());
}
if (width < mWidth) {
mMatrix.postTranslate((mWidth - width) / 2, 0);
}
if (height < mHeight) {
mMatrix.postTranslate(0, (mHeight - height) / 2);
}
setImageMatrix(mMatrix);
}
private float distance(float x0, float x1, float y0, float y1) {
float x = x0 - x1;
float y = y0 - y1;
return (float) Math.sqrt(x * x + y * y);
}
private float dispDistance() {
return (float) Math.sqrt(mWidth * mWidth + mHeight * mHeight);
}
public void clear() {
path.reset();
invalidate();
}
public void save() {
Bitmap returnedBitmap = Bitmap.createBitmap(
getWidth(),
getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
draw(canvas);
setImageBitmap(returnedBitmap);
}
#SuppressWarnings("deprecation")
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mDetector.onTouchEvent(event)) {
return true;
}
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
if (touchCount >= 2) {
float distance = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
mPrevDistance = distance;
isScaling = true;
} else {
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
}
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaling) {
float dist = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
float scale = (dist - mPrevDistance) / dispDistance();
mPrevDistance = dist;
scale += 1;
scale = scale * scale;
zoomTo(scale, mWidth / 2, mHeight / 2);
cutting();
} else if (!isScaling) {
int distanceX = mPrevMoveX - (int) event.getX();
int distanceY = mPrevMoveY - (int) event.getY();
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
mMatrix.postTranslate(-distanceX, -distanceY);
cutting();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
if (event.getPointerCount() <= 1) {
isScaling = false;
}
break;
}
return true;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (isPinShouldBeDrawn) {
Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pin_raster_64);
canvas.drawBitmap(marker, lastTouchX, lastTouchY, null);
}
isPinShouldBeDrawn = false;
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
return super.onTouchEvent(event);
}
}
Sorry for english, it's not my native language :)
Record normalized coordinates on touch events,
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
//lastTouchX = e.getX();
//lastTouchY = e.getY();
float[] touchCoords = new float[]{ e.getX(), e.getY()}; // Touch point in screen-X,Y coords.
Matrix matrix_inverse = new Matrix();
mMatrix.invert(matrix_inverse); // XY to UV mapping matrix.
matrix_inverse.mapPoints(touchCoords); // Touch point in bitmap-U,V coords.
lastTouchX = touchCoords[0];
lastTouchY = touchCoords[1];
isPinShouldBeDrawn = true;
invalidate();
save();
}
Then, draw the overlay bitmap by applying the transform.
protected void onDraw(Canvas canvas)
{
// TODO Auto-generated method stub
super.onDraw(canvas);
if (isPinShouldBeDrawn)
{
Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pin_raster_64);
//canvas.drawBitmap(marker, lastTouchX, lastTouchY, null);
Matrix matrix_marker = new Matrix();
matrix_marker.setTranslate(lastTouchX, lastTouchY);
matrix_marker.postConcat(mMatrix);
canvas.drawBitmap(marker, matrix_marker, null);
}
isPinShouldBeDrawn = false;
}
If you'd like to bake the overlays onto the bitmap, set the invert matrix to the canvas and call draw().
public void save()
{
Bitmap returnedBitmap = Bitmap.createBitmap(
mIntrinsicWidth,
mIntrinsicHeight,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Matrix matrix_inverse = new Matrix();
mMatrix.invert(matrix_inverse);
canvas.setMatrix(matrix_inverse);
draw(canvas);
setImageBitmap(returnedBitmap);
}

PinView does not draw in Loop

I have extended SubsamplingScaleImageView to create PinView as recommend in documentation. I am able to draw Pint at proper location.
But issue i am facing is : When i try to draw in loop it, Pin goes missing.
I verified OnDraw is called on Main Thread.
Following is code i am using
public class PinView extends SubsamplingScaleImageView {
private PointF sPin;
private Bitmap pin;
private PointF sBlueDot;
private Bitmap blueDot;
public PinView(Context context) {
this(context, null);
}
public PinView(Context context, AttributeSet attr) {
super(context,attr);
initialise();
initialiseBlueDot()
}
public void setPin(PointF sPin) {
this.sPin = sPin;
initialise();
invalidate();
}
public void setBlueDot(PointF sPin) {
this.sBlueDot = sPin;
initialiseBlueDot();
invalidate();
}
public PointF getPin() {
return sPin;
}
private void initialise() {
float density = getResources().getDisplayMetrics().densityDpi;
pin = BitmapFactory.decodeResource(this.getResources(), drawable.pushpin_blue);
float w = (density/420f) * pin.getWidth();
float h = (density/420f) * pin.getHeight();
pin = Bitmap.createScaledBitmap(pin, (int)w, (int)h, true);
}
private void initialiseBlueDot() {
float density = getResources().getDisplayMetrics().densityDpi;
blueDot = BitmapFactory.decodeResource(this.getResources(), drawable.pushpin_blue);
float w = (density/420f) * blueDot.getWidth();
float h = (density/420f) * blueDot.getHeight();
blueDot = Bitmap.createScaledBitmap(blueDot, (int)w, (int)h, true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Don't draw pin before image is ready so it doesn't move around during setup.
if (!isReady()) {
return;
}
Paint paint = new Paint();
paint.setAntiAlias(true);
if (sPin != null && pin != null) {
PointF vPin = sourceToViewCoord(sPin);
float vX = vPin.x - (pin.getWidth()/2);
float vY = vPin.y - pin.getHeight();
canvas.drawBitmap(pin, vX, vY, paint);
}
if (sBlueDot != null && pin != null) {
PointF vPin = sourceToViewCoord(sBlueDot);
float vX = vPin.x - (blueDot.getWidth()/2);
float vY = vPin.y - blueDot.getHeight();
canvas.drawBitmap(blueDot, vX, vY, paint);
}
}
}
I got it fixed myself. Issue was with XY and source xy points. used viewToSourceCoord() to get proper location points.

Canvas getting wrong coordinates for finger drawing after pinch to zoom

I create canvas finger drawing app like line brush which is on https://play.google.com/store/apps/details?id=jp.naver.linebrush.android, I done pinch to zoom functionality but problem is after zoom in and zoom out, not drawing properly position on canvas area. For more understanding I share my View class for canvas drawing:
public class DrawingView extends View {
// Zooming Code 16-6-2015 4.12pm
private static final int INVALID_POINTER_ID = -1;
public Bitmap mMyChracter;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
View currentView;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private float focusX;
private float focusY;
private float lastFocusX = -1;
private float lastFocusY = -1;
static final int IMG_WIDTH = 640;
static final int IMG_HEIGHT = 480;
static final int IMAGE_X_POS = 560;
static final int IMAGE_Y_POS = 20;
float sy;
float sx;
public static Context context;
// -------------------------------------
// ...................................
/*private final Bitmap bitmap;
private final int width;
private final int height;*/
private Matrix transform = new Matrix();
private Vector2D position = new Vector2D();
private float scale = 1;
private float angle = 0;
private TouchManager touchManager = new TouchManager(2);
private boolean isInitialized = false;
// Debug helpers to draw lines between the two touch points
private Vector2D vca = null;
private Vector2D vcb = null;
private Vector2D vpa = null;
private Vector2D vpb = null;
int mWidth;
int mHeight;
// ...............................
private final Paint mDefaultPaint;
private Paint mFillPaint;
float x, y;
private Canvas mLayerCanvas = new Canvas();
private Bitmap mLayerBitmap;
private Stack<DrawOp> mDrawOps = new Stack<>();
private Stack<DrawOp> mUndoOps = new Stack<>();
private SparseArray<DrawOp> mCurrentOps = new SparseArray<>(0);
// For Drag and Pan zoom Code initialization
private static float MIN_ZOOM = 1f;
private static float MAX_ZOOM = 2f;
private float scaleFactor = 1.f;
private static ScaleGestureDetector detector;
boolean mFlagDrawing;
private final Matrix mMatrix = new Matrix();
int y_old=0,y_new=0;int zoomMode=0;
float pinch_dist_old=0,pinch_dist_new=0;
int zoomControllerScale=1;//new and old pinch distance to determine Zoom scale
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
// We can be in one of these 3 states
static final int NONE = 0;
static final int PAN = 1;
static final int ZOOM = 2;
int mode = NONE;
private static final String TAG = "DebugTag";
// New Code
private Bitmap imgBitmap = null;
private int containerWidth;
private int containerHeight;
Paint background;
//Matrices will be used to move and zoom image
// Matrix matrix = new Matrix();
// Matrix savedMatrix = new Matrix();
// PointF start = new PointF();
float currentScale;
float curX;
float curY;
//We can be in one of these 3 states
// static final int NONE = 0;
// static final int DRAG = 1;
// static final int ZOOM = 2;
// int mode = NONE;
//For animating stuff
float targetX;
float targetY;
float targetScale;
float targetScaleX;
float targetScaleY;
float scaleChange;
float targetRatio;
float transitionalRatio;
float easing = 0.2f;
boolean isAnimating = false;
float scaleDampingFactor = 0.5f;
//For pinch and zoom
// float oldDist = 1f;
// PointF mid = new PointF();
private Handler mHandler = new Handler();
float minScale;
float maxScale = 8.0f;
float wpRadius = 25.0f;
float wpInnerRadius = 20.0f;
float screenDensity;
private GestureDetector gestureDetector;
public static final int DEFAULT_SCALE_FIT_INSIDE = 0;
public static final int DEFAULT_SCALE_ORIGINAL = 1;
private int defaultScale;
private static final String EXTRA_EVENT_LIST = "event_list";
private static final String EXTRA_STATE = "instance_state";
private ArrayList<MotionEvent> eventList = new ArrayList<MotionEvent>(100);
public DrawingView(Context context) {
this(context, null, 0);
}
public DrawingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// detector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public DrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDefaultPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDefaultPaint.setStyle(Paint.Style.STROKE);
mDefaultPaint.setStrokeJoin(Paint.Join.ROUND);
mDefaultPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultPaint.setStrokeWidth(40);
mDefaultPaint.setColor(Color.GREEN);
/*mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFillPaint.setStyle(Paint.Style.STROKE);
mFillPaint.setStrokeJoin(Paint.Join.ROUND);
mFillPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultPaint.setStrokeWidth(40);
mFillPaint.setColor(Color.GREEN);*/
setFocusable(true);
setFocusableInTouchMode(true);
setBackgroundColor(Color.WHITE);
setLayerType(LAYER_TYPE_SOFTWARE, null);
setSaveEnabled(true);
// Code for Zoom start
// detector = new ScaleGestureDetector(getContext(), new ScaleListener());
// Code for Zoom finish
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
private static float getDegreesFromRadians(float angle) {
return (float)(angle * 180.0 / Math.PI);
}
// Single Touch Code
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
vca = null;
vcb = null;
vpa = null;
vpb = null;
final int pointerCount = MotionEventCompat.getPointerCount(event);
switch (MotionEventCompat.getActionMasked(event)) {
// switch(event.getAction()){
// switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
// case MotionEventCompat.ACTION_POINTER_DOWN:
{
if (mFlagDrawing == true) {
/* final float xx = event.getX() / mScaleFactor;
final float yy = event.getY() / mScaleFactor;
mLastTouchX = xx;
mLastTouchY = yy;
mActivePointerId = event.getPointerId(0);*/
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
DrawOp current = new DrawOp(mDefaultPaint);
current.getPath().moveTo(event.getX(), event.getY());
mCurrentOps.put(id, current);
}
}
// mFlagZoom = true;
// }
}
break;
case MotionEvent.ACTION_MOVE: {
// for(int p = 0; p < pointerCount; p++){
if (mFlagDrawing == true) {
/* final int pointerIndex = event.findPointerIndex(mActivePointerId);
final float xx = event.getX(pointerIndex) / mScaleFactor;
final float yy = event.getY(pointerIndex) / mScaleFactor;
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = xx - mLastTouchX;
final float dy = yy - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = xx;
mLastTouchY = yy;*/
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
// current.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
final int id = MotionEventCompat.getPointerId(event, 0);
DrawOp current = mCurrentOps.get(id);
final int historySize = event.getHistorySize();
for (int h = 0; h < historySize; h++) {
x = event.getHistoricalX(h);
y = event.getHistoricalY(h);
current.getPath().lineTo(x, y);
}
x = MotionEventCompat.getX(event, 0);
y = MotionEventCompat.getY(event, 0);
current.getPath().lineTo(x, y);
// position.add(current.getPath());
// }
}
}
break;
case MotionEvent.ACTION_UP:
// case MotionEventCompat.ACTION_POINTER_UP:
// {
if (mFlagDrawing == true) {
// mActivePointerId = INVALID_POINTER_ID;
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
mDrawOps.push(mCurrentOps.get(id));
mCurrentOps.remove(id);
// }
updateLayer();
}
}
// }
break;
case MotionEvent.ACTION_CANCEL: {
if (mFlagDrawing == true) {
// mActivePointerId = INVALID_POINTER_ID;
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
mCurrentOps
.remove(MotionEventCompat.getPointerId(event, p));
}
}
// mFlagZoom = true;
// }
}
break;
/*case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = event.getX(newPointerIndex) / mScaleFactor;
mLastTouchY = event.getY(newPointerIndex) / mScaleFactor;
mActivePointerId = event.getPointerId(newPointerIndex);
}
break;
}*/
default:
return false;
}
invalidate();
return true;
}
#Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
super.onSizeChanged(w, h, oldW, oldH);
/*mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mLayerCanvas.setBitmap(mLayerBitmap);*/
if(mLayerBitmap == null){
mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}else{
Bitmap temporary = Bitmap.createScaledBitmap(mLayerBitmap, w, h, true);
mLayerBitmap = temporary;
}
mLayerCanvas = new Canvas(mLayerBitmap);
// mLayerCanvas.rotate(90);
/* matrix.setTranslate(1.5f,1.5f);
matrix.postRotate(90, 2.5f, 2.5f);*/
// updateLayer();
/* //Reset the width and height. Will draw bitmap and change
containerWidth = w;
containerHeight = h;
if(mLayerBitmap != null) {
int imgHeight = mLayerBitmap.getHeight();
int imgWidth = mLayerBitmap.getWidth();
float scale;
int initX = 0;
int initY = 0;
if(defaultScale == DrawingView.DEFAULT_SCALE_FIT_INSIDE) {
if(imgWidth > containerWidth) {
scale = (float)containerWidth / imgWidth;
float newHeight = imgHeight * scale;
initY = (containerHeight - (int)newHeight)/2;
matrix.setScale(scale, scale);
matrix.postTranslate(0, initY);
}
else {
scale = (float)containerHeight / imgHeight;
float newWidth = imgWidth * scale;
initX = (containerWidth - (int)newWidth)/2;
matrix.setScale(scale, scale);
matrix.postTranslate(initX, 0);
}
curX = initX;
curY = initY;
currentScale = scale;
minScale = scale;
}
else {
if(imgWidth > containerWidth) {
initY = (containerHeight - (int)imgHeight)/2;
matrix.postTranslate(0, initY);
}
else {
initX = (containerWidth - (int)imgWidth)/2;
matrix.postTranslate(initX, 0);
}
curX = initX;
curY = initY;
currentScale = 1.0f;
minScale = 1.0f;
}
invalidate();
}*/
}
private void updateLayer() {
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
for (DrawOp drawOp : mDrawOps) {
if (drawOp != null) {
drawOp.draw(mLayerCanvas);
}
}
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode()) {
return;
}
// if(mFlagDrawing == true){
if (!isInitialized) {
int w = getWidth();
int h = getHeight();
position.set(w / 2, h / 2);
isInitialized = true;
}
mWidth = mLayerBitmap.getWidth();
mHeight = mLayerBitmap.getHeight();
// Code for Zoom start
/* canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, focusX, focusY);
canvas.translate(mPosX, mPosY);*/
// canvas.scale(scaleFactor, scaleFactor);
/*canvas.scale(mScaleFactor, mScaleFactor, super.getWidth() * 0.5f,
super.getHeight() * 0.5f);*/
// Code for Zoom finish
// canvas.save();
transform.reset();
transform.postTranslate(-mWidth / 2.0f, -mHeight / 2.0f);
// transform.postRotate(getDegreesFromRadians(angle));
transform.postScale(scale, scale);
transform.postTranslate(position.getX(), position.getY());
canvas.drawBitmap(mLayerBitmap, transform, null);
// }
// else if(mFlagDrawing == false){
// canvas.drawBitmap(mLayerBitmap, 0, 0, null);
for (int i = 0; i < mCurrentOps.size(); i++) {
DrawOp current = mCurrentOps.valueAt(i);
if (current != null) {
current.draw(canvas);
}
}
// }
// Code for Zoom
// canvas.restore();
}
public void operationClear() {
mDrawOps.clear();
mUndoOps.clear();
mCurrentOps.clear();
updateLayer();
}
public void operationUndo() {
if (mDrawOps.size() > 0) {
mUndoOps.push(mDrawOps.pop());
updateLayer();
}
}
public void operationRedo() {
if (mUndoOps.size() > 0) {
mDrawOps.push(mUndoOps.pop());
updateLayer();
}
}
public void setPaintStrokeWidth(float widthPx) {
mDefaultPaint.setStrokeWidth(widthPx);
}
public void setPaintOpacity(int percent) {
int alphaValue = (int) Math.round(percent * (255.0 / 100.0));
mDefaultPaint.setColor(combineAlpha(mDefaultPaint.getColor(),
alphaValue));
}
public void setPaintColor(String color) {
mDefaultPaint.setColor(combineAlpha(Color.parseColor(color), mDefaultPaint.getAlpha()));
}
public void setPaintColor(int color) {
mDefaultPaint.setColor(combineAlpha(color, mDefaultPaint.getAlpha()));
}
public void setPaintMaskFilter(MaskFilter filter) {
mDefaultPaint.setMaskFilter(filter);
}
public void setPaintShader(BitmapShader shader) {
mDefaultPaint.setShader(shader);
}
public void setPaintColorFilter(ColorFilter colorFilter) {
mDefaultPaint.setColorFilter(colorFilter);
}
private static int combineAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | ((alpha & 0xFF) << 24);
}
private static class DrawOp {
private float x,y;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path mPath = new Path();
public DrawOp(Paint paint) {
reset(paint);
}
/*public void add(Vector2D moveDelta) {
// TODO Auto-generated method stub
this.x += moveDelta.getX();
this.y += moveDelta.getY();
}*/
void reset(Paint paint) {
mPath.reset();
update(paint);
}
void update(Paint paint) {
mPaint.set(paint);
}
void draw(Canvas canvas) {
canvas.drawPath(mPath, mPaint);
}
public Path getPath() {
return mPath;
}
/* public DrawOp add(DrawOp value) {
this.x += value.getX();
this.y += value.getY();
return this;
}*/
/*public float getX() {
return x;
}
public float getY() {
return y;
}*/
}
public void fillShapeColor(){
}
// Code for Zoom
/* private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
invalidate();
return true;
}
}*/
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// float x = detector.getFocusX();
// float y = detector.getFocusY();
lastFocusX = -1;
lastFocusY = -1;
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
focusX = detector.getFocusX();
focusY = detector.getFocusY();
if (lastFocusX == -1)
lastFocusX = focusX;
if (lastFocusY == -1)
lastFocusY = focusY;
mPosX += (focusX - lastFocusX);
mPosY += (focusY - lastFocusY);
Log.v("Hi Zoom", "Factor:" + mScaleFactor);
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 2.0f));
lastFocusX = focusX;
lastFocusY = focusY;
invalidate();
return true;
}
}
/* #Override
public Parcelable onSaveInstanceState()
{
System.out.println("save instance");
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_STATE, super.onSaveInstanceState());
bundle.putParcelableArrayList(EXTRA_EVENT_LIST, eventList);
return bundle;
}
#Override
public void onRestoreInstanceState(Parcelable state)
{
if (state instanceof Bundle)
{
Bundle bundle = (Bundle) state;
super.onRestoreInstanceState(bundle.getParcelable(EXTRA_STATE));
eventList = bundle.getParcelableArrayList(EXTRA_EVENT_LIST);
if (eventList == null) {
eventList = new ArrayList<MotionEvent>(100);
}
for (MotionEvent event : eventList) {
// performTouchEvent(event);
}
return;
}
super.onRestoreInstanceState(state);
}*/
public void setDrawingFlag(boolean flag) {
// System.out.println("Before Set mFlag " + mFlagDrawing);
this.mFlagDrawing = flag;
// System.out.println("After Set mFlag " + mFlagDrawing);
}
public void moveCanvas(float x, float y) {
float dx = x - mLastTouchX;
float dy = y - mLastTouchY;
// Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
// at 200% zoom causes the image to slide 20 pixels instead of perfectly
// following the user's touch
dx /= (mScaleFactor * 2);
dy /= (mScaleFactor * 2);
mPosX += dx;
mPosY += dy;
// Log.v(TAG, "moving by " + dx + "," + dy + " mScaleFactor: " +
// mScaleFactor);
}
}
I found mistake and correct it by my self. Below is my code.
public void resetZoom() {
mPanX = mPanY = 0;
final Matrix m = new Matrix();
m.postScale(1f / DENSITY, 1f / DENSITY);
setZoom(m);
invalidate();
}
public void setZoomPosNoInval(float x, float y) {
mPanX = x;
mPanY = y;
}
public void setZoomPos(float x, float y) {
setZoomPosNoInval(x, y);
invalidate();
}
public void setZoomPosNoInval(float[] pos) {
setZoomPosNoInval(pos[0], pos[1]);
}
public void setZoomPos(float[] pos) {
setZoomPosNoInval(pos);
invalidate();
}
public float[] getZoomPos(float[] pos) {
if (pos == null)
pos = new float[2];
pos[0] = mPanX;
pos[1] = mPanY;
return pos;
}
public float getZoomPosX() {
return mPanX;
}
public float getZoomPosY() {
return mPanY;
}
public Matrix getZoom() {
return mZoomMatrix;
}
public Matrix getZoomInv() {
return mZoomMatrixInv;
}
public void setZoom(Matrix m) {
mZoomMatrix.set(m);
mZoomMatrix.invert(mZoomMatrixInv);
}

How crop bitmap of selected area on canvas?

I am making an application I am unable to one issue last 3 days doing google as much possible.I make a circle on canvas and want to crop image that part and show that image in zoom mode.My first step is like in screen here:-
in this I am selecting area.here is my code used by me for this.
private float x, y;
private boolean zooming = false;
private Paint mPaint;
private Matrix mmatrix;
private Shader mShader;
private Bitmap mBitmap;
private List<Point> mpoints;
private List<MyPoints> mpointlist;
private Path mpath;
private Canvas mcanvas;
private Bitmap mresult_bitmap, resultingImage,finalbitmap;
private Context mcontext;
private boolean bfirstpoint = false;
private Point mfirstpoint = null;
private Point mlastpoint = null;
public CircularZoomView(Context context) {
super(context);
mcontext = context;
mpath = new Path();
mpoints = new ArrayList<Point>();
setBackgroundResource(R.drawable.testing);
mPaint = new Paint();
mresult_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.testing);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (zooming && resultingImage!=null) {
zooming = false;
ShowImage(resultingImage);
canvas.drawBitmap(resultingImage,mmatrix, null);
}
boolean first = true;
for (int i = 0; i < mpoints.size(); i += 2) {
Point point = mpoints.get(i);
if (first) {
first = false;
mpath.moveTo(point.x, point.y);
} else if (i < mpoints.size() - 1) {
Point next = mpoints.get(i + 1);
mpath.quadTo(point.x, point.y, next.x, next.y);
} else {
mlastpoint = mpoints.get(i);
mpath.lineTo(point.x, point.y);
}
}
canvas.drawPath(mpath, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
x = event.getX();
y = event.getY();
Point point = new Point();
point.x = (int) event.getX();
point.y = (int) event.getY();
if (bfirstpoint) {
if (comparepoint(mfirstpoint, point)) {
mpoints.add(mfirstpoint);
addCircleFromPath(mpath);
} else {
mpoints.add(point);
}
} else {
mpoints.add(point);
}
if (!(bfirstpoint)) {
mfirstpoint = point;
bfirstpoint = true;
}
invalidate();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
zooming = false;
this.invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
zooming = true;
mlastpoint = point;
if (mpoints.size() > 12) {
if (!comparepoint(mfirstpoint, mlastpoint)) {
mpoints.add(mfirstpoint);
addCircleFromPath(mpath);
}
}
this.invalidate();
break;
default:
break;
}
return true;
}
public Bitmap getCroppedBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getWidth() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
void ShowImage(Bitmap mbitmap) {
Display display = ((MainActivity) mcontext).getWindowManager().getDefaultDisplay();
int screenWidth = display.getWidth();
float imageWidth = (float)mbitmap.getWidth();
float imageHeight = (float)mbitmap.getHeight();
float newHeight = imageHeight / (imageWidth / screenWidth);
float newWidth = screenWidth;
float scaleWidth = screenWidth / imageWidth;
float scaleHeight = newHeight / imageHeight;
SetImageMatrix(mbitmap,scaleWidth,scaleHeight);
}
void SetImageMatrix(Bitmap image,float scaleWidth, float scaleHeight) {
mmatrix = new Matrix();
mmatrix.setTranslate(40,40);
mmatrix.postScale(scaleWidth/2, scaleHeight/2);
/*image.setImageMatrix(mmatrix);
image.setScaleType(ScaleType.MATRIX);
image.invalidate();*/
}
private boolean comparepoint(Point first, Point current) {
int left_range_x = (int) (current.x - 3);
int left_range_y = (int) (current.y - 3);
int right_range_x = (int) (current.x + 3);
int right_range_y = (int) (current.y + 3);
if ((left_range_x < first.x && first.x < right_range_x)
&& (left_range_y < first.y && first.y < right_range_y)) {
if (mpoints.size() < 10) {
return false;
} else {
return true;
}
} else {
return false;
}
}
private void addCircleFromPath(Path path){
RectF bounds = new RectF();
path.computeBounds(bounds, true);
int width = (int) (bounds.right-bounds.left);
int height = (int) (bounds.bottom-bounds.top);
if(width<20 && height<20){
path.reset();
return;
}
int radius ;
if(width>=height)
radius = Math.round(((width/2)));
else radius = Math.round((int) ((height/2)));
/*CircleTagObject circle = new CircleTagObject((int)bounds.left+width/2, (int)bounds.top+height/2, radius, crossBitmap, tagBitmap,circleArray.size(),
ImageEditorView.this);
circleArray.add(circle);
tagBallID = circleArray.size() - 1;
dragEnable = true;*/
resultingImage = getCroppedBitmap(Bitmap.createBitmap(mresult_bitmap,0,0,200,200));
mcanvas = new Canvas(resultingImage);
path.reset();
resetView();
invalidate();
}
public void resetView() {
mpoints.clear();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
invalidate();
}
If I create hard coded bitmap like above its showing good but not crop bitmap of selected part.Like this image.
but when add exact coordinate of selected area Like as:-
resultingImage = getCroppedBitmap(Bitmap.createBitmap(mresult_bitmap,(int)bounds.left,(int)bounds.top,width,height));
Then exception occure:-
07-12 10:58:56.700: E/MessageQueue-JNI(12310): java.lang.IllegalArgumentException: y + height must be <= bitmap.height()
07-12 10:58:56.700: E/MessageQueue-JNI(12310): at android.graphics.Bitmap.createBitmap(Bitmap.java:565)
07-12 10:58:56.700: E/MessageQueue-JNI(12310): at android.graphics.Bitmap.createBitmap(Bitmap.java:530)
07-12 10:58:56.700: E/MessageQueue-JNI(12310): at com.intel.view.CircularZoomView.addCircleFromPath(CircularZoomView.java:237)
I know why This exception occurs but unable to find solution how crop image of selected part.Thanks in advance.
I know its too late for your solution but this may help to others Use of this code
help you to come out from this problem.

How to implement touch smooth image eraser in android?

I have already seen fingurePaint.java from API demos. I want to implement touch smooth eraser to erase parts of the image by touch move in android.
fingurePaint told me to implement this
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
But this is not working to erase the image. It is working to erase something which is drawn by touch.
public class SandboxView extends View implements OnTouchListener {
public final Bitmap bitmap;
private final int width;
private final int height;
private Matrix transform = new Matrix();
private Vector2D position = new Vector2D();
private float scale = 1;
private float angle = 0;
public boolean isInitialized = false;
private TouchManager touchManager = new TouchManager(2);
final GestureDetector mGesDetect;
// Debug helpers to draw lines between the two touch points
private Vector2D vca = null;
private Vector2D vcb = null;
private Vector2D vpa = null;
private Vector2D vpb = null;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private Path mPath;
private Canvas mCanvas;
private Paint mPaint;
private Paint mBitmapPaint;
public SandboxView(Context context, Bitmap bitmap) {
super(context);
this.bitmap = bitmap;
this.width = bitmap.getWidth();
this.height = bitmap.getHeight();
this.mGesDetect = new GestureDetector(context, new DoubleTapGestureDetector());
setOnTouchListener(this);
}
private float getDegreesFromRadians(float angle) {
return (float)(angle * 360.0 / Math.PI);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!isInitialized) {
Bitmap mBitmap = bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPaint = new Paint();
mPath = new Path();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaint.setAntiAlias(true);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
int w = getWidth();
int h = getHeight();
position.set(w / 2, h / 2);
isInitialized = true;
}
if(isEraser==1){
canvas.drawColor(80000000);
canvas.drawBitmap(bitmap, transform, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
else{
Paint paint = new Paint();
transform.reset();
transform.postTranslate(-width / 2.0f, -height / 2.0f);
transform.postRotate(getDegreesFromRadians(angle));
transform.postScale(scale, scale);
transform.postTranslate(position.getX(), position.getY());
canvas.drawBitmap(bitmap, transform, paint);
try {
/*paint.setColor(0xFF007F00);
canvas.drawCircle(vca.getX(), vca.getY(), 64, paint);
paint.setColor(0xFF7F0000);
canvas.drawCircle(vcb.getX(), vcb.getY(), 64, paint);
paint.setColor(0xFFFF0000);
canvas.drawLine(vpa.getX(), vpa.getY(), vpb.getX(), vpb.getY(), paint);
paint.setColor(0xFF00FF00);
canvas.drawLine(vca.getX(), vca.getY(), vcb.getX(), vcb.getY(), paint);*/
}
catch(NullPointerException e) {
// Just being lazy here...
}
}
}
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if(isEraser ==1){
float x = event.getX();
float y = event.getY();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
else{
vca = null;
vcb = null;
vpa = null;
vpb = null;
mGesDetect.onTouchEvent(event);
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
return true;
}
}
class DoubleTapGestureDetector extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDoubleTap(MotionEvent e) {
colorseekbar.setVisibility(View.INVISIBLE);
opacityseekbar.setVisibility(View.INVISIBLE);
return true;
}
}
}
So please help me to erase the parts of image by using touch move.
Thanks in advance.
First Declar your paint with all property in your constructor.
Write this code in your onDraw() method
#Override
protected void onDraw(Canvas canvas)
{
System.out.println("come in on draw......");
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
if(eraser==true)
mPaint.setColor(Color.TRANSPARENT):
else
mPaint.setColor(Color.RED):
canvas.drawPath(mPath, mPaint);
super.dispatchDraw(canvas);
}
second solution:
call below method in your touch_move() method
mBitmap.setPixel(x, y, Color.TRANSPARENT); This method will change your bitmap you have to pass only X,Y & COLOR
public void changeBitmap(int x, int y, Bitmap mBitmap)
{
Bitmap tempBitmap = Bitmap.createBitmap(mBitmap); //Edited code
tempBitmap.setPixel(x, y, Color.TRANSPARENT);
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
changeBitmap(x, y, your_bitmap)
}
}
Isn't it better to invert this case ? Just paint on your image with background color and after all when saving, merge those layers if needed.
Define a temporary canvas and bitmap then draw your path or line, circle, image anything on touch events and then pass this temporary bitmap to canvas in onDraw your work will done properly, and also if you want to do erasing then do your erasing on that temporary canvas.
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
TemporaryBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
TemporaryCanvas = new Canvas(TemporaryBitmap);
}
TemporaryCanvas.drawColor(0, PorterDuff.Mode.clear);
public void onDraw(Canvas canv){
canv.drawBitmap(TemporaryBitmap, matrix, paint);

Categories

Resources