Capturable icon indicating copy to clipboard operation
Capturable copied to clipboard

Save the captured image for upload to server

Open chkmls opened this issue 1 year ago • 3 comments

Is there a way to save the capture media as file?

chkmls avatar Jul 19 '22 15:07 chkmls

Yes, just get the Bitmap and save normally. Here's an example of a function for this, created with scoped storage in mind:

fun saveImage(bitmap: Bitmap) {
    try {
        // Used to scan the file on Android devices < 10
        var imageFile: File? = null
        val imageName = "${System.currentTimeMillis()}.png"
        val folderToSave = "${Environment.DIRECTORY_PICTURES}${File.separator}App Name"
        val imageOutputStream: OutputStream?
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val values = ContentValues()
            values.put(MediaStore.Images.Media.DISPLAY_NAME, imageName)
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/png")
            values.put(MediaStore.Images.Media.RELATIVE_PATH, folderToSave)
            val uri: Uri? =
            context.contentResolver.insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                values
            )
            imageOutputStream = context.contentResolver.openOutputStream(uri!!)
        } else {
            val imagePath =
            Environment.getExternalStoragePublicDirectory(folderToSave).toString()
            File(imagePath).mkdirs()
            imageFile = File(imagePath, imageName)
            imageOutputStream = FileOutputStream(imageFile)
        }

        imageOutputStream.use { outputStream ->
            if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)) {
                throw IOException("Unable to save image.")
            }
            /**
             * Scans the file so that it can appear in the gallery right after insertion.
             * This is useful for some phones that don't automatically scan the gallery.
             */
            imageFile?.let {
                MediaScannerConnection.scanFile(
                    context,
                    arrayOf(it.toString()),
                    null
                ) { path, uri -> }
            }
        }
    } catch (e: Exception) {
        Log.e("Error", "Error saving image: ${e.message}\n${e.stackTrace.joinToString()}")
    }
}

Example of use:

onCaptured = { bitmap, error ->
     if (bitmap != null) {
         saveImage(bitmap.asAndroidBitmap())
     }
}

After saving you can get the Uri and then upload it to the server.

jsericksk avatar Jul 19 '22 18:07 jsericksk

Great, thanks! The quality of the captured image is lower than original, and the file size increase, any way to fix this?

chkmls avatar Jul 20 '22 16:07 chkmls

What do you mean by "lower than original"? I didn't experience this problem, but I believe that the quality of the final image may vary depending on the resolution size. As for the image size, you can try lowering the quality in (bitmap.compress(Bitmap.CompressFormat.PNG, 90, outputStream). You can also try changing the format to JPEG, but it will probably result in a image with a slightly reduced quality.

jsericksk avatar Jul 20 '22 16:07 jsericksk

The library is only intended for capturing composable content into bitmap. With file IO operations, you can save bitmap.

See example: https://github.com/PatilShreyas/NotyKT/blob/master/noty-android/app/src/main/java/dev/shreyaspatil/noty/utils/FileUtils.kt

Closing this.

PatilShreyas avatar Jan 16 '23 03:01 PatilShreyas