13

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

Nicolas P.
  • 581
  • 1
  • 4
  • 15

4 Answers4

9

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);
    }
}
pale bone
  • 1,746
  • 2
  • 19
  • 26
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);
idbrii
  • 10,975
  • 5
  • 66
  • 107
  • 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); } – Nicolas P. Jan 20 '11 at 02:46
  • 8
    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. – Nicolas P. Jan 21 '11 at 18:54
  • for your first comment, couldn't you just call doDraw with the bitmap-backed Canvas? `if (screenGrab) { doDraw(c_fromMyPost); } else { doDraw(canvas_fromYourApp); }` – idbrii Jan 22 '11 at 03:12
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.

Community
  • 1
  • 1
Andrew Vovk
  • 353
  • 5
  • 16
1

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

Johann
  • 27,536
  • 39
  • 165
  • 279
  • 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? – Cyrill Feb 20 '22 at 22:04