/CMP-image-pick-n-crop

Primary LanguageKotlinApache License 2.0Apache-2.0

Maven Central Kotlin Compose Multiplatform License

badge-android badge-ios badge-desktop

CMPImagePickNCrop

A CMPImagePickNCrop is image selection & cropping library for Compose Multiplatform for Android and iOS.

CMP-image-pick-n-crop-org

Installation

Add the dependency to your build.gradle.kts file:

commonMain.dependencies {
    implementation("network.chaintech:cmp-image-pick-n-crop:1.0.4")
}

Add Permissions in Android and iOS

  • Android : Include this at root level in your AndroidManifest.xml:
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
  • iOS : Add below key to the Info.plist in your xcode project:
<key>NSCameraUsageDescription</key><string>$(PRODUCT_NAME) camera description.</string>
<key>NSPhotoLibraryUsageDescription</key><string>$(PRODUCT_NAME)photos description.</string>

Usage

@Composable
fun CMPImagePickNCropDialog(
    imageCropper: ImageCropper = rememberImageCropper(),
    openImagePicker: Boolean,
    cropEnable: Boolean = true,
    imagePickerDialogHandler: (Boolean) -> Unit,
    selectedImageCallback: (ImageBitmap) -> Unit
)
  • imageCropper: Manages the image cropping logic (default is rememberImageCropper()).
  • openImagePicker: Controls whether the image picker dialog is open.
  • cropEnable: Enables or disables the image cropping feature (default is true).
  • imagePickerDialogHandler: Handles the opening and closing of the image picker dialog.
  • selectedImageCallback: Called when an image is selected and cropped, providing the cropped image.

Example

@Composable
internal fun App() = AppTheme {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = Color.White
    ) {
        val imageCropper = rememberImageCropper()
        var selectedImage by remember { mutableStateOf<ImageBitmap?>(null) }
        var openImagePicker by remember { mutableStateOf(value = false) }

        CMPImagePickNCropDialog(
            imageCropper = imageCropper,
            openImagePicker = openImagePicker,
            imagePickerDialogHandler = {
                openImagePicker = it
            },
            selectedImageCallback = {
                selectedImage = it
            })

        Column(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.White)
                .safeContentPadding(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            selectedImage?.let {
                Image(
                    bitmap = it,
                    contentDescription = null,
                    modifier = Modifier.weight(1f)
                )
            }
            if (selectedImage == null)
                Box(
                    contentAlignment = Alignment.Center,
                    modifier = Modifier.weight(1f)
                ) {
                    Text("No image selected !", color = Color.Black)
                }

            Button(
                onClick = {
                    openImagePicker = true
                },
            ) { Text("Choose Image") }
        }
    }
}
  • For Crop
val selectedBitmap = remember { mutableStateOf<ImageBitmap?>(null) }
val imageCropper = rememberImageCropper()
CMPImageCropDialog(imageCropper = imageCropper)

Button(
    modifier = Modifier
        .weight(2F)
        .padding(start = 12.dp, end = 12.dp),
    onClick = {
        coroutineScope.launch {
            selectedBitmap.value?.let { bitmap ->
                when (val result = imageCropper.cropImage(bmp = bitmap)) {
                    ImageCropResult.Cancelled -> {
                        // Handle cancellation if needed
                    }
                    is ImageCropError -> {
                        // Handle error if needed
                    }
                    is ImageCropResult.Success -> {
                        selectedBitmap.value = result.bitmap
                    }
                }
            }
        }
    }
) {
    Text(text = "CropImage")
}

Screenshot - Android and iOS

1_9Ea4YOYyvObPhPldxwKngQ

Screenshot - Desktop

CMP-image-pick-n-crop-org

🌐 Stay Connected with Us

Stay connected and keep up with our latest innovations! 💼 Let's innovate together!

LinkedIn Medium

📄 License

Copyright 2023 Mobile Innovation Network

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.