Android: creating a Bitmap with SurfaceView content
Asked Answered
C

4

14

I'm afraid to already have the unfortunate answer to this question but just in case... I'm using a SurfaceView to do some image processing with bitmaps (lights and colors modifications) and I would need to import the modified bitmap (i.e. the content of the SurfaceView) in a new bitmap so that I can save it as an image file.

I've been looking around and it seems that it's possible to get a bitmap from View.getDrawingCache() but it doesn't work with SurfaceView. All I get is an empty bitmap.

Is there any solution to this?

Thanks

Cacique answered 20/1, 2011 at 2:15 Comment(0)
M
10

For API levels >=24, use the PixelCopy API. Here's an example inside an ImageView:

public void DrawBitmap(){
    Bitmap surfaceBitmap = Bitmap.createBitmap(600, 600, Bitmap.Config.ARGB_8888);
    PixelCopy.OnPixelCopyFinishedListener listener = copyResult -> {
        // success/failure callback
    };

    PixelCopy.request(YourSurfaceView, surfaceBitmap,listener,getHandler());
    // visualize the retrieved bitmap on your imageview
    setImageBitmap(plotBitmap);
    }
}
Mudguard answered 11/1, 2019 at 19:40 Comment(1)
I have attempted using PixelCopy but so far on my device, it fails. It has come to my attention that using this API requires hardware acceleration to be enabled. Yet, despite enabling it in the Manifest (at Application and Activity levels) and also at the programming level in the Activity class, it does not work. Perhaps my phone does not support hardware acceleration. I am trying to figure out right now what the workaround would be.Blasius
T
8

Can you draw your SurfaceView onto a Canvas that's backed by a Bitmap?

    // be sure to call the createBitmap that returns a mutable Bitmap
    Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); 
    Canvas c = new Canvas(b);
    yourSurfaceView.draw(c);
Tonjatonjes answered 20/1, 2011 at 2:24 Comment(3)
I wanted to use this solution but it's not possible with SurfaceViews because the drawing process is done in a thread and the canvas is obtained from the SurfaceHolder. It is used this way: canvas = surfaceHolder.lockCanvas(null); synchronized(surfaceHolder) { doDraw(canvas); }Cacique
Problem solved. I changed the SurfaceView to a simple custom View. Then, enabling the drawingCache (setDrawingCacheEnabled(true)) when the view is created, I'm able to retrieve a bitmap calling the getDrawingCache() method.Cacique
for your first comment, couldn't you just call doDraw with the bitmap-backed Canvas? if (screenGrab) { doDraw(c_fromMyPost); } else { doDraw(canvas_fromYourApp); }Tonjatonjes
P
3

There is no simple way to capture frames of SurfaceView, so you can consider using TextureView instead of SurfaceView: the Bitmap can be retrieved using textureView.getBitmap() method.

Paraphernalia answered 20/9, 2016 at 14:10 Comment(0)
E
1

Just grab the source code for SurfaceView and modify it to give you access to the underlying bitmap.

Examen answered 25/4, 2021 at 7:30 Comment(1)
That's an interesting solution. Do you mean editing the Android Sdk and recompiling? You could also just extend the SurfaceView. How else can I modify the source code to give me access to the Bitmap?Blakey

© 2022 - 2024 — McMap. All rights reserved.