赞
踩
private void testDrawBitmap() { Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); int dstWidth = 192 * 9, dstHeight = 192 * 9; Bitmap desBitmap = Bitmap.createBitmap(dstWidth, dstHeight, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(desBitmap); Paint paint = new Paint(); //前者 long time0 = SystemClock.elapsedRealtime(); Matrix mMatrix = new Matrix(); mMatrix.postScale((float) dstWidth / srcBitmap.getWidth(), (float) dstHeight / srcBitmap.getHeight()); canvas.drawBitmap(srcBitmap, mMatrix, paint); Logger.d("Matrix time:" + (SystemClock.elapsedRealtime() - time0)); //后者 time0 = SystemClock.elapsedRealtime(); canvas.drawBitmap(srcBitmap, new Rect(0, 0, srcBitmap.getWidth(), srcBitmap.getHeight()), new Rect(0, 0, dstWidth, dstHeight), paint); Logger.d("Rect time:" + (SystemClock.elapsedRealtime() - time0)); srcBitmap.recycle(); desBitmap.recycle(); }
前者Matrix (22ms)比后者Rect(35ms)快,性能越差的设备越明显
尽量用Matrix替换Rect
通过8.0源码可以找到 public class Canvas extends BaseCanvas
在BaseCanvas有如下代码
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
throwIfHasHwBitmapInSwMode(paint);
nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(),
paint != null ? paint.getNativeInstance() : 0);
}
public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
@Nullable Paint paint) {
...
nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
bitmap.mDensity);
}
最终调用在 frameworks/base/core/jni/android_graphics_Canvas.cpp,其中有如下代码片段
static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, jlong matrixHandle, jlong paintHandle) { const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); } static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintHandle, jint screenDensity, jint bitmapDensity) { Canvas* canvas = get_canvas(canvasHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); if (screenDensity != 0 && screenDensity != bitmapDensity) { Paint filteredPaint; if (paint) { filteredPaint = *paint; } filteredPaint.setFilterQuality(kLow_SkFilterQuality); canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, &filteredPaint); } else { canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, paint); } }
即最终分别调用了
canvas->drawBitmap(bitmap, *matrix, paint);
canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, paint);
在frameworks/base/libs/hwui/hwui/Canvas.cpp有如下代码
Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::RenderNode* renderNode) {
if (uirenderer::Properties::isSkiaEnabled()) {
return new uirenderer::skiapipeline::SkiaRecordingCanvas(renderNode, width, height);
}
return new uirenderer::RecordingCanvas(width, height);
}
因此Canvas就是是RecordingCanvas,在 frameworks/base/libs/hwui/RecordingCanvas.cpp有如下代码
void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { if (matrix.isIdentity()) { drawBitmap(bitmap, paint); } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) && MathUtils::isPositive(matrix.getScaleX()) && MathUtils::isPositive(matrix.getScaleY())) { // SkMatrix::isScaleTranslate() not available in L SkRect src; SkRect dst; bitmap.getBounds(&src); matrix.mapRect(&dst, src); drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint); } else { save(SaveFlags::Matrix); concat(matrix); drawBitmap(bitmap, paint); restore(); } } void RecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { if (srcLeft == 0 && srcTop == 0 && srcRight == bitmap.width() && srcBottom == bitmap.height() && (srcBottom - srcTop == dstBottom - dstTop) && (srcRight - srcLeft == dstRight - dstLeft)) { // transform simple rect to rect drawing case into position bitmap ops, since they merge save(SaveFlags::Matrix); translate(dstLeft, dstTop); drawBitmap(bitmap, paint); restore(); } else { addOp(alloc().create_trivial<BitmapRectOp>( Rect(dstLeft, dstTop, dstRight, dstBottom), *(mState.currentSnapshot()->transform), getRecordedClip(), refPaint(paint), refBitmap(bitmap), Rect(srcLeft, srcTop, srcRight, srcBottom))); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。