How to implement freehand image cropping in androi

2019-03-15 12:45发布

问题:

How can i implement freehand cropping on Imageview.

Using below code i'm able to draw freehand path and can able to crop image but i'm facing some other problems

Now what i have tried so far

Here is my code

code for cropping image using canvas

public class SomeView extends View implements View.OnTouchListener {
    private Paint paint;

    int DIST = 2;
    boolean flgPathDraw = true;

    Point mfirstpoint = null;
    boolean bfirstpoint = false;

    Point mlastpoint = null;

    Bitmap bitmap;

    Context mContext;

    public SomeView(Context c, Bitmap bitmap) {
        super(c);

        mContext = c;
        this.bitmap = bitmap;

        setFocusable(true);
        setFocusableInTouchMode(true);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0));
        paint.setStrokeWidth(5);
        paint.setColor(Color.RED);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);

        this.setOnTouchListener(this);
        points = new ArrayList<Point>();

        bfirstpoint = false;
    }

    public SomeView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mContext = context;
        setFocusable(true);
        setFocusableInTouchMode(true);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        paint.setColor(Color.RED);

        points = new ArrayList<Point>();
        bfirstpoint = false;

        this.setOnTouchListener(this);
    }

    public void onDraw(Canvas canvas) {

        /*Rect dest = new Rect(0, 0, getWidth(), getHeight());

        paint.setFilterBitmap(true);
        canvas.drawBitmap(bitmap, null, dest, paint);*/

        canvas.drawBitmap(bitmap, 0, 0, null);

        Path path = new Path();
        boolean first = true;

        for (int i = 0; i < points.size(); i += 2) {
            Point point = points.get(i);
            if (first) {
                first = false;
                path.moveTo(point.x, point.y);
            } else if (i < points.size() - 1) {
                Point next = points.get(i + 1);
                path.quadTo(point.x, point.y, next.x, next.y);
            } else {
                mlastpoint = points.get(i);
                path.lineTo(point.x, point.y);
            }
        }
        canvas.drawPath(path, paint);
    }

    public boolean onTouch(View view, MotionEvent event) {
        // if(event.getAction() != MotionEvent.ACTION_DOWN)
        // return super.onTouchEvent(event);

        Point point = new Point();
        point.x = (int) event.getX();
        point.y = (int) event.getY();

        if (flgPathDraw) {

            if (bfirstpoint) {

                if (comparepoint(mfirstpoint, point)) {
                    // points.add(point);
                    points.add(mfirstpoint);
                    flgPathDraw = false;
                    showcropdialog();
                } else {
                    points.add(point);
                }
            } else {
                points.add(point);
            }

            if (!(bfirstpoint)) {

                mfirstpoint = point;
                bfirstpoint = true;
            }
        }

        invalidate();
        Log.e("Hi  ==>", "Size: " + point.x + " " + point.y);

        if (event.getAction() == MotionEvent.ACTION_UP) {
            Log.d("Action up*****~~>>>>", "called");
            mlastpoint = point;
            if (flgPathDraw) {
                if (points.size() > 12) {
                    if (!comparepoint(mfirstpoint, mlastpoint)) {
                        flgPathDraw = false;
                        points.add(mfirstpoint);
                        showcropdialog();
                    }
                }
            }
        }

        return true;
    }

    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 (points.size() < 10) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }

    }

    public void fillinPartofPath() {
        Point point = new Point();
        point.x = points.get(0).x;
        point.y = points.get(0).y;

        points.add(point);
        invalidate();
    }

    public void resetView() {
        points.clear();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        paint.setColor(Color.RED);

        points = new ArrayList<Point>();
        bfirstpoint = false;

        flgPathDraw = true;
        invalidate();
    }

    private void showcropdialog() {
        DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent;
                switch (which) {
                    case DialogInterface.BUTTON_POSITIVE:
                        cropImage();
                        break;

                    case DialogInterface.BUTTON_NEGATIVE:
                        /*// No button clicked

                        intent = new Intent(mContext, DisplayCropActivity.class);
                        intent.putExtra("crop", false);
                        mContext.startActivity(intent);

                        bfirstpoint = false;*/
                        resetView();

                        break;
                }
            }
        };

        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setMessage("Do you Want to save Crop or Non-crop image?")
                .setPositiveButton("Crop", dialogClickListener)
                .setNegativeButton("Non-crop", dialogClickListener).show()
                .setCancelable(false);
    }
}

Code for cropping bitmap

public void cropImage() {

    setContentView(R.layout.activity_picture_preview);

    imageView = findViewById(R.id.image);

    int widthOfscreen = 0;
    int heightOfScreen = 0;

    DisplayMetrics dm = new DisplayMetrics();
    try {
        getWindowManager().getDefaultDisplay().getMetrics(dm);
    } catch (Exception ex) {
    }
    widthOfscreen = dm.widthPixels;
    heightOfScreen = dm.heightPixels;

    Bitmap bitmap2 = mBitmap;

    Bitmap resultingImage = Bitmap.createBitmap(widthOfscreen,
            heightOfScreen, bitmap2.getConfig());

    Canvas canvas = new Canvas(resultingImage);

    Paint paint = new Paint();

    Path path = new Path();

    for (int i = 0; i < points.size(); i++) {

        path.lineTo(points.get(i).x, points.get(i).y);

    }

    canvas.drawPath(path, paint);

    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    canvas.drawBitmap(bitmap2, 0, 0, paint);

    imageView.setImageBitmap(resultingImage);

}

Here what i get result using above code

Cropping image using Finger touch

This image showing result after cropping image

This is my expected output

Please check below screenshot for the same

This Image showing cropping image using Finger touch

This image showing result after cropping image

The Below problems i'am facing in above code

  • Unable to set bitmap in full screen using canvas
  • If i set bitmap in full screen in canvas than image is stretching
  • How to set transparent background to cropped bitmap
  • Unable to add border to cropped image
  • The result of image Cropping is not as expected

Here are some other post that i have tried so far

  • crop free hand selected part of image

  • Freehand cropping on the image in android

  • Android Freehand bitmap cropping

  • Android: Free Cropping of Image

  • implemanting freehand crop in android

  • Get the free hand cropping Image From the original in android

  • Darken parts of a free-hand cropped image in android

  • Android-freehand-image-crop

  • Android Top Image Cropper Libraries

  • Crop a shape from an Android bitmap

  • Freehand Image Crop draw inside bitmap region

none of the above post help to achieve my excepted output

If need more information please do let me know. Thanks in advance. Your efforts will be appreciated.

回答1:

In general, your code looks OK, but I have a few comments:

  • Unable to set bitmap in full screen using canvas
  • If i set bitmap in full screen in canvas than image is stretching
    The portion of the image that you are selecting needs to be placed in a smaller bitmap so the layout XML can position it as you like. You are creating a bitmap that is full screen. See the following demo for details.

  • How to set transparent background to cropped bitmap
    I am unclear about what the issue is.

  • Unable to add border to cropped image

  • The result of image Cropping is not as expected
    See below.

Here is a small demo app using your code. You didn't provide an MCVE, so I threw the following together for demonstration purposes. Other than getting the app to function I think that the only change is to draw the border in MainActivity.java. The border width starts at the cut-out path that the user draws and reaches inward to the cut-out. If you want to actually frame the cutout without losing any pixels, then you will need to expand the path to accommodate the frame which I arbitrarily set to 20 pixels.

I also had to create the layouts used, so you may want to look at those. They are posted below.

Here is the demo video with the code to follow:

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private Bitmap mBitmap;
    private SomeView mSomeView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog);
        mSomeView = new SomeView(this, mBitmap);
        LinearLayout layout = findViewById(R.id.layout);
        LinearLayout.LayoutParams lp =
            new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                                          LinearLayout.LayoutParams.WRAP_CONTENT);
        layout.addView(mSomeView, lp);
    }

    public void cropImage() {
        setContentView(R.layout.activity_picture_preview);
        ImageView imageView = findViewById(R.id.image);

        Bitmap fullScreenBitmap =
            Bitmap.createBitmap(mSomeView.getWidth(), mSomeView.getHeight(), mBitmap.getConfig());

        Canvas canvas = new Canvas(fullScreenBitmap);

        Path path = new Path();
        List<Point> points = mSomeView.getPoints();
        for (int i = 0; i < points.size(); i++) {
            path.lineTo(points.get(i).x, points.get(i).y);
        }

        // Cut out the selected portion of the image...
        Paint paint = new Paint();
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(mBitmap, 0, 0, paint);

        // Frame the cut out portion...
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10f);
        canvas.drawPath(path, paint);

        // Create a bitmap with just the cropped area.
        Region region = new Region();
        Region clip = new Region(0, 0, fullScreenBitmap.getWidth(), fullScreenBitmap.getHeight());
        region.setPath(path, clip);
        Rect bounds = region.getBounds();
        Bitmap croppedBitmap =
            Bitmap.createBitmap(fullScreenBitmap, bounds.left, bounds.top,
                                bounds.width(), bounds.height());

        imageView.setImageBitmap(croppedBitmap);
    }
}

SomeView.java
I don't think there were any substantive changes to this class.

public class SomeView extends View implements View.OnTouchListener {  
    private Paint paint;  
    private List<Point> points;  

    int DIST = 2;  
    boolean flgPathDraw = true;  

    Point mfirstpoint = null;  
    boolean bfirstpoint = false;  

    Point mlastpoint = null;  

    Bitmap bitmap;  

    Context mContext;  


        public SomeView(Context c, Bitmap bitmap) {  
            super(c);  

            mContext = c;  
            this.bitmap = bitmap;  

            setFocusable(true);  
            setFocusableInTouchMode(true);  

            paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
            paint.setStyle(Paint.Style.STROKE);  
            paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0));  
            paint.setStrokeWidth(5);  
            paint.setColor(Color.RED);  
            paint.setStrokeJoin(Paint.Join.ROUND);  
            paint.setStrokeCap(Paint.Cap.ROUND);  

            this.setOnTouchListener(this);  
            points = new ArrayList<Point>();  

            bfirstpoint = false;  
        }  

        public SomeView(Context context, AttributeSet attrs) {  
            super(context, attrs);  

            mContext = context;  
            setFocusable(true);  
            setFocusableInTouchMode(true);  

            paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
            paint.setStyle(Paint.Style.STROKE);  
            paint.setStrokeWidth(5);  
            paint.setColor(Color.RED);  

            points = new ArrayList<Point>();  
            bfirstpoint = false;  

            this.setOnTouchListener(this);  
        }  

        public void onDraw(Canvas canvas) {  

            /*Rect dest = new Rect(0, 0, getWidth(), getHeight());  

     paint.setFilterBitmap(true); canvas.drawBitmap(bitmap, null, dest, paint);*/  
      canvas.drawBitmap(bitmap, 0, 0, null);  

            Path path = new Path();  
            boolean first = true;  

            for (int i = 0; i < points.size(); i += 2) {  
                Point point = points.get(i);  
                if (first) {  
                    first = false;  
                    path.moveTo(point.x, point.y);  
                } else if (i < points.size() - 1) {  
                    Point next = points.get(i + 1);  
                    path.quadTo(point.x, point.y, next.x, next.y);  
                } else {  
                    mlastpoint = points.get(i);  
                    path.lineTo(point.x, point.y);  
                }  
            }  
            canvas.drawPath(path, paint);  
        }  

        public boolean onTouch(View view, MotionEvent event) {  
            // if(event.getAction() != MotionEvent.ACTION_DOWN)  
     // return super.onTouchEvent(event);  
      Point point = new Point();  
            point.x = (int) event.getX();  
            point.y = (int) event.getY();  

            if (flgPathDraw) {  

                if (bfirstpoint) {  

                    if (comparepoint(mfirstpoint, point)) {  
                        // points.add(point);  
      points.add(mfirstpoint);  
                        flgPathDraw = false;  
                        showcropdialog();  
                    } else {  
                        points.add(point);  
                    }  
                } else {  
                    points.add(point);  
                }  

                if (!(bfirstpoint)) {  

                    mfirstpoint = point;  
                    bfirstpoint = true;  
                }  
            }  

            invalidate();  
            Log.e("Hi  ==>", "Size: " + point.x + " " + point.y);  

            if (event.getAction() == MotionEvent.ACTION_UP) {  
                Log.d("Action up*****~~>>>>", "called");  
                mlastpoint = point;  
                if (flgPathDraw) {  
                    if (points.size() > 12) {  
                        if (!comparepoint(mfirstpoint, mlastpoint)) {  
                            flgPathDraw = false;  
                            points.add(mfirstpoint);  
                            showcropdialog();  
                        }  
                    }  
                }  
            }  

            return true;  
        }  

        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 (points.size() < 10) {  
                    return false;  
                } else {  
                    return true;  
                }  
            } else {  
                return false;  
            }  

        }  

        public void fillinPartofPath() {  
            Point point = new Point();  
            point.x = points.get(0).x;  
            point.y = points.get(0).y;  

            points.add(point);  
            invalidate();  
        }  

        public void resetView() {  
            points.clear();  
            paint.setColor(Color.WHITE);  
            paint.setStyle(Paint.Style.STROKE);  

            paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
            paint.setStyle(Paint.Style.STROKE);  
            paint.setStrokeWidth(5);  
            paint.setColor(Color.RED);  

            points = new ArrayList<Point>();  
            bfirstpoint = false;  

            flgPathDraw = true;  
            invalidate();  
        }  

        private void showcropdialog() {  
            DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {  
                @Override  
      public void onClick(DialogInterface dialog, int which) {  
                    Intent intent;  
                    switch (which) {  
                        case DialogInterface.BUTTON_POSITIVE:  
                            ((MainActivity) mContext).cropImage();  
                            break;  

                        case DialogInterface.BUTTON_NEGATIVE:  
                            /*// No button clicked  

     intent = new Intent(mContext, DisplayCropActivity.class); intent.putExtra("crop", false); mContext.startActivity(intent);  
     bfirstpoint = false;*/  resetView();  

                            break;  
                    }  
                }  
            };  

            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);  
            builder.setMessage("Do you Want to save Crop or Non-crop image?")  
                .setPositiveButton("Crop", dialogClickListener)  
                .setNegativeButton("Non-crop", dialogClickListener).show()  
                .setCancelable(false);  
        }  

        public List<Point> getPoints() {  
            return points;  
        }  
    }

activity_main.xml

<LinearLayout 
  android:id="@+id/layout"  
  xmlns:tools="http://schemas.android.com/tools"  
  android:layout_width="match_parent"  
  android:layout_height="match_parent"  
  android:orientation="vertical"  
  tools:context=".MainActivity"/>

activity_picture_preview.xml

<android.support.constraint.ConstraintLayout x
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:srcCompat="@drawable/dog" />
</android.support.constraint.ConstraintLayout> 

If you want to create a cropped bitmap with a 100px border, use the following code in cropImage():

    // Create a bitmap with just the cropped area.
    Region region = new Region();
    Region clip = new Region(0, 0, fullScreenBitmap.getWidth(), fullScreenBitmap.getHeight());
    region.setPath(path, clip);
    Rect sourceBounds = region.getBounds();
    Rect destBounds =
        new Rect(CROPPED_MARGIN, CROPPED_MARGIN, sourceBounds.width() + CROPPED_MARGIN,
                 sourceBounds.height() + CROPPED_MARGIN);
    Bitmap croppedBitmap =
        Bitmap.createBitmap(sourceBounds.width() + CROPPED_MARGIN * 2,
                            sourceBounds.height() + CROPPED_MARGIN * 2, mBitmap.getConfig());
    canvas.setBitmap(croppedBitmap);
    canvas.drawBitmap(fullScreenBitmap, sourceBounds, destBounds, null);

    imageView.setImageBitmap(croppedBitmap);

    // Add as member variable.
    private static final int CROPPED_MARGIN = 100;


回答2:

I have tried lots of solution for this problem in my project, but this code is working. Here, i put my own project's Code Here. You can use it, if you found your solution in it.

public class CropView extends View implements View.OnTouchListener {
public static final String INTENT_KEY_CROP = "crop";
public static final String CACHE_KEY = "bitmap";

public static List<Point> points;
boolean flgPathDraw = true;
boolean bFirstPoint = false;
private Point firstPoint = null;
private Point lastPoint = null;

private final Bitmap originalImageBitmap;
private int canvasWidth;
private int canvasHeight;
private Paint paint;
private Context context;
private static LruCache<String, Bitmap> mMemoryCache;
private final ImageCropListener imageCropListener;

public interface ImageCropListener {
    void onClickDialogPositiveButton();
    void onClickDialogNegativeButton();
}

public static Bitmap getBitmapFromMemCache() {
    return mMemoryCache.get(CACHE_KEY);
}


public CropView(Context c, Bitmap bm, ImageCropListener listener) {
    super(c);

    context = c;
    setFocusable(true);
    setFocusableInTouchMode(true);
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setStyle(Paint.Style.STROKE);
    paint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
    paint.setStrokeWidth(5);
    paint.setColor(Color.WHITE);

    this.setOnTouchListener(this);
    points = new ArrayList<>();

    bFirstPoint = false;
    this.originalImageBitmap = bm;
    this.imageCropListener = listener;

    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in kilobytes rather than
            // number of items.
            return bitmap.getByteCount() / 1024;
        }
    };

 }

 public CropView(Context context, AttributeSet attrs, Bitmap bm, 
 ImageCropListener listener) {
    super(context, attrs);
    this.context = context;
    setFocusable(true);
    setFocusableInTouchMode(true);

    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(2);
    paint.setColor(Color.WHITE);

    this.setOnTouchListener(this);
    points = new ArrayList<>();
    bFirstPoint = false;
    this.originalImageBitmap = bm;
    this.imageCropListener = listener;
}

public void addBitmapToMemoryCache(Bitmap bitmap) {
    if (getBitmapFromMemCache() == null) {
        mMemoryCache.put(CACHE_KEY, bitmap);
    }
}

private float calcBitmapScale(int canvasWidth, int canvasHeight, int bmpWidth, int bmpHeight) {

    float scale = (float)canvasWidth / (float)bmpWidth;
    float tmp = bmpHeight * scale;

    if (tmp < canvasHeight) {
        scale = (float)canvasHeight / (float)bmpHeight;
        return scale;
    }

    return scale;
}

public void onDraw(Canvas canvas) {
    canvasWidth = canvas.getWidth();
    canvasHeight = canvas.getHeight();

   /* int bmpWidth = this.originalImageBitmap.getWidth();
    int bmpHeight = this.originalImageBitmap.getHeight();


    float toCanvasScale = this.calcBitmapScale(canvasWidth, canvasHeight, bmpWidth, bmpHeight);


    float diffX = (bmpWidth * toCanvasScale - canvasWidth);
    float diffY = (bmpHeight * toCanvasScale - canvasHeight);


    float addX = (diffX / toCanvasScale) / 2;
    float addY = (diffY / toCanvasScale) / 2;


    Rect rSrc = new Rect((int)addX, (int)addY,
            (int)((canvasWidth / toCanvasScale) + addX), (int)((canvasHeight / 
    toCanvasScale) + addY));
    RectF rDest = new RectF(0, 0, canvasWidth, canvasHeight);
    */
    canvas.drawBitmap(originalImageBitmap, 0, 0, null);

    Path cropAreaPath = new Path();
    boolean isFirstPoint = true;

    for (int i = 0; i < points.size(); i += 2) {
        Point point = points.get(i);
        if (isFirstPoint) {
            isFirstPoint = false;
            // 最初の処理でPathのx,y座標をpointの座標に移動する
            cropAreaPath.moveTo(point.x, point.y);
        } else if (i < points.size() - 1) {
            Point next = points.get(i + 1);
            cropAreaPath.quadTo(point.x, point.y, next.x, next.y);
        } else {
            lastPoint = points.get(i);
            cropAreaPath.lineTo(point.x, point.y);
        }
    }
    canvas.drawPath(cropAreaPath, paint);
}

public boolean onTouch(View view, MotionEvent event) {
    Point point = new Point();
    point.x = (int) event.getX();
    point.y = (int) event.getY();

    if (flgPathDraw) {
        if (bFirstPoint) {
            if (comparePoint(firstPoint, point)) {
                // points.add(point);
                points.add(firstPoint);
                flgPathDraw = false;
                showCropDialog();
            } else {
                points.add(point);
            }
        } else {
            points.add(point);
        }

        if (!(bFirstPoint)) {

            firstPoint = point;
            bFirstPoint = true;
        }
    }

    invalidate();
    //Log.e("Hi  ==>", "Size: " + point.x + " " + point.y);

    if (event.getAction() == MotionEvent.ACTION_UP) {
        Log.d("Action up***>", "called");
        lastPoint = point;
        if (flgPathDraw) {
            if (points.size() > 12) {
                if (!comparePoint(firstPoint, lastPoint)) {
                    flgPathDraw = false;
                    points.add(firstPoint);
                    showCropDialog();
                }
            }
        }
    }

    return true;
}

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 (points.size() < 10) {
            return false;
        } else {
            return true;
        }
    } else {
        return false;
    }

}

public void fillinPartofPath() {
    Point point = new Point();
    point.x = points.get(0).x;
    point.y = points.get(0).y;

    points.add(point);
    invalidate();
}

public void resetView() {
    points.clear();
    paint.setColor(Color.WHITE);
    paint.setStyle(Paint.Style.STROKE);
    flgPathDraw = true;
    invalidate();
}

private void showCropDialog() {
    final Bitmap croppedImage = cropImage(this.originalImageBitmap);
    DialogInterface.OnClickListener dialogClickListener = new 
    DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            switch (which) {
                case DialogInterface.BUTTON_POSITIVE:
                    addBitmapToMemoryCache(croppedImage);
                    imageCropListener.onClickDialogPositiveButton();
                    break;

                case DialogInterface.BUTTON_NEGATIVE:
                    bFirstPoint = false;
                    resetView();
                    imageCropListener.onClickDialogNegativeButton();
                    break;
            }
        }
    };

    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setMessage("Do you Want to save Crop or Non-crop image?")
            .setPositiveButton("Crop", dialogClickListener)
            .setNegativeButton("Cancel", dialogClickListener).show()
            .setCancelable(false);
}

private Bitmap cropImage(Bitmap image) {
    Bitmap cropImage = Bitmap.createBitmap(canvasWidth, canvasHeight, 
    image.getConfig());
    Canvas canvas = new Canvas(cropImage);
    Paint paint = new Paint();
    paint.setAntiAlias(true);

    Path path = new Path();
    for (int i = 0; i < CropView.points.size(); i++) {
        path.lineTo(CropView.points.get(i).x, CropView.points.get(i).y);
    }
    canvas.drawPath(path, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(originalImageBitmap, 0, 0, paint);

    return cropImage;
}

class Point {
    public float dy;
    public float dx;
    float x, y;

    @Override
    public String toString(){
        return x + ", " + y;
    }
}
}

Then You can get Crop Result..as like,

Bitmap cropBitmap = CropView.getBitmapFromMemCache();
                cropBitmap = getBitmapWithTransparentBG(cropBitmap,Color.WHITE);
                Drawable d = new BitmapDrawable(getResources(),cropBitmap);

public Bitmap getBitmapWithTransparentBG(Bitmap srcBitmap, int bgColor) {
    Bitmap result = srcBitmap.copy(Bitmap.Config.ARGB_8888, true);
    int nWidth = result.getWidth();
    int nHeight = result.getHeight();
    for (int y = 0; y < nHeight; ++y)
        for (int x = 0; x < nWidth; ++x) {
            int nPixelColor = result.getPixel(x, y);
            if (nPixelColor == bgColor)
                result.setPixel(x, y, Color.TRANSPARENT);
        }
    return result;
}

I Think, This code will be perfect for your problem solution.. Thanks



回答3:

The links you've posted are quite old.Why don't you consider adding a library?