Cannot resize image captured with CameraX?

639 Views Asked by At

I've succesfully capture image with CameraX into JPEG files. The problem is the file size is big. On an Android powered walki talkie (Android 11), the result is typically 4 to 6 MB, so I'd like to resize it.

Here's my code:

fun takePhoto() {
        val FILENAME_FORMAT = "ddMMyyyy_HHmmss"

        val capturedContentValues = ContentValues()
        capturedContentValues.put(MediaStore.MediaColumns.DISPLAY_NAME,
            "CARAKA_"+SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()))
        capturedContentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM+"/TESTAPP")
        capturedContentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")

        val outputOptions= ImageCapture.OutputFileOptions.Builder(
            context.contentResolver,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            capturedContentValues
        ).build()


        imageCapture.takePicture(
            outputOptions,
            ContextCompat.getMainExecutor(context),
            object : ImageCapture.OnImageSavedCallback {
                override fun onError(exc: ImageCaptureException) {
                    Toast.makeText(context,"Photo capture failed: ${exc.message}", Toast.LENGTH_SHORT).show()
                }

                override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                    val theFile = getFile(context, output.savedUri!!)
                    val capturedBitmap = BitmapFactory.decodeFile(theFile!!.absolutePath)
                    val resizedBitmap = getResizedBitmap(capturedBitmap, 1024)
                    val fout = FileOutputStream(theFile.absolutePath)
                    resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout)

                    fout.flush()
                    fout.close()

                }
            })
    }

    fun getResizedBitmap(image: Bitmap, maxSize: Int): Bitmap {
        var width = image.width
        var height = image.height
        val bitmapRatio = width.toFloat() / height.toFloat()
        if (bitmapRatio > 1) {
            width = maxSize
            height = (width / bitmapRatio).toInt()
        } else {
            height = maxSize
            width = (height * bitmapRatio).toInt()
        }
        return Bitmap.createScaledBitmap(image, width, height, true)
    }
 
    @Throws(IOException::class)
    fun getFile(context: Context, uri: Uri): File? {
        val destinationFilename =
            File(context.filesDir.path + File.separatorChar + queryName(context, uri))
        try {
            context.contentResolver.openInputStream(uri).use { ins ->
                createFileFromStream(
                    ins!!,
                    destinationFilename
                )
            }
        } catch (ex: java.lang.Exception) {
            Log.e("Save File", ex.message!!)
            ex.printStackTrace()
        }
        return destinationFilename
    }

    fun createFileFromStream(ins: InputStream, destination: File?) {
        try {
            FileOutputStream(destination).use { os ->
                val buffer = ByteArray(4096)
                var length: Int
                while (ins.read(buffer).also { length = it } > 0) {
                    os.write(buffer, 0, length)
                }
                os.flush()
            }
        } catch (ex: java.lang.Exception) {
            Log.e("Save File", ex.message!!)
            ex.printStackTrace()
        }
    }

    private fun queryName(context: Context, uri: Uri): String {
        val returnCursor: Cursor = context.contentResolver.query(uri, null, null, null, null)!!
        val nameIndex: Int = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
        returnCursor.moveToFirst()
        val name: String = returnCursor.getString(nameIndex)
        returnCursor.close()
        return name
    }

Those saved JPEGs size is still within 4 to 6 MB. Not reduced into hundreds KB. What's wrong here?

1

There are 1 best solutions below

0
Xi 张熹 On

Instead of resizing it afterwards, another thing you can try is taking a smaller picture. You can set the target resolution to be lower: https://developer.android.com/reference/androidx/camera/core/ImageCapture.Builder#setTargetResolution(android.util.Size)