Save hardware accelerated android canvas as a bitmap

I am currently drawing directly to the Canvas object provided to my onDraw method. This canvas is hardware accelerated. In particular, I draw several circles using RadialGradient shaders with OVERLAY PorterDuff mode. However, when I try to apply the same drawing procedure to the canvas that I create manually, I do not get the same results. I believe this is because the canvas object created for the bitmap is NOT accelerated.

The code looks something like this:

public class MyView extends View { private Paint mPaint; private List<Shader> mShaders; public MyView(Context context) { super(context); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DITHER_FLAG); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)); mShaders = new ArrayList<Shader>(); // assume x, y, r, and color vals are defined. mShaders.add(new RadialGradient(x1, y1, r1, c11, c12, Shader.TileMode.CLAMP)); mShaders.add(new RadialGradient(x2, y2, r2, c21, c22, Shader.TileMode.CLAMP)); } @Override protected void onDraw(Canvas canvas) { mPaint.setShader(mShaders.get(0)); canvas.drawCircle(x1, y1, r1, mPaint); mPaint.setShader(mShaders.get(1)); canvas.drawCircle(x2, y2, r2, mPaint); } } 

Up to this point, all is well and good. Circles are drawn, as expected, on a hardware accelerated canvas.

However, if I do this:

 ... Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); draw(canvas); 

or some changes:

 ... setDrawingCacheEnabled(true); buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(getDrawingCache()); destroyDrawingCache(); setDrawingCacheEnabled(false); 

or if I try to draw with the same shaders and colored flags on, say, the non-hardware accelerated canvas provided by the WallpaperService Engine, the results simply do not match the results when I did the same on a hardware accelerated canvas object of the kind.

Here is a screenshot showing what happens when circles are drawn on canvas with an accelerated view. https://www.dropbox.com/s/vgvo3l6wz2d1b1c/good.png?dl=0

This is what happens when drawing a manually created canvas that is not associated with a view. https://www.dropbox.com/s/zuo23z2y7ik2wmg/bad.png?dl=0

Although I understand that there are significant differences when drawing with hardware acceleration, it seems that there is no way to capture even the visualized appearance of the accelerated canvas without having to re-render it in the software using a cache drawing that does not work. How to capture a rendered view as is?

Shortly afterwards, I noticed that just commenting on the line that sets OVERLAY Xfermode eliminates the difference between drawing on accelerated or non-accelerated canvas, but this is not a solution. Deleting OVERLAY mode gives a completely different effect than what I'm trying to capture.

+5
source share

Source: https://habr.com/ru/post/1203458/


All Articles