propeace
propeace

Reputation: 23

How to crop an image from camera and gallery directly in Jetpack Compose

I would like to implement a functionality where the user can choose between the camera and gallery options when they click on a button. Once the user selects an image from either option, I want to enable them to crop the selected image. Unfortunately, I haven't been able to find a suitable library for this task, and even if one exists, the documentation appears to be lacking.

I also tried some libraries for Kotlin (XML) and they did not work, as well.

Upvotes: 0

Views: 1711

Answers (1)

Megh Lath
Megh Lath

Reputation: 2138

You can use this library to enable crop feature once user selects image from gallery and clicks image from camera: https://github.com/CanHub/Android-Image-Cropper

Sample implementation:


  var openImageChooser = rememeber { mutableStateOf(false) }


 // For gallery image chooser
 val imageCropLauncher = rememberLauncherForActivityResult(
        contract = CropImageContract()
    ) { result ->
        if (result.isSuccessful) {
            // Got image data. Use it according to your need
        } else {
            // There is some error while choosing image -> show error accordingly(result.error)
        }
    }

    val imagePickerLauncher =
        rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) { uri: Uri? ->
            val cropOptions = CropImageContractOptions(uri, CropImageOptions())
            imageCropLauncher.launch(cropOptions)
        }


    // For camera image
    val cameraLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.TakePicturePreview()
    ) { cameraBitmap ->
        cameraBitmap?.let {
            val fileName = "IMG_${System.currentTimeMillis()}.jpg"
            val imageFile = File(context.filesDir, fileName)
            try {
                val out = FileOutputStream(imageFile)
                it.compress(Bitmap.CompressFormat.JPEG, 100, out)
                out.flush()
                out.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            // Got image data. Use it according to your need(imageFile)
        }
    }


    if (openImageChooser) {
        UploadImageAlertDialog(
            onCameraClick = {
                cameraLauncher.launch()
                openImageChooser = false
            },
            onGalleryClick = {
                imagePickerLauncher.launch("image/*")
                openImageChooser = false
            },
            onDismissClick = { openImageChooser = false }
        )
    }

    Button(onClick = { openImageChooser = true }){
       ...
    }
@Composable
fun UploadImageAlertDialog(
    onCameraClick: () -> Unit,
    onGalleryClick: () -> Unit,
    onDismissClick: () -> Unit
) {
    Dialog(
        onDismissRequest = { onDismissClick() },
        DialogProperties(usePlatformDefaultWidth = false)
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 20.dp)
                .clip(RoundedCornerShape(28.dp))
                .background(AppTheme.colorScheme.containerNormalOnSurface),
            contentAlignment = Alignment.Center
        ) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 24.dp)
            ) {
                Text(
                    text = "Camera",
                    style = AppTheme.appTypography.subtitle2,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 24.dp)
                        .clickable { onCameraClick() }
                )
                Text(
                    text = "Gallery",
                    style = AppTheme.appTypography.subtitle2,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 24.dp)
                        .clickable {
                            onGalleryClick()
                        }
                )
                Spacer(modifier = Modifier.height(24.dp))
            }
        }
    }
}

Add this in AndroidManifest.xml

<activity android:name="com.canhub.cropper.CropImageActivity"
            android:theme="@style/Base.Theme.AppCompat"/>

Upvotes: 2

Related Questions