ionic-team / ionic-team/capacitor-camera
chooseFromGallery returns the original library asset (HEIC on iOS) where pickImages re-encoded to JPEG
- Dominant language
- TypeScript
- Stars
- 4
- Forks
- 1
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 2
Description
### Summary
`chooseFromGallery` returns the original photo-library asset without re-encoding it, so on iOS a normally-shot iPhone photo comes back as HEIC. The deprecated `pickImages`/`getPhoto` it replaces always re-encoded to JPEG, so migrating off them is a behaviour change for any app that assumed a browser-renderable format.
This isn't obvious from the docs: `ChooseFromGalleryOptions` carries a `quality` field documented as "Only applicable for `MediaType.Photo` and JPEG format", which reads as though photos come back as JPEG.
### Where it happens
**iOS** — `IONCameraLib`'s `IONCAMRPhotoLibraryService.fetchImage(from:)` builds its result from `fetchImageURL(for: asset)`, which is `asset.requestContentEditingInput { … editingInput?.fullSizeImageURL }`. That URL is the original asset in the library; nothing decodes or re-encodes it.
Worth noting this applies to **both** selection modes, not just `allowMultipleSelection: true`. `didFinishPicking` branches on `thumbnailAsData` rather than on the selection mode:
```swift
if self.thumbnailAsData {
let results = await self.fetchMultipleResult(assetArray) // original asset URL
…
} else {
let item = await self.fetchSingleResult(assetArray.first) // UIImage → toData()
…
}
```
`IONCAMRGalleryOptions` decodes `thumbnailAsData` with a default of `true`, and `ChooseFromGalleryOptions` in the plugin's TypeScript has no field that maps to it — so a `chooseFromGallery` call can only ever take the first branch.
**Android** — `ioncamera-android`'s `onChooseFromGalleryResult` resolves the picked URI to a file path and passes it to `createImageMediaResult`, whose bitmap decode/`compress` feeds only the base64 thumbnail; the result's `uri` still names the original file. Less visible in practice because Android cameras usually write JPEG, but the same pass-through.
`takePhoto` is unaffected — `UIImage.toData(with:)` honours `encodingType`, which defaults to JPEG.
### Why it matters
HEIC uploads fine and then fails to render for most viewers: Chrome and Firefox decode none of it, and server-side `sharp`'s prebuilt libvips ships no HEVC decoder, so thumbnailing fails too. An app that offers "choose from library" and accepts what it gets will store images that a majority of its users see as broken — and the failure lands after upload, where the only remedy is rejecting a photo the user already chose.
Versions: `@capacitor/camera` 8.2.2, `IONCameraLib` 1.0.5, `ioncamera-android` 1.0.2.
### Steps to reproduce
1. On an iPhone with **Settings → Camera → Formats → High Efficiency**, take a photo.
2. Call `chooseFromGallery({ mediaType: MediaTypeSelection.Photo, includeMetadata: true })` and pick it.
3. `results[0].metadata.format` is `heic`, and `uri` points at a `.HEIC` file.
Expected (and what `pickImages` did): a JPEG.
### Possible resolutions
Any one of these would be enough, in rough order of preference:
1. Give `ChooseFromGalleryOptions` an `encodingType` like `TakePhotoOptions` has, and re-encode to it.
2. Re-encode gallery picks to JPEG by default, matching the deprecated methods' behaviour.
3. If pass-through is the intended design, say so in the `chooseFromGallery` docs and in the deprecation notes on `getPhoto`/`pickImages` — the format change is the migration's sharpest edge and currently isn't mentioned.
Contributor guide
Research direction
Start with IONCAMRPhotoLibraryService.fetchImage(from:) and its fetchImageURL(for: asset) path, then inspect didFinishPicking and the thumbnailAsData branches. Compare the iOS behavior with Android's onChooseFromGalleryResult and createImageMediaResult. Done means the chosen gallery format behavior is consistent with the selected resolution and the chooseFromGallery documentation explains the resulting encoding.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift, typescript
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100