draw only a portion of a Drawable/Bitmap

2019-02-13 21:58发布

问题:

I was wondering if it is possible to draw only a portion of a bitmap after it is loaded into memory without creating a new Bitmap. I see Drawable has a setBounds method but im not sure if it only draws the area set or just resizes the entire image. Thank you.

回答1:

Assuming you have a main canvas to draw to, you can use one of the drawBitmap methods of the Canvas class to draw a subset of the loaded bitmap.

public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)



回答2:

I searched for an answer to exactly this question in order to be able to reuse existing bitmaps for my image cache and to avoid memory fragmentation (and subsequent OutOfMemoryError...), which was caused by lots of bitmaps allocated in different parts of a memory space. As a result I created simple specialized "BitmapSubsetDrawable", which exposes itself as an arbitrary part of the underlined Bitmap (the part is determined by scrRect). Now I allocate a set of large enough Bitmaps once, and then reuse them ( canvas.drawBitmap(sourceBitmap, 0 , 0, null); on them...) for storage of different bitmaps.

The main code of the class is below, see BitmapSubsetDrawable.java for actual usage.

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;

public class BitmapSubsetDrawable extends Drawable {
    private Bitmap bitmap;
    private Rect scrRect;

    public BitmapSubsetDrawable(@NonNull Bitmap bitmap, @NonNull Rect srcRect) {
        this.bitmap = bitmap;
        this.scrRect = srcRect;
    }

    @Override
    public int getIntrinsicWidth() {
        return scrRect.width();
    }

    @Override
    public int getIntrinsicHeight() {
        return scrRect.height();
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawBitmap(bitmap, scrRect, getBounds(), null);
    }

    @Override
    public void setAlpha(int alpha) {
        // Empty
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        // Empty
    }

    @Override
    public int getOpacity() {
        return PixelFormat.OPAQUE;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }
}