Skip to content

feat: add optional targetResolution to preview output - #4239

Open
ismaelsousa wants to merge 24 commits into
margelo:mainfrom
ismaelsousa:feat/add-optional-targetresolution-preview
Open

ismaelsousa wants to merge 24 commits into
margelo:mainfrom
ismaelsousa:feat/add-optional-targetresolution-preview

Conversation

@ismaelsousa

@ismaelsousa ismaelsousa commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #4224

What

Adds an optional targetResolution to the Preview output, plus an optional previewTargetResolution prop on <Camera />.

  • PreviewOutputOptions.targetResolution?: Size
  • usePreviewOutput({ targetResolution }) (memoized by value via useMemoizedSize, like the other output hooks)
  • <Camera previewTargetResolution={...} />
  • Android: the CameraX Preview gets a ResolutionSelector that sorts sizes by closest to the target
  • iOS: targetResolution returns .closestTo(...) when set, otherwise the existing screen-size bias is unchanged

When omitted, behavior is unchanged on both platforms.

Why

Every output is a view of the same sensor, and outputs with different aspect ratios crop it differently. The Preview can then show more (or less) than a Frame/Photo/Video output actually sees.

This is mainly an Android problem. CameraX picks a default aspect ratio per use case: image capture/analysis default to 4:3, video usually resolves to 16:9, and the Preview defaults to 4:3. A 16:9 video next to a 4:3 Preview covers a different area than what the user sees, and Android ignores resolutionBias, so the Preview could not be steered before.

Setting the Preview's targetResolution to match another output (e.g. the video output) aligns their field of view.

On iOS every output derives from the resolved active format, so targetResolution should not be specified there; use a resolutionBias constraint to steer the resolution instead. This is documented.

Docs

Rewrote the "Preview Resolution" section in preview-output.mdx (the old text said the Preview has no configurable target resolution) and documented the option in JSDoc.

Notes

targetResolution is a preference negotiated with the session's other outputs, so the resulting resolution may differ; use onConfigurationChanged / onPreviewResolution to read the actual size.

Example

Android (Samsung SM-A556E). The example draws the four corners of the frame output (always HD_16_9) as red dots on the preview. If the preview and the frame cover the same area, the dots sit on the preview's corners.

Stock preview targetResolution mismatched targetResolution matched
The stock preview picks its own (4:3) size, so the 16:9 frame corners land inside the image. Preview at FHD_4_3 (1080 × 1440) with a HD_16_9 frame: the 4:3 preview shows more than the frame, so the dots are inset. Preview and frame both HD_16_9 (720 × 1280): the dots sit exactly on the preview corners.

Store and forward outputOrientation to Preview.targetRotation so CameraX updates ResolutionInfo for the new target orientation. This keeps resolutionInfo.rotationDegrees synchronized instead of leaving it based on the default rotation.
Use AVCaptureDevice.RotationCoordinator on iOS 17 and later, creating the interface orientation manager only on older versions. Apply preview rotation updates synchronously and clean up observation on reconfiguration and deinit.

Related PR: margelo#4237

Validation: VisionCamera iOS target build, Swift formatting, and git diff --check passed.
…nfiguration because does nothing anymore on android
@vercel

vercel Bot commented Nov 1, 2026

Copy link
Copy Markdown

@ismaelsousa is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

@ismaelsousa ismaelsousa changed the title Add optional targetResolution to preview output feat: add optional targetResolution to preview output Nov 1, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant