Search code examples
javaandroidandroid-drawableandroid-bitmapdrawbitmap

Cropped Bitmap not fitting to the center. (Hand free cropping.)


I'm trying to crop image using draw. And Its cropping as expected but i think not scaling the cropped part to center of new bitmap. You can see 2 pictures 1. Picture is what i own now. And 2. Picture is what i expect.

ORIGINAL IMAGE.

enter image description here

WHAT I HAVE

enter image description here

WHAT I NEED

enter image description here

I'm Cropping on SomeView and sending points to CropActivity and CropActivity crops the image and send it to the MainActivity.

Here is my CropActivity.Java

public class CropActivity extends Activity {

    ImageView compositeImageView;
    boolean crop;


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

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            crop = extras.getBoolean("crop");
        }
        int widthOfscreen = 512;
        int heightOfScreen = 512;

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

        compositeImageView = (ImageView) findViewById(R.id.our_imageview);

        Bitmap bitmap2 = SomeView.bitmap;

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

        Canvas canvas = new Canvas(resultingImage);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

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

        } else {
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
        }

        canvas.drawBitmap(bitmap2, 0, 0, paint);
        compositeImageView.setImageBitmap(resultingImage);


        Button donb = findViewById(R.id.donb);

        donb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent returnIntent = new Intent();

                ByteArrayOutputStream bStream = new ByteArrayOutputStream();
                resultingImage.compress(Bitmap.CompressFormat.PNG, 100, bStream);
                byte[] byteArray = bStream.toByteArray();

                returnIntent.putExtra("result",byteArray);
                setResult(2,returnIntent);
                finish();
             //   donb.setText("Dondum");
            }
        });






    }
}

Here is my SomeView.Java

public class SomeView extends View implements View.OnTouchListener {
    private Paint paint;
    public static List<Point> points;
    int DIST = 2;
    boolean flgPathDraw = true;
    public static final int PICK_IMAGE = 1;
    Point mfirstpoint = null;
    boolean bfirstpoint = false;

    Point mlastpoint = null;

  public static Bitmap bitmap;
    Context mContext;


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

        bitmap = b;
        mContext = 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(15);
        paint.setColor(Color.GREEN);


        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(2);
        paint.setColor(Color.WHITE);

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

    }

    public void onDraw(Canvas canvas) {
        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) {

            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);
        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:
                        // Yes button clicked
                        // bfirstpoint = false;

                        intent = new Intent(mContext, CropActivity.class);
                        intent.putExtra("crop", true);
                        ((Activity)mContext).startActivityForResult(intent,1);
                        break;

                    case DialogInterface.BUTTON_NEGATIVE:
                        // No button clicked

                        intent = new Intent(mContext, CropActivity.class);
                        intent.putExtra("crop", false);
                        ((Activity)mContext).startActivityForResult(intent,1);
                        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);
    }
}


class Point {

    public float dy;
    public float dx;
    float x, y;

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

And I'm really thankful about giving answers to me.


Solution

  • I was searching a solution for a 2 days. I looked all cropping answers in StackOverflow and did'nt find any solution to make it center. And trimming extra spaces. So I found a solution for avoiding extra spaces on cropped image....

    Using this function is making new Bitmap without extra spaces. Use function before resultingImage.

     static Bitmap trim(Bitmap source) {
            int firstX = 0, firstY = 0;
            int lastX = source.getWidth();
            int lastY = source.getHeight();
            int[] pixels = new int[source.getWidth() * source.getHeight()];
            source.getPixels(pixels, 0, source.getWidth(), 0, 0, source.getWidth(), source.getHeight());
            loop:
            for (int x = 0; x < source.getWidth(); x++) {
                for (int y = 0; y < source.getHeight(); y++) {
                    if (pixels[x + (y * source.getWidth())] != Color.TRANSPARENT) {
                        firstX = x;
                        break loop;
                    }
                }
            }
            loop:
            for (int y = 0; y < source.getHeight(); y++) {
                for (int x = firstX; x < source.getWidth(); x++) {
                    if (pixels[x + (y * source.getWidth())] != Color.TRANSPARENT) {
                        firstY = y;
                        break loop;
                    }
                }
            }
            loop:
            for (int x = source.getWidth() - 1; x >= firstX; x--) {
                for (int y = source.getHeight() - 1; y >= firstY; y--) {
                    if (pixels[x + (y * source.getWidth())] != Color.TRANSPARENT) {
                        lastX = x;
                        break loop;
                    }
                }
            }
            loop:
            for (int y = source.getHeight() - 1; y >= firstY; y--) {
                for (int x = source.getWidth() - 1; x >= firstX; x--) {
                    if (pixels[x + (y * source.getWidth())] != Color.TRANSPARENT) {
                        lastY = y;
                        break loop;
                    }
                }
            }
            return Bitmap.createBitmap(source, firstX, firstY, lastX - firstX, lastY - firstY);
        }