Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing on canvas and multiple paint objects

I am trying to make an application where user can either choose to blur the image or can choose to paint on the screen (user can also do both of these at one canvas).

I have it pretty much working however, I am having a strange issue with the drawing on a first draw after the mode is changed from blur to paint or vice versa.

Please see the image below.

PAINT MODE

The paths drawn vertically is when user has paint mode selected. As you can see the first path contains paint from both blur paint object as well paint object (with red stroke). Any subsequent paths drawn now works fine.

BLUR MODE

Similarly you can see, after drawing two vertical paths, user switches the mode to blur and draws horizontal paths in this mode. This time similar to above first path is a mixture of two paint objects and subsequent paths works fine.

Please see the code posted below and It would be great if you can suggest what could be causing the problem.

enter image description here

ArrayList<DrawCommands> path_color_stroke_list = new ArrayList<DrawCommands>();
ArrayList<DrawCommands> path_color_stroke_list_undone = new ArrayList<DrawCommands>();
ArrayList<BlurCommands> path_blur_list = new ArrayList<BlurCommands>();
ArrayList<BlurCommands> path_blur_list_undone = new ArrayList<BlurCommands>();
ArrayList<EditTextDrawCommands> editTextList = new ArrayList<EditTextDrawCommands>();

private Bitmap mBitmap;
private Paint transparentPaint;
private Paint mPaint;

public DrawingPanel(Context context, String imageStorageDir) {
    super(context);
    appContext = context;
    setFocusable(true);
    setFocusableInTouchMode(true);
    setClickable(true);
    this.setOnTouchListener(this);

    mPath = new Path();
    setDefaultPaintAttributes();

    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inSampleSize = 8;

    blurRefImage = BitmapFactory.decodeResource(getResources(), R.drawable.canvas_test, bmOptions);
    canvasBackImage = BitmapFactory.decodeResource(getResources(), R.drawable.canvas_test);


    //stretch this small image to the size of the device so that it will be stretched and will already be blurred
    blurRefImage = Bitmap.createScaledBitmap(blurRefImage, Utilities.getDeviceWidth(), Utilities.getDeviceHeight(), true);
    blurRefImage = BlurBuilder.blurFullImage(appContext, blurRefImage, 20);

    mBitmap = Bitmap.createBitmap(Utilities.getDeviceWidth(), Utilities.getDeviceHeight(), Bitmap.Config.ARGB_8888);

    mCanvas = new Canvas(mBitmap);

}

protected void setDefaultPaintAttributes() {
    mPaint = new Paint();
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(30);

    //mPaint.setColor(0xcc000000);

    transparentPaint = new Paint();
    transparentPaint.setStyle(Paint.Style.STROKE);
    transparentPaint.setStrokeJoin(Paint.Join.ROUND);
    transparentPaint.setStrokeCap(Paint.Cap.ROUND);
    transparentPaint.setStrokeWidth(60);
    transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

}

@Override
protected void onDraw(Canvas canvas) {
    mCanvas.drawBitmap(canvasBackImage, 0, 0, mPaint);

    //Draw Blur
    for (BlurCommands path_blur : path_blur_list) {
        mCanvas.drawPath(path_blur.getPath(), transparentPaint);
    }

    //Draw Paints
    for (DrawCommands path_clr : path_color_stroke_list) {
        mCanvas.drawPath(path_clr.getPath(), mPaint);
    }

    switch (CURRENT_MODE) {
        case MODE_BLUR:
            mCanvas.drawPath(mPath, transparentPaint);
            break;
        case MODE_PAINT:
            mCanvas.drawPath(mPath, mPaint);
            break;
    }

    canvas.drawBitmap(blurRefImage, 0, 0, mPaint);
    canvas.drawBitmap(mBitmap, 0, 0, mPaint);

}

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    switch (CURRENT_MODE) {
        case MODE_BLUR:
            break;
        case MODE_PAINT:
            break;
        default:
            break;
    }
}

private void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);

    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        switch (CURRENT_MODE) {
            case MODE_BLUR:
            case MODE_PAINT:
                mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
                mX = x;
                mY = y;
                break;
            default:
                break;
        }

    }

}

private void touch_up(MotionEvent event) {
    switch (CURRENT_MODE) {
        case MODE_BLUR:
            mPath.lineTo(mX, mY);
            mPath = new Path();
            path_blur_list.add(new BlurCommands(mPath, blurStrength, transparentPaint.getStrokeWidth()));
            break;
        case MODE_PAINT:
            mPath.lineTo(mX, mY);
            mPath = new Path();
            path_color_stroke_list.add(new DrawCommands(mPath, mPaint.getColor(), mPaint.getStrokeWidth()));
            Log.d(TAG, "Touch up: X: " + mX + " Y: " + mY);
            break;
        default:
            break;
    }
}
like image 445
Sahil Avatar asked Nov 25 '15 19:11

Sahil


2 Answers

You probably want to switch the order of the 2 lines in touch_up that clear the path (new Path), and that add ad the path to the list (first add, then clear)

like image 200
yoah Avatar answered Sep 20 '22 11:09

yoah


The error occurs because the mPath object is created matching the previous drawing mode since it was created on mouse-up with the previous drawing mode.

Move the mPath creation to touch_start and the current drawing mode will be used:

private void touch_start(float x, float y) {
    mPath = new Path();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    switch (CURRENT_MODE) {
        case MODE_BLUR:
            path_blur_list.add(new BlurCommands(mPath, blurStrength, transparentPaint.getStrokeWidth()));
            break;
        case MODE_PAINT:
            path_color_stroke_list.add(new DrawCommands(mPath, mPaint.getColor(), mPaint.getStrokeWidth()));
            break;
        default:
            break;
    }
}
...
private void touch_up(MotionEvent event) {
    mPath.lineTo(mX, mY);
}
like image 44
bebbo Avatar answered Sep 21 '22 11:09

bebbo