Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

move,scale and crop the image in android like facebook profile picture

I want crop an image in my application.I tried a lot but not succeed.Its challenge to android developer. Is there any idea or reference to implement the features move,scale and crop the image in android like facebook upload profile pic. Now i am able to move, scale and crop and the image.But not consistant like facebook.I want to set fix image scale based on orientation.I attached the screen shot-3.

My code as below:-

crop_image.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/flCrop"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <ImageView
            android:id="@+id/img"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="matrix"
            android:src="@drawable/nature" />

        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:scaleType="fitXY"
            android:src="@drawable/blur_with_frame"
            android:visibility="visible" />

        <ImageView
            android:id="@+id/troll_face"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="10dp"
            android:layout_gravity="bottom" />
    </FrameLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="btnSelectPic"
            android:layout_marginRight="10dp"
            android:text="select Pic" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:onClick="btnCrop"
            android:text="Crop" />
    </LinearLayout>

</LinearLayout>

MainActivity.java

package com.hotveryspicy.maskimage;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.net.Uri;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;

import com.ipaulpro.afilechooser.utils.FileUtils;

public class MainActivity extends Activity implements OnTouchListener{
    ImageView img;
    FrameLayout flCrop;

    int framWidth = 0;
    int framHeight = 0;

    int imageHeight ;
    int imageWidth ;

    int cropImageWidth = 320;
    int cropImageHeight = 263;

    public static int SELECT_PHOTO =0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.crop_image);
        img = (ImageView) findViewById(R.id.img);
        flCrop = (FrameLayout) findViewById(R.id.flCrop);
        img.setOnTouchListener(this);


    }

    public void btnCrop(View v) {
        ImageView troll_face = (ImageView) findViewById(R.id.troll_face);
        makeMaskImage(troll_face, R.drawable.nature);
    }

    public void btnSelectPic(View v){
        Intent intent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (resultCode) {
        case RESULT_OK:
            Uri targetUri = data.getData();

            final String path = FileUtils.getPath(this, targetUri);

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;

            Bitmap bitmap = null;
            try {

                bitmap = BitmapFactory
                        .decodeFile(path);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            imageHeight = options.outHeight;
            imageWidth = options.outWidth;

            img.setOnTouchListener(MainActivity.this);

            img.setImageBitmap(bitmap);

            break;
        }
    }

    // Method of creating mask runtime
    public void makeMaskImage(ImageView mImageView, int mContent) {

        flCrop.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(flCrop.getDrawingCache());
        flCrop.setDrawingCacheEnabled(false);

        Log.e("TEST", "Frame W : " + framWidth + " H : " + framHeight);
        Log.e("TEST",
                "Bitmap W : " + bitmap.getWidth() + " H : "
                        + bitmap.getHeight());

        Bitmap result = Bitmap.createBitmap(bitmap, (framWidth / 2)
                - (cropImageWidth / 2) +1, (framHeight / 2)
                - (cropImageHeight / 2), cropImageWidth -2, cropImageHeight);
        mImageView.setImageBitmap(result);
        mImageView.setScaleType(ScaleType.CENTER);
        // mImageView.setBackgroundResource(R.drawable.frame);
    }





    @Override
      public boolean onTouch(View v, MotionEvent event) {
            // handle touch events here
            ImageView view = (ImageView) v;
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    savedMatrix.set(matrix);
                    start.set(event.getX(), event.getY());
                    mode = DRAG;
                    lastEvent = null;
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    if (oldDist > 10f) {
                        savedMatrix.set(matrix);
                        midPoint(mid, event);
                        mode = ZOOM;
                    }
                    lastEvent = new float[4];
                    lastEvent[0] = event.getX(0);
                    lastEvent[1] = event.getX(1);
                    lastEvent[2] = event.getY(0);
                    lastEvent[3] = event.getY(1);
                    d = rotation(event);
                    Log.e("MainActivity","MainActivity down d = "+d);
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    lastEvent = null;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == DRAG) {
                        matrix.set(savedMatrix);
                        float dx = event.getX() - start.x;
                        float dy = event.getY() - start.y;
                        Log.e("TEST","Dx : "+ dx+" Dy : "+ dy);
                        matrix.postTranslate(dx, dy);
                    } else if (mode == ZOOM) {
                        float newDist = spacing(event);
                        if (newDist > 10f) {
                            matrix.set(savedMatrix);
                            float scale = (newDist / oldDist);
                            matrix.postScale(scale, scale, mid.x, mid.y);
                        }
                        if (lastEvent != null && event.getPointerCount() == 3) {
                            newRot = rotation(event);
                            Log.e("MainActivity","MainActivity move d= "+d);
                            float r = newRot - d;
                            float[] values = new float[9];
                            matrix.getValues(values);
                            float tx = values[2];
                            float ty = values[5];
                            float sx = values[0];
                            float xc = (view.getWidth() / 2) * sx;
                            float yc = (view.getHeight() / 2) * sx;
                            matrix.postRotate(r, tx + xc, ty + yc);
                        }
                    }
                    break;
                 default:
                     view.setImageMatrix(matrix);
                     return true;
            }
            view.setImageMatrix(matrix);
            return true;
        }

        /**
         * Determine the space between the first two fingers
         */
        private float spacing(MotionEvent event) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return FloatMath.sqrt(x * x + y * y);
        }

        /**
         * Calculate the mid point of the first two fingers
         */
        private void midPoint(PointF point, MotionEvent event) {
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }

        /**
         * Calculate the degree to be rotated by.
         *
         * @param event
         * @return Degrees
         */
        private float rotation(MotionEvent event) {
            double delta_x = (event.getX(0) - event.getX(1));
            double delta_y = (event.getY(0) - event.getY(1));
            double radians = Math.atan2(delta_y, delta_x);
            return (float) Math.toDegrees(radians);
        }
        // these matrices will be used to move and zoom image
        private static Matrix matrix = new Matrix();
        private static Matrix savedMatrix = new Matrix();
        // we can be in one of these 3 states
        private static final int NONE = 0;
        private static final int DRAG = 1;
        private static final int ZOOM = 2;
        private int mode = NONE;
        // remember some things for zooming
        private PointF start = new PointF();
        private PointF mid = new PointF();
        private float oldDist = 1f;
        private float d = 0f;
        private float newRot = 0f;
        private float[] lastEvent = null;

        boolean flag ;
}

Looking my demo like:-

Screenshot-1 Screenshot-1

When zoom-out its looking as below image:- Screenshot-2 Screenshot-2

What exactly i am looking the solution :- Screenshot-3

Screenshot-3

If anyone have idea.Please help me.Thanks in advance...

like image 887
Jagdish Avatar asked Apr 07 '14 14:04

Jagdish


1 Answers

I had a similar requirement. Created a cropping component using modified Photoview and Cropper library. User can select image from Gallery or take a picture from Camera and then crop the image with move and scale, similar to Facebook profile picture cropping. Sharing the project on github.

Please check the github project here: https://github.com/ozeetee/AndroidImageZoomCrop

like image 86
Ozeetee Avatar answered Oct 23 '22 14:10

Ozeetee