Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw Rectangle Over ImageView for highlight that can be zoom in-out in android

I have been refer this example from SO below are they.

1.Draw Line Over ImageView

2.Draw Picture Over ImageView

3.I have use this ImageView Class for my image to become zoom in-out Image Pinch zoom code google.

Now what i am try to do is :

I want to make zoom in by pinching the screen and other point is that when i do single tap a rectangle should be drawn over image view and i also want this rectangle should get zoom in & out with imageView's Zoom in and Zoom Out and i want to use it through ScaleImageView class.

Output of this should look like below image.

you can see when i make single tap over ImageViewit will draw rectangle like showing in image

And i also known that ,this can be done by Using Relative Layout or may be by using SurfaceViewin android but i am new for use Surface view and i also worry about if i use Another View over imageView to draw then do this both view work for zoom in and out . If i use SurfaceView over ImageView then do Image Can be able to zoom in and out .

By using this pinch zoom in-out example from here.example that i use pinch zoom.

Now i draw Rectangle on Single Touch by below code in that example.

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.v("Log_tag", "Draw Image View");
        //Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.rect_image);
        //canvas.drawColor(Color.BLACK);
        //canvas.drawBitmap(_scratch, 10, 10, null);
        Drawable d = getDrawable();
        //Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565);
        /*if(bitmap!=null){
            if (x1 > 0 || x2 > 0 || y1 > 0 || y2 > 0){
                  Log.v("Log_tag", "ImageBitmap is draw");
                //Canvas mCanvas=new Canvas(bitmap);
                //mCanvas.drawRect(x1, y1, x2, y2, mPaint);
                //  canvas.clipRect(left, top, right, bottom);
                   paint.setStyle(Paint.Style.FILL_AND_STROKE);
                    paint.setStrokeWidth(1);
                   paint.setColor(0xFF000000
                      + ((int)(PRESET_PRESSURE * pressure) <<16)
                      + ((int)(PRESET_PRESSURE * pressure) << 8)
                      + (int)(PRESET_PRESSURE * pressure));
                   //mCanvas.drawCircle(x1, y1, (PRESET_SIZE * size), paint);
            }

        }*/
        //canvas.save();
        //canvas.translate(mPosX, mPosY);
       // canvas.scale(mScaleFactor, mScaleFactor);
        mBitmapDrawable.draw(canvas);
        Paint myPaint = new Paint();
        myPaint.setColor(Color.GREEN);
        myPaint.setStyle(Paint.Style.STROKE);
        myPaint.setStrokeWidth(1);
        Log.v("Log_tag", "Redraw with this point");
        canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);
        mCanvasMatrix=canvas.getMatrix();
        mImageCanvas=canvas;

        canvas.setMatrix(mCanvasMatrix);
        //canvas.restore();

    }

UPDATE

Below is my class used for ImageView pinch zoom.

public class ImageViewScale extends ImageView implements OnTouchListener {
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //canvas.save();
        //canvas.scale(mScale, mScale);
        mCanvasMatrix=canvas.getMatrix();
        Paint myPaint = new Paint();
        myPaint.setColor(Color.GREEN);
        myPaint.setStyle(Paint.Style.STROKE);
        myPaint.setStrokeWidth(1);
        if(mCanvasMatrix!=null){
            if(orignalRect!=null)
                mCanvasMatrix.mapRect(orignalRect);
        }
        if(orignalRect!=null){
            canvas.drawRect(orignalRect,myPaint);
        }
        //canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);
        int canavs_width=canvas.getWidth();
        int canavs_height=canvas.getHeight();
        canvas.setMatrix(mCanvasMatrix);
        //canvas.setMatrix(mMatrix);
        if(mDrawable!=null){
            //mDrawable.draw(canvas);
            Log.v("Log_tag", "draw with Canvas is done  W:"+ canavs_width+"H:"+ canavs_height);
        }
        //canvas.restore();
    }

    private float MAX_SCALE = 2f;
    private int DOUBLE_TAP_SECOND = 400;

    private float CANVAS_MAX_SCALE=2f;

    float rect_x1=50;
    float rect_y1=150;

    private Matrix mMatrix;
    private Matrix mCanvasMatrix;

    private final float[] mCanvasMatrixValues=new float[9];
    private final float[] mMatrixValues = new float[9];
    RectF orignalRect;
    private Drawable mDrawable;
    private ImageView mImageView;
    // display width height.
    private int mWidth;
    private int mHeight;

    private int mIntrinsicWidth;
    private int mIntrinsicHeight;

    private int mCanvasWidth;
    private int mCanvasHeight;


    private float mScale;
    private float mMinScale;

    private float mCanvasMinScale;

    // double tap for determining
    private long mLastTime = 0;
    private boolean isDoubleTap;
    private int mDoubleTapX;
    private int mDoubleTapY;

    private float mPrevDistance;
    private boolean isScaling;

    private int mPrevMoveX;
    private int mPrevMoveY;

    String TAG = "ScaleImageView";

    public ImageViewScale(Context context, AttributeSet attr) {
        super(context, attr);
        initialize();
    }

    public ImageViewScale(Context context) {
        super(context);
        initialize();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        this.initialize();

    }

    private void initialize() {
        this.setScaleType(ScaleType.MATRIX);
        this.mMatrix = new Matrix();
        Drawable d = getDrawable();
        mDrawable=d;
        if (d != null) {
            mIntrinsicWidth = d.getIntrinsicWidth();
            mIntrinsicHeight = d.getIntrinsicHeight();
            setOnTouchListener(this);
        }
    }

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        Log.v("Log_tag", "Size are here "+ l + t + r+ b);
        mWidth = r - l;
        mHeight = b - t;

        mMatrix.reset();
        mScale = (float) r / (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];
    }
    //New Added
    protected float getCanvasValue(Matrix matrix,int whichvalues){
        mCanvasMatrix.getValues(mCanvasMatrixValues);
        return mCanvasMatrixValues[whichvalues];
    }

    protected float getScale() {
        return getValue(mMatrix, Matrix.MSCALE_X);
    }

    //New added  Method
    protected float getCanvasScale(){
        return getCanvasValue(mCanvasMatrix, Matrix.MSCALE_X);
    }

    protected float getTranslateX() {
        return getValue(mMatrix, Matrix.MTRANS_X);
    }

    //New added Method
    protected float getCanvasTranslateX(){
        return getCanvasValue(mCanvasMatrix, Matrix.MTRANS_X);
    }


    protected float getTranslateY() {
        return getValue(mMatrix, Matrix.MTRANS_Y);
    }

    //New Added Method
    protected float getCanvasTranslateY(){
        return getCanvasValue(mCanvasMatrix, 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);
        }
    }




    protected 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);
    }


    protected void zoomToCanvas(float scale,int x,int y){
        if(getCanvasScale()* scale<mCanvasMinScale){
            return;
        }

        if(scale>=1 && getCanvasScale()*scale> CANVAS_MAX_SCALE){
            return;
        }
        mCanvasMatrix.postScale(scale, scale);



    }

    public void cutting() {
        int width = (int) (mIntrinsicWidth * getScale());
        int height = (int) (mIntrinsicHeight * getScale());
        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 FloatMath.sqrt(x * x + y * y);
    }

    private float dispDistance() {
        return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        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 {
                if (System.currentTimeMillis() <= mLastTime + DOUBLE_TAP_SECOND) {
                    if (30 > Math.abs(mPrevMoveX - event.getX())
                            + Math.abs(mPrevMoveY - event.getY())) {
                        isDoubleTap = true;
                        mDoubleTapX = (int) event.getX();
                        mDoubleTapY = (int) event.getY();
                    }
                }
                mLastTime = System.currentTimeMillis();
                mPrevMoveX = (int) event.getX();
                mPrevMoveY = (int) event.getY();
            }
            break;
        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;
                if (isDoubleTap) {
                    if (30 > Math.abs(mDoubleTapX - event.getX())
                            + Math.abs(mDoubleTapY - event.getY())) {
                        maxZoomTo(mDoubleTapX, mDoubleTapY);
                        cutting();
                    }
                }
            }
            isDoubleTap = false;
            break;
        }
        return true;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int count_touch=event.getPointerCount();
        switch(event.getAction()){
        case MotionEvent.ACTION_UP:
            float point_x=event.getX();
            float point_y=event.getY();
            rect_x1=point_x;
            rect_y1=point_y;
            if(count_touch==1){
                orignalRect=new RectF(rect_x1-30, rect_y1-30, rect_x1+30,  rect_y1+30);
                invalidate();
            }
            break;
        }

        return super.onTouchEvent(event);
    }
}
like image 260
Herry Avatar asked May 07 '12 12:05

Herry


People also ask

How do you highlight in ImageView?

You need to assign the src attribute of the ImageView a state list drawable. In other words, that state list would have a different image for selected, pressed, not selected, etc. - that's how the Twitter App does it. The Google IO Schedule app has a good example of this.

How can I access ImageView in android?

Open “res/layout/main. xml” file, just add an ImageView and Button for demonstration. By default, imageView1 will display “android.

How do you save a zoomed picture on android?

Move the zoomed image up, down left or right in the LCD screen using the CONTROL BUTTON . When the desired modifications are complete, press the shutter button to store the picture.


2 Answers

You might want to checkout Matrix.mapRect. Use this method to transform the rectangle by the same amount as the image in the imageview.

boolean onTouch(MotionEvent ev) {
    ....
    // this rect dimensions should be initial values and should be a member.
    mOriginalRect = new RectF(rect_x1-30, rect_y1-30, rect_x1+30, rect_y1+30); 
    .....
}

@Override
protected void onDraw(Canvas canvas) {
    ....
    mCanvasMatrix = canvas.getMatrix();  ///matrix should have scale values..
    mCanvasMatrix.mapRect(tempRect, mOriginalRect); // mOriginalRect is src 
    canvas.drawRect(tempRect, myPaint);   // draw tempRect..
    ....
}
like image 195
Ronnie Avatar answered Oct 18 '22 18:10

Ronnie


You probably want to extend ImageView, in the views onDraw(Canvas) you would draw the rectangle.

Extend ImageView once in order to make in pinch-to-zoom (which should use the Matrix in the image view to implement the pinch zoom)

Extend it again to take a rectangle, transform it using the image matrix and draw it after the super.draw() call.

like image 32
HaMMeReD Avatar answered Oct 18 '22 17:10

HaMMeReD