Draw cirble bitmap in onDraw() ImageView without creating another bitmap

918 views Asked by At

I used options.inPurgeable to store bitmap in Ashmem when decoding bitmap. So that I don't wanna create more bitmap on Java heap (causes much GC) when drawing circle bitmap in onDraw() method. My code is below, but it doesn't work

private void init() {

        mRoundPaint = new Paint();
        mRoundPaint.setColor(Color.RED);
        mRoundPaint.setStyle(Paint.Style.FILL);
        mRoundPaint.setAntiAlias(true);
//      mRoundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

        mBmPaint = new Paint();
        mBmPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    }

protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mWidth = Math.min(w, h);
        rectDes = new Rect(0, 0, mWidth, mWidth);
    }

protected void onDraw(Canvas canvas) {

//      super.onDraw(canvas);

        if(getDrawable() == null)
            return;

        // Option 1
        Drawable drawable = getDrawable();
        canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mRoundPaint);
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        canvas.drawBitmap(bitmap, null, rectDes, mBmPaint);


        // Option 2
//      Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
//      canvas.drawBitmap(bitmap, null, rectDes, mBmPaint);
//      canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mRoundPaint);
}

Here is the result:
enter image description here
What I expect
enter image description here

I also used BitmapShader, It worked. But I don't know why BitmapShader keeps my bitmaps in Ashmem aren't removed by GC.

BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(shader);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mWidth / 2, mWidth/ 2, mWidth /2, paint);

I appreciate all your help.

EDIT Sorry, I forget to show my expected bitmap.

1

There are 1 answers

1
Kingfisher Phuoc On

Uhm, If I don't misunderstand, you want to get rounded bitmap from normal image? Here's my function to do so, you can try to change it whatever you like:

/**
 * Create rounded corner bitmap from given bitmap. The given bitmap will be
 * recycle after createing round image.
 * 
 * @param bitmap
 *            in {@link Bitmap} to parse
 * @param corner
 *            in {@link Integer} the corner of round rect image
 * @return rounded corner bitmap in {@link Bitmap}
 */
public static Bitmap parseBitmapToRoundedBitmap(Bitmap bitmap) {
    final int width = bitmap.getWidth();
    final int height = bitmap.getHeight();
    int size = Math.min(width, height);
    Bitmap output = Bitmap.createBitmap(size, size, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final Paint paint = new Paint();
    // Rect of bitmap
    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    // This is how we draw round rect image or circle image
    // Round rect image
    // canvas.drawRoundRect(new RectF(rect), roundPx, roundPx, paint);
    // Circle image
    final float radius = size / 2;
    canvas.drawCircle(size / 2, size / 2, radius, paint);
    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    Rect srcRect = new Rect(width / 2 - size / 2, height / 2 - size / 2,
            size, size);
    canvas.drawBitmap(bitmap, srcRect, new Rect(0, 0, size, size), paint);
    // Recycle bitmap if need.
    if (hasHoneycomb()) {
        bitmap = null;
    } else {
        bitmap.recycle();
        bitmap = null;
    }
    return output;
}