确实,Bitmap 和Canvas 都具有密度属性,如果画布和位图的密度不同,则绘制位图会自动缩放位图。
来自Bitmap.setDensity() 文档:
指定此位图的密度。当位图绘制到
也有密度的画布,它会被适当地缩放。
您可以致电bitmap.setDensity(Bitmap.DENSITY_NONE) 以完全禁用此自动缩放行为。如果从资源中加载位图,放在drawable-nodpi 下就足够了。
出于好奇:此行为背后的逻辑在Canvas.cpp(android.graphics.Canvas 的本机部分)中的drawBitmap__BitmapFFPaint() 方法中实现:
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();
}
}