peekaboo


📂 Kotlin Multiplatform library for Compose Multiplatform, designed for seamless integration of an image picker feature in iOS and Android applications.
Getting started
Compose Multiplatform
peekaboo is based on Compose Multiplatform, currently targeting only iOS and Android.
Please note that it primarily focuses on these platforms, and additional platforms may be considered in the future.
When using peekaboo on Android, ensure that Google's Jetpack Compose version is compatible with peekaboo's Compose Multiplatform version.
Installation
The minimum supported Android SDK is 24 (Android 7.0).
In your commonMain configuration, add the desired dependency, either peekaboo-ui or peekaboo-image-picker, to your project. Both are available on Maven Central.
Without Version Catalog
commonMain {
dependencies {
implementation("io.github.onseok:peekaboo-ui:$latest_version")
implementation("io.github.onseok:peekaboo-image-picker:$latest_version")
}
}
With Version Catalog
First, define the version in libs.versions.toml:
[versions]
peekaboo = "0.5.2"
[libraries]
peekaboo-ui = { module = "io.github.onseok:peekaboo-ui", version.ref = "peekaboo" }
peekaboo-image-picker = { module = "io.github.onseok:peekaboo-image-picker", version.ref = "peekaboo" }
Then, in your commonMain configuration, reference the defined version:
commonMain {
dependencies {
implementation(libs.peekaboo.ui)
implementation(libs.peekaboo.image.picker)
}
}
Artifacts
Usage
Xcode setup
In order to access the camera on iOS devices, it's essential to include a specific key-value pair in the Info.plist file of your iOS project. This key-value pair comprises a key that identifies the type of permission being requested and a value that provides a user-friendly description explaining why the app needs access to the camera.
Here's the key-value pair you should add to your Info.plist:
<key>Privacy - Camera Usage Description</key>
<string>This app uses camera for capturing photos.</string>
Custimizable Camera UI
PeekabooCamera is a composable function that provides a customizable camera UI within a Compose Multiplatform application.
Simple Camera UI
@Composable
fun CustomCameraView() {
val state = rememberPeekabooCameraState(onCapture = { })
PeekabooCamera(
state = state,
modifier = Modifier.fillMaxSize(),
permissionDeniedContent = {
},
)
}
Camera UI with overlay
@Composable
fun CustomCameraView() {
val state = rememberPeekabooCameraState(onCapture = { })
Box(modifier = Modifier.fillMaxSize()) {
PeekabooCamera(
state = state,
modifier = Modifier.fillMaxSize(),
permissionDeniedContent = {
},
)
YourCameraOverlay(
state = state,
modifier = Modifier.fillMaxSize(),
)
}
}
state : The PeekabooCameraState to control camera.
permissionDeniedContent : An optional composable lambda that provides content to be displayed when camera permission is denied. This allows users to define a custom UI to inform or guide the user when camera access has been denied. The content can be informative text, an image, a button to redirect the user to settings, or any other content. This lambda will be invoked within the composable scope, replacing the camera preview with the user-defined UI.
Camera state
rememberPeekabooCameraState(
initialCameraMode: CameraMode = CameraMode.Back,
onCapture: (ByteArray?) -> Unit,
)
initialCameraMode : The initial camera mode (front or back). Default is [CameraMode.Back]. Changes does not affect state. To toggle use [PeekabooCameraState.toggleCamera]
onCapture : A lambda called when a photo is captured, providing the photo as a ByteArray or null if the capture fails.
Capturing an Image from Camera
| Android | iOS |
|---|
 |  |
Toggling Camera Mode Between Front and Back
| Android | iOS |
|---|
 |  |
Handling Denied Camera Permissions
| Android | iOS |
|---|
 |  |
Select Single Image
val scope = rememberCoroutineScope()
val singleImagePicker = rememberImagePickerLauncher(
selectionMode = SelectionMode.Single,
scope = scope,
onResult = { byteArrays ->
byteArrays.firstOrNull()?.let {
println(it)
}
}
)
Button(
onClick = {
singleImagePicker.launch()
}
) {
Text("Pick Single Image")
}
| Android | iOS |
|---|
 |  |
Simply select the desired image with an intuitive interface.
Select Multiple Images
If you want to select multiple images, you can use SelectionMode.Multiple(). And you can set the maximum number of images to select.
If you didn't set max selection, the default value is maximum number that the system supports.
val scope = rememberCoroutineScope()
val multipleImagePicker = rememberImagePickerLauncher(
selectionMode = SelectionMode.Multiple(maxSelection = 5),
scope = scope,
onResult = { byteArrays ->
byteArrays.forEach {
println(it)
}
}
)
Button(
onClick = {
multipleImagePicker.launch()
}
) {
Text("Pick Multiple Images")
}
| Android | iOS |
|---|
 |  |
Image Resizing Options
peekaboo offers customizable resizing options for both single and multiple image selections, along with a new feature to resize images only if they exceed a certain file size.
This feature allows you to resize the selected images to specific dimensions, optimizing them for your application's requirements and enhancing performance.
- The default resizing dimensions are set to
800 x 800 pixels.
- The default threshold for resizing is set to
1MB, meaning images larger than this size will be resized.
- You can customize the resizing dimensions, threshold, and now the compression quality according to your needs.
Usage
Set the resizeOptions parameter in rememberImagePickerLauncher with your desired dimensions, threshold and compression quality:
val resizeOptions = ResizeOptions(
width = 1200,
height = 1200,
resizeThresholdBytes = 2 * 1024 * 1024L,
compressionQuality = 0.5
)
Single Image Selection with Resizing
val singleImagePicker = rememberImagePickerLauncher(
selectionMode = SelectionMode.Single,
scope = rememberCoroutineScope(),
resizeOptions = resizeOptions,
onResult = { byteArrays ->
byteArrays.firstOrNull()?.let {
println(it)
}
}
)
Multiple Images Selection with Resizing
val multipleImagePicker = rememberImagePickerLauncher(
selectionMode = SelectionMode.Multiple(maxSelection = 5),
scope = rememberCoroutineScope(),
resizeOptions = resizeOptions,
onResult = { byteArrays ->
byteArrays.forEach {
println(it)
}
}
)
💡 Note: While resizing, the aspect ratio of the original images is preserved. The final dimensions may slightly vary to maintain the original proportions.
Image Filter Options
peekaboo-image-picker now offers customizable filter options for selected images.
This feature is available on both Android and iOS devices.
| Default | GrayScale | Sepia | Invert |
|---|
 |  |
Usage
Set the filterOptions parameter in rememberImagePickerLauncher:
val imagePicker = rememberImagePickerLauncher(
selectionMode = SelectionMode.Single,
scope = rememberCoroutineScope(),
filterOptions = FilterOptions.GrayScale,
onResult = { byteArrays ->
}
)
💡 Note: The default filter option is Default, which applies no filter.
Choose from GrayScale, Sepia, or Invert for different effects.
ByteArray to ImageBitmap Conversion
We've added a new extension function toImageBitmap() to convert a ByteArray into an ImageBitmap.
This function simplifies the process of converting image data into a displayable format, enhancing the app's capability to handle image processing efficiently.
Usage
val imageBitmap = byteArray.toImageBitmap()
Contributions 🙏
Contributions are always welcome!
If you'd like to contribute, please feel free to create a PR or open an issue. 👍
Stargazers :star:
Support it by joining stargazers for this repository. :star:
License
Copyright 2024 onseok
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
https:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.