How to save SurfaceView to Bitmap on Android in Kotlin

eye catch Android

How to save SurfaceView to Bitmap on Android.

There are PixelCopy class on Android SDK.

Provides a mechanisms to issue pixel copy requests to allow for copy operations from Surface to Bitmap

Quotes : https://developer.android.com/reference/android/view/PixelCopy

This class makes it easy to save a SurfaceView as an image.

This article explains the way and code examples with Kotlin.

1. Get Bitmap from SurfaceView

Use the PixelCopy.request() method.

Quote : PixelCopy.request() | Android Developers

public static void request (SurfaceView source,
Bitmap dest,
PixelCopy.OnPixelCopyFinishedListener listener,
Handler listenerThread)

Requests for the display content of a SurfaceView to be copied into a provided Bitmap. The contents of the source will be scaled to fit exactly inside the bitmap. The pixel format of the source buffer will be converted, as part of the copy, to fit the the bitmap’s Bitmap.Config. The most recently queued buffer in the SurfaceView’s Surface will be used as the source of the copy.

Quotes : https://developer.android.com/reference/android/view/PixelCopy#request(android.view.SurfaceView,%20android.graphics.Bitmap,%20android.view.PixelCopy.OnPixelCopyFinishedListener,%20android.os.Handler)

 

An example code using this method  :

surfaceView = findViewById(R.id.surfacce_view)

/// Initialize SurfaceView...

val svBitmap = Bitmap.createBitmap(
    surfaceView.width, surfaceView.height, Bitmap.Config.ARGB_8888)
PixelCopy.request(surfaceView, svBitmap, PixelCopy.OnPixelCopyFinishedListener {
    if (it != PixelCopy.SUCCESS) {
        /// Fallback when request fails...

        return@OnPixelCopyFinishedListener
    }

    Log.d(TAG, "svBitmap w : ${svBitmap.width} , h : ${svBitmap.height}")
    
    /// Handle retrieved Bitmap...
}, surfaceView.handler)

Write the code calling PixelCopy.request() like the example code above.

You can then process the acquired Bitmap as you like.

2. Save SurfaceView bitmap as png file

In addition, try to save the Bitmap to the externalFilesDir of the app.

Example code in Kotlin :

fun saveBitmap(bitmap: Bitmap){
    val saveFile = File(getExternalFilesDir(
        Environment.DIRECTORY_PICTURES), "capture.png")
    if(!saveFile.exists()){ saveFile.createNewFile() }
    val outStream = FileOutputStream(saveFile)
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream)
    outStream.close()
}

A Bitmap is saved in externalFilesDir with the file name capture.png. If you prefer to save to the app’s private internal storage, use filesDir instead.

Leave a Reply