Drawing bitmap without scaling on Android

2019-02-15 15:24发布

I was trying to drawbitmap on a canvas. In the emulator, it seems that the image is blurred. Is it likely that the android automatically scaled the bitmap? I did try to disable the scaling such as

< supports-screens android:smallScreens="false" android:normalScreens="true" 
android:largeScreens="false" android:xlargeScreens="false" android:anyDensity="true" />

blur means if I have a pixel in the bitmap, I am seeing like 2x2 pixel. soemtimes a pixel is missing. so I assumed that Android automatically scaled it to fit different screens. I am just use WVGA and how do I prevent this scaling? Thanks.

2条回答
成全新的幸福
2楼-- · 2019-02-15 15:57

Indeed, both Bitmap and Canvas have a density property, drawing a bitmap automatically scales the bitmap if the densities of the canvas and bitmap differ.

From Bitmap.setDensity() documentation:

Specifies the density for this bitmap. When the bitmap is drawn to a Canvas that also has a density, it will be scaled appropriately.

You can call bitmap.setDensity(Bitmap.DENSITY_NONE) to disable this automatic scaling behavior altogether. If you load the bitmap from resources, placing it under drawable-nodpi should be enough.

For the curious: the logic behind this behavior is implemented in Canvas.cpp (native part of the android.graphics.Canvas), in the drawBitmap__BitmapFFPaint() method:

static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
                                      SkCanvas* canvas, SkBitmap* bitmap,
                                      jfloat left, jfloat top,
                                      SkPaint* paint, jint canvasDensity,
                                      jint screenDensity, jint bitmapDensity) {
    SkScalar left_ = SkFloatToScalar(left);
    SkScalar top_ = SkFloatToScalar(top);

    if (canvasDensity == bitmapDensity || canvasDensity == 0
            || bitmapDensity == 0) {
        if (screenDensity != 0 && screenDensity != bitmapDensity) {
            SkPaint filteredPaint;
            if (paint) {
                filteredPaint = *paint;
            }
            filteredPaint.setFilterBitmap(true);
            canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
        } else {
            canvas->drawBitmap(*bitmap, left_, top_, paint);
        }
    } else {
        canvas->save();
        SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
        canvas->translate(left_, top_);
        canvas->scale(scale, scale);

        SkPaint filteredPaint;
        if (paint) {
            filteredPaint = *paint;
        }
        filteredPaint.setFilterBitmap(true);

        canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);

        canvas->restore();
    }
}
查看更多
狗以群分
3楼-- · 2019-02-15 16:15

I think put you bitmap in drawable-nodpi folder will fix this problem. BTW, tag only be used by Google Play.

查看更多
登录 后发表回答