<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ismoy Belizaire</title>
    <description>The latest articles on DEV Community by Ismoy Belizaire (@ismoy).</description>
    <link>https://dev.to/ismoy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2471422%2Fb982589d-455c-4e60-a924-5674a28b3c2b.jpeg</url>
      <title>DEV Community: Ismoy Belizaire</title>
      <link>https://dev.to/ismoy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ismoy"/>
    <language>en</language>
    <item>
      <title>From Images to PDFs: OCR Workflows with ImagePickerKMP</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Wed, 27 May 2026 14:07:42 +0000</pubDate>
      <link>https://dev.to/ismoy/from-images-to-pdfs-ocr-workflows-with-imagepickerkmp-2na5</link>
      <guid>https://dev.to/ismoy/from-images-to-pdfs-ocr-workflows-with-imagepickerkmp-2na5</guid>
      <description>&lt;p&gt;Modern mobile apps are increasingly moving beyond just "viewing" images to "understanding" them. Whether it's scanning a receipt, reading a business card, or extracting data from an ID, document workflows are a top requirement. ImagePickerKMP supports these workflows by providing a unified way to capture images and select PDFs. The feature list at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; highlights PDF and OCR-ready capture as key capabilities.&lt;/p&gt;

&lt;p&gt;The library's role in an OCR workflow is to provide high-quality, predictable input. For OCR to work well, the image needs to be clear, correctly framed, and available in a format the OCR engine can read.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workflow Step&lt;/th&gt;
&lt;th&gt;ImagePickerKMP Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;CameraScaleType.FIT_CENTER&lt;/code&gt; for precise framing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Selection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;mimeTypes&lt;/code&gt; to allow both images and PDFs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Preparation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;PhotoResult.absolutePath&lt;/code&gt; to pass to a native OCR SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shared Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;PhotoResult.toPath()&lt;/code&gt; for shared extraction logic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;galleryConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GalleryConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;mimeTypes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"image/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/pdf"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;cameraCaptureConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraCaptureConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;cameraScaleType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraScaleType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FIT_CENTER&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The documentation source for document capture and PDF selection is &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;. Refer to it for the latest API reference on MIME types and camera configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By allowing both images and PDFs in the same picker, ImagePickerKMP simplifies the UI for document apps. The user doesn't have to choose "Upload Photo" vs "Upload PDF" in separate buttons; they can tap one action and find their document regardless of its format.&lt;/p&gt;

&lt;p&gt;Once the file is selected, extensions like &lt;code&gt;absolutePath&lt;/code&gt; or &lt;code&gt;toPath()&lt;/code&gt; make it easy to pass the data to an OCR engine like ML Kit, Tesseract, or a cloud-based AI service.&lt;/p&gt;

&lt;p&gt;As AI-driven features become standard in mobile apps, having a reliable media picker that understands the difference between a "pretty photo" and a "readable document" is essential. ImagePickerKMP provides that foundation.&lt;/p&gt;

&lt;p&gt;For more examples of document-focused configurations, visit the live documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

</description>
      <category>kotlin</category>
      <category>machinelearning</category>
      <category>mobile</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Smarter Android Picking: ImagePickerKMP Automatically Chooses Gallery or File Explorer</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Mon, 25 May 2026 14:08:13 +0000</pubDate>
      <link>https://dev.to/ismoy/smarter-android-picking-imagepickerkmp-automatically-chooses-gallery-or-file-explorer-422h</link>
      <guid>https://dev.to/ismoy/smarter-android-picking-imagepickerkmp-automatically-chooses-gallery-or-file-explorer-422h</guid>
      <description>&lt;p&gt;Android media picking has become increasingly complex over the years. Depending on the OS version, the installed apps, and the requested MIME types, the "best" way to pick an image might be the system Photo Picker, a third-party Gallery app, or the system File Explorer. ImagePickerKMP 1.0.35 introduced logic to handle this choice automatically. The documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; describes this as a unified gallery picker.&lt;/p&gt;

&lt;p&gt;The core problem is MIME type support. While most gallery apps are great at showing JPEGs and PNGs, they often fail when asked to show PDFs or specialized file formats. If a developer asks for &lt;code&gt;image/*&lt;/code&gt;, a gallery is perfect. If they ask for &lt;code&gt;application/pdf&lt;/code&gt;, a file explorer is required.&lt;/p&gt;

&lt;p&gt;ImagePickerKMP solves this by inspecting the requested MIME types. If the request is purely for images or videos, it prioritizes the gallery experience. If the request includes non-media types, it seamlessly falls back to the file explorer.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Primary UI&lt;/th&gt;
&lt;th&gt;Fallback&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;System Gallery / Photo Picker&lt;/td&gt;
&lt;td&gt;File Explorer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;video/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;System Gallery / Photo Picker&lt;/td&gt;
&lt;td&gt;File Explorer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/pdf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File Explorer&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mixed types&lt;/td&gt;
&lt;td&gt;File Explorer&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;For the current platform matrix and MIME type support details, visit the official documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;galleryConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GalleryConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;mimeTypes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"image/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/pdf"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This "smart picking" means developers don't have to write branching logic to decide which intent to launch. They simply declare what they need, and the library ensures the user sees a valid UI for that selection.&lt;/p&gt;

&lt;p&gt;In a world where Android fragmentation remains a challenge, this level of abstraction is a significant time-saver. It ensures that the app remains compatible with older devices while taking advantage of modern system pickers where available.&lt;/p&gt;

&lt;p&gt;Check the live documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; for more information on how to configure MIME types and handle multi-selection in the smart picker.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>mobile</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Automatic Image Compression for Camera and Gallery in ImagePickerKMP</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Sun, 24 May 2026 14:04:02 +0000</pubDate>
      <link>https://dev.to/ismoy/automatic-image-compression-for-camera-and-gallery-in-imagepickerkmp-5e32</link>
      <guid>https://dev.to/ismoy/automatic-image-compression-for-camera-and-gallery-in-imagepickerkmp-5e32</guid>
      <description>&lt;p&gt;Mobile developers often face a dilemma: high-resolution photos are great for quality but terrible for upload speed, storage costs, and memory consumption. ImagePickerKMP 1.0.35 introduced automatic image compression for both camera and gallery flows. The documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; lists compression as a core feature available across platforms.&lt;/p&gt;

&lt;p&gt;The compression system is built into the picker's configuration. Instead of writing manual resizing and re-encoding logic after the user picks an image, developers can specify a &lt;code&gt;CompressionLevel&lt;/code&gt; during initialization.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No compression, original file quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LOW&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minimal compression, high visual fidelity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MEDIUM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Balanced compression for general use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HIGH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aggressive compression for maximum size reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;cameraCaptureConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraCaptureConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;compressionLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompressionLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MEDIUM&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;galleryConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GalleryConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;compressionLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompressionLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LOW&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The official documentation source is &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;. Refer to it for details on how different compression levels impact file size and visual quality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation handles the heavy lifting: decoding the original image, applying the requested compression, and saving the result to a temporary file. This temporary file is what is returned to the application through &lt;code&gt;PhotoResult&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This feature is particularly valuable for Kotlin Multiplatform apps because image processing is notoriously platform-specific. By moving compression into the library, ImagePickerKMP allows teams to maintain a consistent "size budget" for their media without writing separate &lt;code&gt;Bitmap&lt;/code&gt; or &lt;code&gt;UIImage&lt;/code&gt; processing code for every target.&lt;/p&gt;

&lt;p&gt;When choosing a compression level, consider the final destination of the image. For a profile avatar, &lt;code&gt;MEDIUM&lt;/code&gt; or &lt;code&gt;HIGH&lt;/code&gt; is usually sufficient. For a document scan where text must remain legible, &lt;code&gt;LOW&lt;/code&gt; or &lt;code&gt;NONE&lt;/code&gt; is safer. With ImagePickerKMP, that decision is just one line of configuration away.&lt;/p&gt;

&lt;p&gt;Explore the full configuration options at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; to see how compression interacts with other features like EXIF preservation and GPS redaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

</description>
      <category>kotlin</category>
      <category>mobile</category>
      <category>performance</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Cross-Platform File Operations with PhotoResult.toPath() and kotlinx-io</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Sat, 23 May 2026 14:09:34 +0000</pubDate>
      <link>https://dev.to/ismoy/cross-platform-file-operations-with-photoresulttopath-and-kotlinx-io-4omp</link>
      <guid>https://dev.to/ismoy/cross-platform-file-operations-with-photoresulttopath-and-kotlinx-io-4omp</guid>
      <description>&lt;p&gt;Kotlin Multiplatform teams often want one shared pipeline after a photo is captured or selected. ImagePickerKMP 1.0.38 introduced &lt;code&gt;PhotoResult.toPath()&lt;/code&gt;, an extension that converts a photo URI into a &lt;code&gt;kotlinx.io.files.Path?&lt;/code&gt; for cross-platform file operations. The public documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; identifies ImagePickerKMP as a unified camera and gallery picker for Android, iOS, Desktop, Web, and WASM, while the API reference documents &lt;code&gt;toPath()&lt;/code&gt; as available since v1.0.38.&lt;/p&gt;

&lt;p&gt;The motivation is simple. A URI is useful for representing media, but shared business logic often wants a file abstraction. A &lt;code&gt;Path&lt;/code&gt; can be passed into common code that reads metadata, prepares upload payloads, performs validation, or coordinates local processing. By returning &lt;code&gt;Path?&lt;/code&gt;, the extension acknowledges that path conversion can fail and makes that possibility explicit.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Best use&lt;/th&gt;
&lt;th&gt;Tradeoff&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;photo.uri&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Universal identity of the selected media&lt;/td&gt;
&lt;td&gt;May require platform-specific handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;photo.toPath()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shared file operations with &lt;code&gt;kotlinx-io&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Requires a resolvable path and the &lt;code&gt;kotlinx-io&lt;/code&gt; dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;photo.absolutePath&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Native integrations expecting a string path&lt;/td&gt;
&lt;td&gt;More platform-specific and nullable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The code is intentionally small at the call site.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;processPhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real benefit appears when &lt;code&gt;processPhoto&lt;/code&gt; lives in shared code. Instead of branching by Android, iOS, Desktop, or Web at every feature boundary, your app can move more work into common modules. That is exactly the kind of simplification KMP teams look for when choosing shared libraries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The documentation source for the library is &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;. It should be cited when publishing examples because it contains the current API reference, changelog, installation version, and platform matrix.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;toPath()&lt;/code&gt; also works well with &lt;code&gt;rememberImagePickerKMP&lt;/code&gt;. The picker handles capture or selection, and the result-handling branch moves from UI state into file processing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launchGallery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allowMultiple&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Select photos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;success&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Success&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="nd"&gt;@LaunchedEffect&lt;/span&gt;
    &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapNotNull&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;processPhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A careful implementation should still keep fallbacks. Some targets or providers may not expose a path that can be converted. Treat &lt;code&gt;null&lt;/code&gt; as a normal outcome, not as an exceptional one. If your workflow must handle every selected asset, pair &lt;code&gt;toPath()&lt;/code&gt; with URI-based reading or platform-specific streams where needed.&lt;/p&gt;

&lt;p&gt;The feature is particularly useful for upload preparation, local caching, image transformations, and validation flows. For example, common code can check size, derive a display name, or move a file into an app-controlled cache before upload. When combined with ImagePickerKMP's metadata fields such as &lt;code&gt;fileName&lt;/code&gt;, &lt;code&gt;fileSize&lt;/code&gt;, &lt;code&gt;mimeType&lt;/code&gt;, and optional EXIF data, &lt;code&gt;toPath()&lt;/code&gt; helps turn a picked image into a workable file object.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PhotoResult.toPath()&lt;/code&gt; is a small extension, but it fits a larger theme in ImagePickerKMP: reduce the amount of platform-specific glue required after media selection. Start from the live documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;, confirm the current dependency version, and then move your post-picker file logic into shared code wherever possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;ImagePickerKMP Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ismoy/ImagePickerKMP" rel="noopener noreferrer"&gt;ImagePickerKMP GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ismoy/ImagePickerKMP/blob/develop/docs/CHANGELOG.md" rel="noopener noreferrer"&gt;ImagePickerKMP Changelog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>kotlin</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Direct File System Paths with PhotoResult.absolutePath in ImagePickerKMP</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Fri, 22 May 2026 14:11:04 +0000</pubDate>
      <link>https://dev.to/ismoy/direct-file-system-paths-with-photoresultabsolutepath-in-imagepickerkmp-3gi6</link>
      <guid>https://dev.to/ismoy/direct-file-system-paths-with-photoresultabsolutepath-in-imagepickerkmp-3gi6</guid>
      <description>&lt;p&gt;Image picking is usually only the first step. After a user captures or selects media, many apps need to upload it, inspect it, move it, cache it, or pass it into another SDK. ImagePickerKMP 1.0.40 adds &lt;code&gt;PhotoResult.absolutePath&lt;/code&gt;, an extension that returns the absolute file system path as a &lt;code&gt;String?&lt;/code&gt; when the platform can resolve it. The feature is documented in the ImagePickerKMP API reference and changelog, with &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; as the public documentation source for the library.&lt;/p&gt;

&lt;p&gt;The value of &lt;code&gt;absolutePath&lt;/code&gt; is convenience. Platform media APIs often return URIs rather than plain file paths. On Android, that may mean resolving &lt;code&gt;content://&lt;/code&gt; URIs through &lt;code&gt;ContentResolver&lt;/code&gt;. On iOS, it may mean extracting &lt;code&gt;URL.path&lt;/code&gt;. On Desktop and Web, direct path extraction can be simpler depending on the URI form. The changelog describes those platform-specific implementations and positions &lt;code&gt;absolutePath&lt;/code&gt; as a complement to &lt;code&gt;toPath()&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Resolution strategy described by the project&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;Resolve &lt;code&gt;content://&lt;/code&gt; URIs through &lt;code&gt;ContentResolver&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Avoids repeated manual URI parsing in app code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;URL.path&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Produces a familiar native file path string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop/Web&lt;/td&gt;
&lt;td&gt;Extract path from &lt;code&gt;file://&lt;/code&gt; URIs where available&lt;/td&gt;
&lt;td&gt;Keeps file workflows readable across targets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A typical usage pattern is straightforward. Once the picker returns &lt;code&gt;ImagePickerResult.Success&lt;/code&gt;, you inspect the first photo or the selected list and read &lt;code&gt;absolutePath&lt;/code&gt; when it is available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;absolutePath&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Absolute path: $path"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the property is nullable, a robust integration should always handle the missing-path case. Some platforms, permissions, storage providers, or browser environments may not expose a direct filesystem path. The nullable design encourages developers to treat &lt;code&gt;absolutePath&lt;/code&gt; as a convenience rather than a universal guarantee.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The official documentation for ImagePickerKMP is available at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;. Every implementation should check that page for the current dependency version, API reference, platform matrix, and changelog before adopting a new feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;absolutePath&lt;/code&gt; is especially useful when integrating with APIs that expect a string path instead of a URI or a multiplatform &lt;code&gt;Path&lt;/code&gt;. Common examples include native compression tools, upload clients, image-processing SDKs, logging, diagnostics, and migration code that has not yet moved to a shared file abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;uploadSelectedPhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PhotoResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;absolutePath&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;uploadFileFromPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;uploadFileFromUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important design decision is fallback. If your application is truly multiplatform, do not build the entire media workflow around absolute file paths. Use &lt;code&gt;absolutePath&lt;/code&gt; where a native path is the simplest bridge, but keep URI-based or byte-stream-based alternatives for environments that do not expose paths cleanly.&lt;/p&gt;

&lt;p&gt;For teams already using ImagePickerKMP, this feature removes a common piece of repeated glue code. Instead of writing separate URI-to-path utilities in each app, the library provides a consistent extension on &lt;code&gt;PhotoResult&lt;/code&gt;. That makes feature code easier to read and reduces the chance of platform-specific bugs.&lt;/p&gt;

&lt;p&gt;In short, &lt;code&gt;PhotoResult.absolutePath&lt;/code&gt; is not a replacement for every file abstraction. It is a pragmatic shortcut for real-world integrations that need a path string. Use it carefully, check for &lt;code&gt;null&lt;/code&gt;, and keep &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; as the reference point for current behavior and platform support.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;ImagePickerKMP Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ismoy/ImagePickerKMP" rel="noopener noreferrer"&gt;ImagePickerKMP GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ismoy/ImagePickerKMP/blob/develop/docs/CHANGELOG.md" rel="noopener noreferrer"&gt;ImagePickerKMP Changelog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>kotlin</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Better Post-Capture Previews with confirmationImageContentScale in ImagePickerKMP</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Thu, 21 May 2026 14:03:33 +0000</pubDate>
      <link>https://dev.to/ismoy/better-post-capture-previews-with-confirmationimagecontentscale-in-imagepickerkmp-2om1</link>
      <guid>https://dev.to/ismoy/better-post-capture-previews-with-confirmationimagecontentscale-in-imagepickerkmp-2om1</guid>
      <description>&lt;p&gt;Image capture does not end when the shutter button is pressed. Many apps show a confirmation screen where the user accepts, retakes, or reviews the photo. In ImagePickerKMP 1.0.41, &lt;code&gt;PermissionAndConfirmationConfig.confirmationImageContentScale&lt;/code&gt; gives developers control over how the captured photo is displayed in that post-capture preview. The official documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; highlights this release alongside configurable camera preview scaling.&lt;/p&gt;

&lt;p&gt;The new parameter accepts Compose &lt;code&gt;ContentScale&lt;/code&gt; values such as &lt;code&gt;Crop&lt;/code&gt;, &lt;code&gt;Fit&lt;/code&gt;, &lt;code&gt;FillWidth&lt;/code&gt;, &lt;code&gt;FillHeight&lt;/code&gt;, &lt;code&gt;FillBounds&lt;/code&gt;, &lt;code&gt;Inside&lt;/code&gt;, and &lt;code&gt;None&lt;/code&gt;. The default is &lt;code&gt;ContentScale.Crop&lt;/code&gt;, which preserves the previous behavior. This is a good compatibility choice because existing apps can upgrade without changing the look of their confirmation screen.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;code&gt;ContentScale&lt;/code&gt; choice&lt;/th&gt;
&lt;th&gt;User experience&lt;/th&gt;
&lt;th&gt;Typical use case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Crop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The preview area is filled, with possible cropping&lt;/td&gt;
&lt;td&gt;Avatar photos, social-style camera flows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Fit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The entire captured image remains visible&lt;/td&gt;
&lt;td&gt;Receipts, documents, product photos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FillWidth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The image fills horizontal space&lt;/td&gt;
&lt;td&gt;Wide confirmation cards or feed-like previews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Inside&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The image scales down only when needed&lt;/td&gt;
&lt;td&gt;Conservative previews that avoid upscaling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A confirmation screen is about trust. If users take a document photo and the preview silently crops the edges, they may accept an image that is unusable. If users take a profile photo and the preview is heavily letterboxed, the interface may feel less polished. &lt;code&gt;confirmationImageContentScale&lt;/code&gt; lets the confirmation step match the product intent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;permissionAndConfirmationConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PermissionAndConfirmationConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;confirmationImageContentScale&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ContentScale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fit&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setting pairs well with the new &lt;code&gt;CameraScaleType&lt;/code&gt;. For example, a document capture flow can use &lt;code&gt;CameraScaleType.FIT_CENTER&lt;/code&gt; during preview and &lt;code&gt;ContentScale.Fit&lt;/code&gt; during confirmation. That combination tells users a consistent story: what they framed is what they review.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;cameraCaptureConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraCaptureConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;cameraScaleType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraScaleType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FIT_CENTER&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;permissionAndConfirmationConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PermissionAndConfirmationConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;confirmationImageContentScale&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ContentScale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fit&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Use &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; as the documentation source for ImagePickerKMP. It includes current installation snippets, feature descriptions, API examples, platform notes, and changelog information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The feature is especially useful for teams that customize their capture pipeline but still want the default confirmation screen. Before this option, a team might have needed a custom confirmation composable to change display behavior. Now, the scaling decision is a configuration parameter. That keeps the integration smaller and makes the intent visible in code review.&lt;/p&gt;

&lt;p&gt;The default &lt;code&gt;ContentScale.Crop&lt;/code&gt; remains appropriate for full-bleed experiences. However, &lt;code&gt;ContentScale.Fit&lt;/code&gt; is often the safer choice for workflows where the entire captured image matters. If the photo is later processed by OCR, uploaded for verification, or used as evidence in a form, showing the entire image in confirmation reduces ambiguity.&lt;/p&gt;

&lt;p&gt;The most practical recommendation is to align preview and confirmation. If the camera preview is full-bleed, a cropped confirmation may be consistent. If the preview is letterboxed for exact framing, a fitted confirmation is more transparent. ImagePickerKMP 1.0.41 gives developers both controls, making camera flows easier to tune without building a custom UI from scratch.&lt;/p&gt;

&lt;p&gt;For updated examples and platform-specific notes, keep the official documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; close while implementing this feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

</description>
      <category>kotlin</category>
      <category>mobile</category>
      <category>showdev</category>
      <category>ui</category>
    </item>
    <item>
      <title>Precise Android Camera Framing with CameraScaleType in ImagePickerKMP 1.0.41</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Wed, 20 May 2026 14:12:23 +0000</pubDate>
      <link>https://dev.to/ismoy/precise-android-camera-framing-with-camerascaletype-in-imagepickerkmp-1041-46ce</link>
      <guid>https://dev.to/ismoy/precise-android-camera-framing-with-camerascaletype-in-imagepickerkmp-1041-46ce</guid>
      <description>&lt;p&gt;ImagePickerKMP 1.0.41 adds &lt;code&gt;CameraScaleType&lt;/code&gt;, a small API with a practical impact: it lets Android developers control how the camera preview is scaled inside its viewport. The official documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; identifies v1.0.41 as the release focused on camera preview scale type and confirmation image scale type, and the GitHub release notes connect that version with configurable camera preview scaling options.&lt;/p&gt;

&lt;p&gt;Camera previews can be deceptively difficult. A preview that fills the screen may crop part of the sensor feed, while a preview that fits the full feed may show letterboxing. Both behaviors can be correct, but they solve different product problems. A social camera interface may prefer a full-bleed preview. A document capture flow may prefer precise framing where the preview matches the captured image as closely as possible.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scale family&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FILL_*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fills the viewport and crops overflow&lt;/td&gt;
&lt;td&gt;Immersive camera screens, profile photos, social capture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FIT_*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shows the full feed with letterboxing when needed&lt;/td&gt;
&lt;td&gt;Document capture, product photos, framing-sensitive workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;*_CENTER&lt;/code&gt;, &lt;code&gt;*_START&lt;/code&gt;, &lt;code&gt;*_END&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Controls alignment within the viewport&lt;/td&gt;
&lt;td&gt;Layouts where the crop or letterbox should favor a specific edge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The changelog lists six enum values: &lt;code&gt;FILL_CENTER&lt;/code&gt;, &lt;code&gt;FILL_START&lt;/code&gt;, &lt;code&gt;FILL_END&lt;/code&gt;, &lt;code&gt;FIT_CENTER&lt;/code&gt;, &lt;code&gt;FIT_START&lt;/code&gt;, and &lt;code&gt;FIT_END&lt;/code&gt;. It also explains that &lt;code&gt;FILL_*&lt;/code&gt; values fill the viewport by cropping the camera feed, while &lt;code&gt;FIT_*&lt;/code&gt; values letterbox the preview so the entire camera feed is visible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;cameraCaptureConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraCaptureConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;cameraScaleType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraScaleType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FIT_CENTER&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launchCamera&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Open camera"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;FIT_CENTER&lt;/code&gt; is a strong default for workflows where the user needs trust in the preview. If the preview is used to frame a receipt, identity document, product label, or any object that must remain fully visible, letterboxing is often preferable to silent cropping. Conversely, &lt;code&gt;FILL_CENTER&lt;/code&gt; preserves the previous default behavior, which means existing apps can upgrade without a visual surprise unless they opt into another scale type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The public documentation source for ImagePickerKMP is &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;. It should be mentioned when sharing examples or release notes because it centralizes installation, API reference, changelog, and platform guidance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The API is exposed through &lt;code&gt;CameraCaptureConfig.cameraScaleType&lt;/code&gt;, so it composes naturally with the rest of the camera configuration. A developer can combine it with compression, EXIF extraction, UI customization, crop settings, and permission or confirmation configuration in the same object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;CameraCaptureConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;compressionLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompressionLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MEDIUM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;includeExif&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;redactGpsData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cameraScaleType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CameraScaleType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FIT_CENTER&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feature is currently described as Android-specific. That distinction matters because iOS uses the system camera UI, where preview and capture framing already follow system behavior. For a Kotlin Multiplatform library, platform-specific improvements are still valuable when they are exposed through a shared API that keeps the call site readable.&lt;/p&gt;

&lt;p&gt;The best way to choose a scale type is to start from the user promise. If the user expects an immersive camera, keep &lt;code&gt;FILL_CENTER&lt;/code&gt;. If the user expects the captured image to match the visible framing, choose &lt;code&gt;FIT_CENTER&lt;/code&gt;. If the layout places important controls or overlays near a particular side, test &lt;code&gt;START&lt;/code&gt; or &lt;code&gt;END&lt;/code&gt; variants to align the preview with the interface.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;CameraScaleType&lt;/code&gt;, ImagePickerKMP gives Android developers a direct way to make that decision instead of accepting a hardcoded preview behavior. For teams building production KMP apps, that control can reduce support issues, improve capture confidence, and make camera screens feel more intentional. Review the live docs at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; before shipping so your implementation matches the current version and platform notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>mobile</category>
      <category>ui</category>
    </item>
    <item>
      <title>The New Recommended Compose API in ImagePickerKMP: One State Holder for Camera and Gallery</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Tue, 19 May 2026 21:17:26 +0000</pubDate>
      <link>https://dev.to/ismoy/the-new-recommended-compose-api-in-imagepickerkmp-one-state-holder-for-camera-and-gallery-5dle</link>
      <guid>https://dev.to/ismoy/the-new-recommended-compose-api-in-imagepickerkmp-one-state-holder-for-camera-and-gallery-5dle</guid>
      <description>&lt;p&gt;ImagePickerKMP has moved toward a cleaner Compose-first model with &lt;code&gt;rememberImagePickerKMP&lt;/code&gt;, the recommended API for new code. According to the official ImagePickerKMP documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;, the library provides a unified camera and gallery picker for Android, iOS, Desktop, Web, and WASM, and the new API is designed to remove manual launcher state from application screens.&lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important shift is architectural. Instead of tracking &lt;code&gt;showCamera&lt;/code&gt; and &lt;code&gt;showGallery&lt;/code&gt; booleans, developers create one stable state holder and call &lt;code&gt;launchCamera()&lt;/code&gt; or &lt;code&gt;launchGallery()&lt;/code&gt; when the user taps an action. The GitHub changelog describes &lt;code&gt;rememberImagePickerKMP&lt;/code&gt; as a top-level composable that returns &lt;code&gt;ImagePickerKMPState&lt;/code&gt;, exposes a reactive result, and supports per-launch overrides.&lt;a href="https://github.com/ismoy/ImagePickerKMP/blob/develop/docs/CHANGELOG.md" rel="noopener noreferrer"&gt;2&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Legacy pattern&lt;/th&gt;
&lt;th&gt;Recommended pattern&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keep &lt;code&gt;showCamera&lt;/code&gt; and &lt;code&gt;showGallery&lt;/code&gt; booleans in the screen&lt;/td&gt;
&lt;td&gt;Use one &lt;code&gt;ImagePickerKMPState&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read results through callbacks&lt;/td&gt;
&lt;td&gt;Observe &lt;code&gt;picker.result&lt;/code&gt; reactively&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configure camera and gallery separately&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;ImagePickerKMPConfig&lt;/code&gt; as a shared default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toggle UI state manually after dismiss or error&lt;/td&gt;
&lt;td&gt;Let the state holder represent &lt;code&gt;Idle&lt;/code&gt;, &lt;code&gt;Loading&lt;/code&gt;, &lt;code&gt;Success&lt;/code&gt;, &lt;code&gt;Dismissed&lt;/code&gt;, or &lt;code&gt;Error&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The documentation source for this library is &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;. Use it as the primary reference when checking installation steps, platform support, API examples, and migration notes.&lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A minimal camera workflow now reads like normal Compose state. You remember the picker, trigger it from a button, and react to the result in the UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;ProfilePhotoScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launchCamera&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Take photo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;loadPainter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;painter&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;painter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;painter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contentDescription&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Selected photo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;CircularProgressIndicator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: ${result.exception.message}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dismissed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Idle&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No photo selected yet"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This style matters because camera and gallery flows are usually full of edge cases. The user may cancel, permissions may fail, multiple images may be selected, and a screen may need to reset after processing. &lt;code&gt;ImagePickerResult&lt;/code&gt; makes those states explicit, so the UI can handle them in a single &lt;code&gt;when&lt;/code&gt; expression instead of scattering callback side effects across a composable.&lt;/p&gt;

&lt;p&gt;The new API also improves configuration ergonomics. A screen can define global defaults through &lt;code&gt;ImagePickerKMPConfig&lt;/code&gt;, then override details for one launch. For example, a profile screen might default to single-image selection, while an album screen may call &lt;code&gt;launchGallery(allowMultiple = true, selectionLimit = 10)&lt;/code&gt; only for that interaction. This keeps default behavior stable while making one-off flows easy to express.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;picker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberImagePickerKMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerKMPConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;galleryConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GalleryConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;allowMultiple&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;includeExif&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;redactGpsData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;picker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launchGallery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;allowMultiple&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;selectionLimit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pick up to five photos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For teams migrating from &lt;code&gt;ImagePickerLauncher&lt;/code&gt; and &lt;code&gt;GalleryPickerLauncher&lt;/code&gt;, the important point is that legacy calls still work, but the recommended path is now the state-holder API. The API reference notes that the legacy launchers are deprecated with warnings and that existing code remains compatible while new code should use &lt;code&gt;rememberImagePickerKMP&lt;/code&gt;.&lt;a href="https://github.com/ismoy/ImagePickerKMP/blob/develop/docs/CHANGELOG.md" rel="noopener noreferrer"&gt;3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The practical benefit is not just fewer lines of code. It is a more predictable mental model: one remembered object owns launching, state, result delivery, and reset. In Compose Multiplatform apps, where consistency across targets is one of the main reasons to adopt KMP, that predictability is valuable.&lt;/p&gt;

&lt;p&gt;If you are starting a new Kotlin Multiplatform screen that needs camera or gallery access, begin with &lt;code&gt;rememberImagePickerKMP&lt;/code&gt;. If you are maintaining older launcher-based code, migrate one flow at a time: remove the visibility boolean, create the picker, call &lt;code&gt;launchCamera()&lt;/code&gt; or &lt;code&gt;launchGallery()&lt;/code&gt;, and render based on &lt;code&gt;picker.result&lt;/code&gt;. The official documentation at &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt; should remain the source of truth for the current API surface, installation instructions, and platform notes.&lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

</description>
      <category>kotlin</category>
      <category>kmp</category>
      <category>mobile</category>
    </item>
    <item>
      <title>New ImagePickerKMP API: The easiest way to handle Camera and Gallery in Kotlin Multiplatform</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Wed, 06 May 2026 05:15:16 +0000</pubDate>
      <link>https://dev.to/ismoy/new-imagepickerkmp-api-the-easiest-way-to-handle-camera-and-gallery-in-kotlin-multiplatform-16g</link>
      <guid>https://dev.to/ismoy/new-imagepickerkmp-api-the-easiest-way-to-handle-camera-and-gallery-in-kotlin-multiplatform-16g</guid>
      <description>&lt;p&gt;Handling camera and gallery in Kotlin Multiplatform has always been difficult.&lt;/p&gt;

&lt;p&gt;Different APIs for Android and iOS.&lt;br&gt;&lt;br&gt;
Permissions everywhere.&lt;br&gt;&lt;br&gt;
State management with booleans like showCamera and showGallery.&lt;/p&gt;

&lt;p&gt;This changes with the new API introduced in ImagePickerKMP, which provides a cleaner, reactive, and truly multiplatform approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with current solutions
&lt;/h2&gt;

&lt;p&gt;If you have worked with KMP and media input, you have likely faced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Platform-specific implementations
&lt;/li&gt;
&lt;li&gt;Complex permission flows
&lt;/li&gt;
&lt;li&gt;UI inconsistencies between Android and iOS
&lt;/li&gt;
&lt;li&gt;State handling with multiple flags (showCamera, showGallery, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most existing solutions are also not designed with Compose Multiplatform as a first-class approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing the new API: rememberImagePickerKMP
&lt;/h2&gt;

&lt;p&gt;The new recommended API is:&lt;/p&gt;

&lt;p&gt;kotlin val picker = rememberImagePickerKMP(...) &lt;/p&gt;

&lt;p&gt;This API provides a state-driven approach that controls the entire flow.&lt;/p&gt;

&lt;p&gt;It returns an ImagePickerKMPState, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles camera and gallery&lt;/li&gt;
&lt;li&gt;Exposes a reactive result&lt;/li&gt;
&lt;li&gt;Eliminates the need for manual UI triggers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no need for Render() calls or manual UI handling.&lt;/p&gt;

&lt;p&gt;More details: &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Launch camera or gallery
&lt;/h2&gt;

&lt;p&gt;kotlin picker.launchCamera() picker.launchGallery() &lt;/p&gt;

&lt;p&gt;Each call:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opens the appropriate UI&lt;/li&gt;
&lt;li&gt;Applies configuration automatically&lt;/li&gt;
&lt;li&gt;Returns results reactively&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can override configuration per launch without modifying global state.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reactive result handling
&lt;/h2&gt;

&lt;p&gt;Instead of multiple callbacks:&lt;/p&gt;

&lt;p&gt;kotlin when (val result = picker.result) {     is Success -&amp;gt; { /* use image &lt;em&gt;/ }     is Error -&amp;gt; { /&lt;/em&gt; handle error */ } } &lt;/p&gt;

&lt;p&gt;The result is modeled as a sealed hierarchy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Idle&lt;/li&gt;
&lt;li&gt;Loading&lt;/li&gt;
&lt;li&gt;Success&lt;/li&gt;
&lt;li&gt;Dismissed&lt;/li&gt;
&lt;li&gt;Error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This leads to a more predictable and maintainable UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unified configuration
&lt;/h2&gt;

&lt;p&gt;The API introduces a single configuration object:&lt;/p&gt;

&lt;p&gt;kotlin ImagePickerKMPConfig(...) &lt;/p&gt;

&lt;p&gt;This controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Camera behavior
&lt;/li&gt;
&lt;li&gt;Gallery selection (multi-select, MIME types, limits)
&lt;/li&gt;
&lt;li&gt;Crop options (square, circular, freeform)
&lt;/li&gt;
&lt;li&gt;UI customization
&lt;/li&gt;
&lt;li&gt;Permissions
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is centralized in one place.&lt;/p&gt;




&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;ImagePickerKMP provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native camera (zoom, flash, rotation)
&lt;/li&gt;
&lt;li&gt;Gallery support (single and multiple selection)
&lt;/li&gt;
&lt;li&gt;Built-in crop UI
&lt;/li&gt;
&lt;li&gt;EXIF metadata (GPS, ISO, etc.)
&lt;/li&gt;
&lt;li&gt;Compression levels (LOW, MEDIUM, HIGH)
&lt;/li&gt;
&lt;li&gt;PDF support
&lt;/li&gt;
&lt;li&gt;Cloud OCR integration (Gemini, OpenAI, Claude, etc.)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compatible with Android, iOS, Desktop, Web, and WASM.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this API matters
&lt;/h2&gt;

&lt;p&gt;Key improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eliminates boolean-based state handling
&lt;/li&gt;
&lt;li&gt;Removes manual UI rendering
&lt;/li&gt;
&lt;li&gt;Fully reactive state model
&lt;/li&gt;
&lt;li&gt;Compose-first design
&lt;/li&gt;
&lt;li&gt;Supports per-launch configuration overrides
&lt;/li&gt;
&lt;li&gt;Cleaner and scalable architecture
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;kotlin implementation("io.github.ismoy:imagepickerkmp:1.0.35") &lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kotlin 2.3.x
&lt;/li&gt;
&lt;li&gt;Compose Multiplatform 1.10+
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information: &lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Full documentation, examples, and API reference are available at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://imagepickerkmp.dev/" rel="noopener noreferrer"&gt;https://imagepickerkmp.dev/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Handling media input in Kotlin Multiplatform should not require complex platform-specific logic.&lt;/p&gt;

&lt;p&gt;This API simplifies the process and provides a consistent way to work with camera and gallery across platforms.&lt;/p&gt;




&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What has been your main challenge when working with image pickers in KMP?
&lt;/li&gt;
&lt;li&gt;What features would you like to see next?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-———————&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>kotlin</category>
      <category>mobile</category>
    </item>
    <item>
      <title>ImagePickerKMP 1.0.23: Controling Camera Launch on iOS with `directCameraLaunch`</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Wed, 03 Sep 2025 11:51:36 +0000</pubDate>
      <link>https://dev.to/ismoy/imagepickerkmp-1023-controling-camera-launch-on-ios-with-directcameralaunch-3bjn</link>
      <guid>https://dev.to/ismoy/imagepickerkmp-1023-controling-camera-launch-on-ios-with-directcameralaunch-3bjn</guid>
      <description>&lt;p&gt;The latest release of &lt;strong&gt;ImagePickerKMP (v1.0.23)&lt;/strong&gt; brings a small but&lt;br&gt;
powerful addition for iOS developers: a new flag called&lt;br&gt;
&lt;code&gt;directCameraLaunch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This feature gives you control over whether the image picker should&lt;br&gt;
&lt;strong&gt;open directly into the camera&lt;/strong&gt; or show the &lt;strong&gt;source selection&lt;br&gt;
dialog&lt;/strong&gt; first.&lt;/p&gt;
&lt;h2&gt;
  
  
  The New Flag: &lt;code&gt;directCameraLaunch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;By default, the picker shows a dialog on iOS asking the user to choose&lt;br&gt;
between camera and gallery.\&lt;br&gt;
With &lt;code&gt;directCameraLaunch&lt;/code&gt;, you can now change that behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;directCameraLaunch = true&lt;/code&gt; → Skips the dialog and opens the
&lt;strong&gt;camera immediately&lt;/strong&gt;.\&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;directCameraLaunch = false&lt;/code&gt; → Keeps the &lt;strong&gt;dialog&lt;/strong&gt; so the user can
choose.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Usage Example
&lt;/h2&gt;

&lt;p&gt;Here's how you can use it with &lt;code&gt;ImagePickerLauncher&lt;/code&gt; in your Compose&lt;br&gt;
Multiplatform project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="nc"&gt;ImagePickerLauncher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagePickerConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;onPhotoCaptured&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;capturedPhoto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
                &lt;span class="n"&gt;showCamera&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;showCamera&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onDismiss&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;showImagePicker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// Reset state when user doesn't select anything&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;directCameraLaunch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// Set to true if you want to launch the camera directly Only IOS&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This new option provides &lt;strong&gt;better UX flexibility&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Apps that want a streamlined flow (e.g., scanning receipts, IDs, QR
codes) can go straight to the camera.\&lt;/li&gt;
&lt;li&gt;  Apps that want to offer both gallery and camera selection can keep
the dialog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: you now have the best of both worlds, controlled with a simple&lt;br&gt;
flag.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dependency
&lt;/h2&gt;

&lt;p&gt;To try it out, update your Gradle dependency to the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.github.ismoy:imagepickerkmp:1.0.23"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;directCameraLaunch&lt;/code&gt; flag makes ImagePickerKMP even more versatile&lt;br&gt;
for real-world use cases. Whether your app prioritizes fast camera&lt;br&gt;
access or user choice, you can now support both seamlessly with version&lt;br&gt;
&lt;strong&gt;1.0.23&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Are you planning to use &lt;code&gt;directCameraLaunch&lt;/code&gt; in your project? Would you&lt;br&gt;
prefer the dialog or direct camera launch by default?&lt;/p&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/ismoy/ImagePickerKMP" rel="noopener noreferrer"&gt;https://github.com/ismoy/ImagePickerKMP&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Kotlin Multiplatform + Compose: Unified Camera &amp; Gallery Picker with Expect/Actual and Permission Handling</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Wed, 20 Aug 2025 13:55:30 +0000</pubDate>
      <link>https://dev.to/ismoy/kotlin-multiplatform-compose-unified-camera-gallery-picker-with-expectactual-and-permission-4573</link>
      <guid>https://dev.to/ismoy/kotlin-multiplatform-compose-unified-camera-gallery-picker-with-expectactual-and-permission-4573</guid>
      <description>&lt;p&gt;Handling image capture and gallery access in mobile apps is a task most developers face – but doing it the Kotlin Multiplatform way, using Compose, introduces unique challenges.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk through how to create a shared, composable-based image picker using Kotlin's expect/actual mechanism. The result is a unified camera and gallery experience for Android and iOS, fully integrated with Compose Multiplatform UI.&lt;/p&gt;

&lt;p&gt;The Problem with Platform-Specific Image Pickers&lt;br&gt;
Image picking requires different APIs on Android and iOS:&lt;/p&gt;

&lt;p&gt;• Android: ActivityResultContracts, CameraX, media permissions&lt;/p&gt;

&lt;p&gt;• iOS: UIImagePickerController, delegate protocols, Info.plist&lt;/p&gt;

&lt;p&gt;• Compose Multiplatform has no built-in media picker&lt;/p&gt;

&lt;p&gt;• Permissions and file access require different logic per platform&lt;br&gt;
We want to hide this complexity and give developers a clean, shared interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Define expect functions in commonMain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We declare our public API with expect composables. These serve as the shared contract across platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ImagePickerLauncher&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
expect fun ImagePickerLauncher(
    config: ImagePickerConfig
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This picker handles capturing a photo with the camera. The config provides callbacks like onPhotoCaptured, onError, and onDismiss.&lt;/p&gt;

&lt;p&gt;GalleryPickerLauncher&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
expect fun GalleryPickerLauncher(
    onPhotosSelected: (List&amp;lt;PhotoResult&amp;gt;) -&amp;gt; Unit,
    onError: (Exception) -&amp;gt; Unit,
    onDismiss: () -&amp;gt; Unit = {},
    allowMultiple: Boolean = false,
    mimeTypes: List&amp;lt;String&amp;gt; = listOf("image/*"),
    selectionLimit: Long = SELECTION_LIMIT
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This version supports selecting one or multiple images and filtering by MIME type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Android Implementation&lt;/strong&gt;&lt;br&gt;
The Android actual implementation uses Compose with platform-aware context handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
actual fun ImagePickerLauncher(config: ImagePickerConfig) {
    val context = LocalContext.current
    if (context !is ComponentActivity) {
        config.onError(Exception("Invalid context"))
        return
    }

    CameraCaptureView(
        activity = context,
        onPhotoResult = { result -&amp;gt; config.onPhotoCaptured(result) },
        onPhotosSelected = config.onPhotosSelected,
        onError = config.onError,
        onDismiss = config.onDismiss,
        cameraCaptureConfig = config.cameraCaptureConfig
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For gallery access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
actual fun GalleryPickerLauncher(...) {
    val context = LocalContext.current
    if (context !is ComponentActivity) {
        onError(Exception("Invalid context"))
        return
    }

    val config = GalleryPickerConfig(
        context = context,
        onPhotosSelected = onPhotosSelected,
        onError = onError,
        onDismiss = onDismiss,
        allowMultiple = allowMultiple,
        mimeTypes = mimeTypes
    )

    GalleryPickerLauncherContent(config)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;iOS Implementation&lt;/strong&gt;&lt;br&gt;
On iOS, we integrate UIKit behavior with Compose state, launching the correct picker depending on user action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
actual fun ImagePickerLauncher(config: ImagePickerConfig) {
    var showDialog by remember { mutableStateOf(true) }
    var askCameraPermission by remember { mutableStateOf(false) }
    var launchCamera by remember { mutableStateOf(false) }
    var launchGallery by remember { mutableStateOf(false) }

    handleImagePickerState(
        showDialog = showDialog,
        askCameraPermission = askCameraPermission,
        launchCamera = launchCamera,
        launchGallery = launchGallery,
        config = config,
        onDismissDialog = { showDialog = false },
        onCancelDialog = {
            showDialog = false
            config.onDismiss()
        },
        onRequestCameraPermission = { askCameraPermission = true },
        onRequestGallery = { launchGallery = true },
        onCameraPermissionGranted = {
            askCameraPermission = false
            launchCamera = true
        },
        onCameraPermissionDenied = {
            askCameraPermission = false
            config.onDismiss()
        },
        onCameraFinished = { launchCamera = false },
        onGalleryFinished = { launchGallery = false }
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for gallery selection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
actual fun GalleryPickerLauncher(...) {
    LaunchedEffect(Unit) {
        if (allowMultiple) {
            val selectedImages = mutableListOf&amp;lt;PhotoResult&amp;gt;()
            GalleryPickerOrchestrator.launchGallery(
                onPhotoSelected = { result -&amp;gt;
                    selectedImages.add(result)
                    onPhotosSelected(selectedImages.toList())
                },
                onError = onError,
                onDismiss = onDismiss,
                allowMultiple = true,
                selectionLimit = selectionLimit
            )
        } else {
            GalleryPickerOrchestrator.launchGallery(
                onPhotoSelected = { result -&amp;gt; onPhotosSelected(listOf(result)) },
                onError = onError,
                onDismiss = onDismiss,
                allowMultiple = false,
                selectionLimit = 1
            )
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How It All Comes Together in Compose&lt;/strong&gt;&lt;br&gt;
With both platform implementations hidden, your shared Compose code stays clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (showCamera) {
    ImagePickerLauncher(
        config = ImagePickerConfig(
            onPhotoCaptured = { photo -&amp;gt; capturedPhoto = photo },
            onError = { showError = true },
            onDismiss = { showCamera = false }
        )
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for gallery:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (showGallery) {
    GalleryPickerLauncher(
        onPhotosSelected = { photos -&amp;gt; selectedImages = photos },
        onError = { showError = true },
        onDismiss = { showGallery = false },
        allowMultiple = true
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Pattern Works&lt;/strong&gt;&lt;br&gt;
• Shared UI remains fully declarative and platform-agnostic&lt;/p&gt;

&lt;p&gt;• Permissions and platform quirks are abstracted&lt;/p&gt;

&lt;p&gt;• It respects Compose principles and KMP architecture&lt;/p&gt;

&lt;p&gt;• You avoid boilerplate and platform channels&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kotlin Multiplatform offers powerful abstractions when used correctly. By leveraging expect/actual and fully composable APIs, we've built a clean, testable, and scalable image picker that works across platforms.&lt;/p&gt;

&lt;p&gt;You can explore the full implementation in &lt;a href="https://github.com/ismoy/ImagePickerKMP" rel="noopener noreferrer"&gt;ImagePickerKMP&lt;/a&gt;, an open-source project that follows these principles. Whether you use it directly or as inspiration, it's a practical example of Compose and KMP working in harmony.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>kotlin</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>🎯 What’s New in v1.0.21?</title>
      <dc:creator>Ismoy Belizaire</dc:creator>
      <pubDate>Tue, 12 Aug 2025 14:56:03 +0000</pubDate>
      <link>https://dev.to/ismoy/whats-new-in-v1021-3lk4</link>
      <guid>https://dev.to/ismoy/whats-new-in-v1021-3lk4</guid>
      <description>&lt;p&gt;🎉 &lt;strong&gt;ImagePickerKMP v1.0.21 – A Fresh New Look for iOS &amp;amp; Android!&lt;/strong&gt; 🎉  &lt;/p&gt;

&lt;p&gt;Hey there, fellow Kotlin Multiplatform enthusiasts!  &lt;/p&gt;

&lt;p&gt;I’m thrilled to announce the latest release of &lt;strong&gt;ImagePickerKMP&lt;/strong&gt; – the cross‑platform image picker &amp;amp; camera library that lets you pull photos from the gallery or capture new ones with a single line of code. 🚀  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; v1.0.21
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag:&lt;/strong&gt; &lt;a href="https://github.com/ismoy/ImagePickerKMP/releases/tag/v1.0.21" rel="noopener noreferrer"&gt;v1.0.21&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt; 2025‑08‑11
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/ismoy/ImagePickerKMP" rel="noopener noreferrer"&gt;ImagePickerKMP on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this update, we’re adding &lt;em&gt;custom bottom sheet support for iOS&lt;/em&gt; and &lt;em&gt;customizable confirmation UI for Android&lt;/em&gt;. Let’s dive into the details!  &lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 What’s New in v1.0.21?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Custom Bottom Sheet on iOS
&lt;/h3&gt;

&lt;p&gt;Previously, the iOS picker presented the standard &lt;code&gt;UIImagePickerController&lt;/code&gt; UI. While functional, it left designers with limited styling options. This release introduces a &lt;strong&gt;&lt;code&gt;CustomBottomSheet&lt;/code&gt;&lt;/strong&gt; component that can be fully themed, animated, and integrated into your Compose UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;ImagePicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Custom bottom sheet&lt;/span&gt;
    &lt;span class="n"&gt;bottomSheet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class="nc"&gt;CustomBottomSheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;onDismiss&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BottomSheetStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;White&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;cornerRadius&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Key benefits:&lt;/em&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎨 Full control over colors, shapes, and shadows.
&lt;/li&gt;
&lt;li&gt;📲 Seamless integration with your existing Compose layout.
&lt;/li&gt;
&lt;li&gt;🔄 Consistent behavior across iOS versions.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2️⃣ Customizable Confirmation View on Android
&lt;/h3&gt;

&lt;p&gt;On Android, after a user selects an image, the picker used to show a default “Confirm” dialog. We now provide a &lt;strong&gt;&lt;code&gt;ConfirmView&lt;/code&gt;&lt;/strong&gt; composable that can be swapped out for any design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;ImagePicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Android&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;confirmView&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nc"&gt;MyCustomConfirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;onConfirm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Handle confirm */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;onCancel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Handle cancel */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;What you can change:&lt;/em&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Button styles, text, icons.
&lt;/li&gt;
&lt;li&gt;Layout – grid, carousel, or single‑image preview.
&lt;/li&gt;
&lt;li&gt;Animation – fade, slide, or custom physics.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These changes empower designers to keep the UI in line with their brand while still leveraging the power of Kotlin Multiplatform.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Improvements &amp;amp; Fixes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;iOS Picker&lt;/td&gt;
&lt;td&gt;The picker would crash on iOS 16 if the user denied camera permission.&lt;/td&gt;
&lt;td&gt;Added robust permission handling and graceful fallback.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android Picker&lt;/td&gt;
&lt;td&gt;Confirmation dialog flickered on orientation change.&lt;/td&gt;
&lt;td&gt;Implemented state‑saving across configuration changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Minor lag when loading high‑resolution images.&lt;/td&gt;
&lt;td&gt;Optimized bitmap decoding with &lt;code&gt;ImageDecoder&lt;/code&gt; and lazy loading.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;bottomSheet&lt;/code&gt; API lacked examples.&lt;/td&gt;
&lt;td&gt;Updated README with usage snippets and style reference.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency Management&lt;/td&gt;
&lt;td&gt;Outdated Compose Multiplatform version (1.5.0).&lt;/td&gt;
&lt;td&gt;Bumped to 1.5.2 and updated compiler flags.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you’re still on Kotlin 1.9.10 or Compose 1.5.0, consider upgrading to benefit from the performance tweaks and bug fixes.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📦 How to Update
&lt;/h2&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;Add the dependency&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you’re already using ImagePickerKMP, simply bump the version in your &lt;code&gt;build.gradle.kts&lt;/code&gt; (or &lt;code&gt;build.gradle&lt;/code&gt; if you’re using Groovy).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.ismoy:ImagePickerKMP:1.0.21"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2️⃣ &lt;strong&gt;Sync &amp;amp; Rebuild&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Run &lt;code&gt;./gradlew clean build&lt;/code&gt; or use your IDE’s Gradle sync.  &lt;/p&gt;

&lt;p&gt;3️⃣ &lt;strong&gt;Migrate Custom UI&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you’re using the new custom bottom sheet or confirmation view, replace the old API calls with the new ones shown above.  &lt;/p&gt;

&lt;p&gt;4️⃣ &lt;strong&gt;Test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Run your app on both Android and iOS simulators/devices to confirm the UI behaves as expected.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; No breaking changes in the public API, so your existing code should compile without modification unless you decide to adopt the new custom UI components.&lt;/p&gt;




&lt;h2&gt;
  
  
  🙏 A Huge Thank You!
&lt;/h2&gt;

&lt;p&gt;This release wouldn’t have been possible without the dedication of the community. A special shout‑out to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/ismoy"&gt;@ismoy&lt;/a&gt;&lt;/strong&gt; – for spearheading the project and keeping the roadmap steady.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All contributors&lt;/strong&gt; – for reviewing PRs, reporting bugs, and suggesting UI tweaks.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your feedback keeps this library robust and user‑friendly. Keep the issues coming, and let’s keep building great cross‑platform code together!  &lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Try It Out Today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Download&lt;/strong&gt; the latest release from the &lt;a href="https://github.com/ismoy/ImagePickerKMP/releases/tag/v1.0.21" rel="noopener noreferrer"&gt;Releases page&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore&lt;/strong&gt; the new demo app in the &lt;code&gt;demo&lt;/code&gt; folder – it now showcases the custom bottom sheet on iOS and the custom confirmation view on Android.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share&lt;/strong&gt; your experience on Twitter or LinkedIn using #ImagePickerKMP and let us know how you’re styling your picker!
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to fork the repo, experiment with the new UI components, and submit your own pull requests. The library is open source, and every contribution helps make cross‑platform development smoother for everyone.  &lt;/p&gt;




&lt;h3&gt;
  
  
  Quick Recap
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;How to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Custom Bottom Sheet&lt;/td&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bottomSheet = { image -&amp;gt; CustomBottomSheet(...) }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Confirmation View&lt;/td&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;&lt;code&gt;confirmView = { image -&amp;gt; MyCustomConfirm(...) }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permission Handling&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;td&gt;Automatic – no extra code needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance Optimizations&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;td&gt;Transparent – just upgrade!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Got questions? Drop an issue on GitHub or ping me on Discord (link in the README).  &lt;/p&gt;

&lt;p&gt;Let’s keep the momentum going and continue to push the boundaries of what Kotlin Multiplatform can do!  &lt;/p&gt;

&lt;p&gt;Happy coding! 🧑‍💻✨  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/ismoy/ImagePickerKMP" rel="noopener noreferrer"&gt;https://github.com/ismoy/ImagePickerKMP&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Release Tag:&lt;/strong&gt; &lt;a href="https://github.com/ismoy/ImagePickerKMP/releases/tag/v1.0.21" rel="noopener noreferrer"&gt;https://github.com/ismoy/ImagePickerKMP/releases/tag/v1.0.21&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Stars:&lt;/strong&gt; ⭐ 38 | &lt;strong&gt;Forks:&lt;/strong&gt; 🍴 4 | &lt;strong&gt;Contributors:&lt;/strong&gt; 👥 1  &lt;/p&gt;




&lt;p&gt;&lt;em&gt;Keep exploring. Keep sharing. Keep building.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>development</category>
      <category>programming</category>
      <category>opensource</category>
      <category>github</category>
    </item>
  </channel>
</rss>
