Как реализовать обрезку изображения от руки в Android?

Как я могу реализовать обрезку от руки на Imageview.

Используя приведенный ниже код, я могу нарисовать путь от руки и могу обрезать изображение, но я столкнулся с некоторыми другими проблемами

Теперь, что я пробовал до сих пор

Вот мой код

код для обрезки изображения с помощью холста

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

Код для обрезки растрового изображения

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

}

Вот что я получаю, используя приведенный выше код

Обрезка изображения с помощью касания пальцем

Это изображение показывает результат после обрезки изображения

Это мой ожидаемый результат

Пожалуйста, проверьте ниже скриншот для того же

Это изображение показывает обрезку изображения с помощью касания пальцем

Это изображение показывает результат после обрезки изображения

Ниже приведены проблемы, с которыми я сталкиваюсь в приведенном выше коде

  • Невозможно установить растровое изображение на весь экран, используя холст
  • Если я устанавливаю растровое изображение на весь экран в холсте, то изображение растягивается
  • Как установить прозрачный фон для обрезанного растрового изображения
  • Невозможно добавить рамку к обрезанному изображению
  • Результат обрезки изображения не такой, как ожидалось

Вот еще один пост, который я пробовал до сих пор

ни один из вышеперечисленных постов не помогает достичь моего исключенного вывода

Если вам нужна дополнительная информация, пожалуйста, дайте мне знать. Заранее спасибо. Ваши усилия будут оценены.

Ответы

Ответ 1

В целом ваш код выглядит нормально, но у меня есть несколько комментариев:

  • Невозможно установить растровое изображение на весь экран, используя холст
  • Если я устанавливаю растровое изображение на весь экран в холсте, то изображение растягивается
    Часть изображения, которую вы выбираете, должна быть размещена в меньшем растровом изображении, чтобы макет XML мог расположить его так, как вам нравится. Вы создаете растровое изображение на весь экран. Смотрите следующую демонстрацию для деталей.

  • Как установить прозрачный фон для обрезанного растрового изображения
    Мне неясно, в чем проблема.

  • Невозможно добавить рамку к обрезанному изображению

  • Результат обрезки изображения не такой, как ожидалось
    Увидеть ниже.

Вот небольшое демонстрационное приложение, использующее ваш код. Вы не предоставили MCVE, поэтому я собрал следующее для демонстрационных целей. Помимо того, что приложение работает, я думаю, что единственное изменение - это нарисовать границу в MainActivity.java. Ширина границы начинается у траектории выреза, которую рисует пользователь, и достигает внутрь от выреза. Если вы хотите создать рамку выреза без потери пикселей, вам нужно будет расширить путь, чтобы разместить кадр, который я произвольно установил на 20 пикселей.

Я также должен был создать используемые макеты, так что вы можете посмотреть на них. Они размещены ниже.

Вот демонстрационное видео с кодом для подражания:

enter image description here

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
Я не думаю, что в этом классе произошли какие-либо существенные изменения.

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> 

Если вы хотите создать обрезанное растровое изображение с границей в 100 пикселей, используйте следующий код в 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

Я пробовал много решений этой проблемы в моем проекте, но этот код работает. Здесь я поместил свой собственный код проекта здесь. Вы можете использовать его, если нашли в нем свое решение.

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

Тогда вы можете получить результат урожая.. как, например,

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

Думаю, этот код подойдет для решения вашей проблемы.. Спасибо

Ответ 3

Ссылки, которые вы разместили, довольно старые. Почему вы не планируете добавить библиотеку?