Skip to content

feat: add zoom ratio API (setZoomRatio) to ICameraProvider#566

Merged
wysaid merged 6 commits intomasterfrom
feature/zoom-ratio
Feb 28, 2026
Merged

feat: add zoom ratio API (setZoomRatio) to ICameraProvider#566
wysaid merged 6 commits intomasterfrom
feature/zoom-ratio

Conversation

@wysaid
Copy link
Owner

@wysaid wysaid commented Feb 28, 2026

Summary

Adds a zoom ratio API to the ICameraProvider abstraction layer, enabling callers to control optical/digital zoom on both the CameraX and Camera1 backends.

Closes #529

Changes

ICameraProvider — new interface methods (all with default no-ops, zero breaking changes)

Method Description
boolean isZoomSupported() Whether the hardware supports zoom
float getMinZoomRatio() Minimum ratio (always 1.0)
float getMaxZoomRatio() Maximum ratio reported by the hardware
void setZoomRatio(float ratio) Set zoom to the given ratio

CameraXProvider

  • isZoomSupported() → always true (CameraX always supports zoom)
  • getMin/MaxZoomRatio() → reads from CameraInfo.getZoomState()
  • setZoomRatio() → calls CameraControl.setZoomRatio() (async, fire-and-forget)

Camera1Provider

  • isZoomSupported() → delegates to Camera.Parameters.isZoomSupported()
  • getMaxZoomRatio() → reads getZoomRatios().get(getMaxZoom()) / 100f
  • setZoomRatio() → maps float ratio to the closest discrete integer zoom index via Parameters.setZoom(int); slight rounding is expected (Camera1 only exposes discrete steps)

Backward Compatibility

All four methods use default implementations, so any custom ICameraProvider that does not override them compiles and runs without change.

How to verify

ICameraProvider provider = ...; // Camera1 or CameraX
if (provider.isZoomSupported()) {
    float max = provider.getMaxZoomRatio();
    provider.setZoomRatio(max / 2f); // zoom to half of max
}

Summary by CodeRabbit

  • New Features
    • System-wide zoom support: check availability, read min/max zoom ratios, and set a floating-point zoom level across legacy and modern camera implementations; requests are clamped to supported ranges and safely no-op when unavailable.
  • Documentation
    • Updated contributor guidance for review policy handling and P3 classification procedures.

…mera1Provider

- ICameraProvider: add isZoomSupported(), getMinZoomRatio(), getMaxZoomRatio(),
  and setZoomRatio(float) with default no-op implementations so existing
  code requires no changes
- CameraXProvider: implement via CameraControl.setZoomRatio() and
  CameraInfo.getZoomState(); always supported
- Camera1Provider: implement by mapping float ratio to the nearest
  Camera.Parameters integer zoom index; guarded by isZoomSupported()

Closes #529
Copilot AI review requested due to automatic review settings February 28, 2026 15:16
@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds floating-point zoom controls to the camera provider API: new methods to query support and min/max ratios and to set a zoom ratio. Camera1 maps float ratios to discrete Camera.Parameters zoom indices; CameraX uses ZoomState and CameraControl to apply linear zoom.

Changes

Cohort / File(s) Summary
Interface
library/src/main/java/org/wysaid/camera/ICameraProvider.java
Added default zoom API methods: isZoomSupported(), getMinZoomRatio(), getMaxZoomRatio(), setZoomRatio(float) with fallback defaults and documentation notes about provider behavior.
Camera1 implementation
library/src/main/java/org/wysaid/camera/Camera1Provider.java
Added isZoomSupported(), getMinZoomRatio(), getMaxZoomRatio(), setZoomRatio(float). Reads Camera.Parameters/zoom ratios, converts between discrete zoom indices and float ratios, selects nearest index, applies zoom with null/unsupported checks and exception handling.
CameraX implementation
library/src/main/java/org/wysaid/camera/CameraXProvider.java
Added isZoomSupported(), getMinZoomRatio(), getMaxZoomRatio(), setZoomRatio(float). Uses ZoomState for bounds and CameraControl to set linear zoom (clamped to [min,max]) with main-thread callback and availability guards.
Docs / policy
.github/skills/pr-review/SKILL.md
Documentation-only edits: updated P3 policy label/handling and Review Restraint Policy procedure; sample table entries adjusted.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Camera1Provider
  participant CameraParameters as "Camera.Parameters"
  Client->>Camera1Provider: setZoomRatio(ratio)
  Camera1Provider->>CameraParameters: getZoomRatios() / getMaxZoom()
  Camera1Provider->>Camera1Provider: compute nearest discrete index
  Camera1Provider->>CameraParameters: setZoom(index)
  CameraParameters-->>Camera1Provider: success / exception
  Camera1Provider-->>Client: return / log error
Loading
sequenceDiagram
  participant Client
  participant CameraXProvider
  participant ZoomState
  participant CameraControl
  Client->>CameraXProvider: setZoomRatio(ratio)
  CameraXProvider->>ZoomState: getMinMaxZoom()
  CameraXProvider->>CameraXProvider: clamp ratio to [min,max]
  CameraXProvider->>CameraControl: setLinearZoom(clampedRatio)
  CameraControl-->>CameraXProvider: onComplete callback
  CameraXProvider-->>Client: return / log warning if unavailable
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I hopped in code from wide to near,
Ratios whispered, indexes clear,
Camera1 and X now bow,
Zooming softly — take a bow! 📸

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and specifically summarizes the main change: adding a zoom ratio API (setZoomRatio) to the ICameraProvider interface.
Linked Issues check ✅ Passed The PR implements zoom support for both CameraX and Camera1 backends via the ICameraProvider interface, directly addressing issue #529's request for camera zoom/magnification controls.
Out of Scope Changes check ✅ Passed All changes are in-scope: four zoom methods added to three camera provider classes, plus documentation updates to the PR review policy unrelated to zoom functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/zoom-ratio

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a zoom ratio API to the ICameraProvider abstraction so callers can control zoom consistently across both CameraX and Camera1 backends (addresses #529).

Changes:

  • Adds default (no-op) zoom methods to ICameraProvider: isZoomSupported, getMinZoomRatio, getMaxZoomRatio, setZoomRatio.
  • Implements zoom support in CameraXProvider using ZoomState and CameraControl.setZoomRatio(...).
  • Implements zoom support in Camera1Provider by mapping a float ratio to the closest discrete Parameters.setZoom(int) index.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
library/src/main/java/org/wysaid/camera/ICameraProvider.java Introduces the new zoom-related interface methods with default implementations to avoid breaking existing implementors.
library/src/main/java/org/wysaid/camera/CameraXProvider.java Wires zoom to CameraX ZoomState/CameraControl.
library/src/main/java/org/wysaid/camera/Camera1Provider.java Adds Camera1 zoom support via Parameters.isZoomSupported(), getZoomRatios(), and discrete zoom index selection.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@library/src/main/java/org/wysaid/camera/CameraXProvider.java`:
- Around line 367-375: Clamp the incoming ratio in setZoomRatio before passing
to CameraControl: if mCamera is null return as before; otherwise compute a
clamped value using getMinZoomRatio() and getMaxZoomRatio() and call
mCamera.getCameraControl().setZoomRatio(clampedRatio) (still using
ContextCompat.getMainExecutor(mContext) and the existing listener). This ensures
setZoomRatio honors the ICameraProvider contract and avoids passing out-of-range
values to CameraControl.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f37e3b4 and 575b55f.

📒 Files selected for processing (3)
  • library/src/main/java/org/wysaid/camera/Camera1Provider.java
  • library/src/main/java/org/wysaid/camera/CameraXProvider.java
  • library/src/main/java/org/wysaid/camera/ICameraProvider.java

…ZoomRatio

- isZoomSupported() now returns false when camera is not yet bound or
  ZoomState is unavailable, giving callers a reliable capability check
- setZoomRatio() clamps the incoming ratio to [min, max] before passing
  to CameraControl, honoring the ICameraProvider contract
- observe the returned ListenableFuture to log errors instead of silently
  discarding failures
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@library/src/main/java/org/wysaid/camera/Camera1Provider.java`:
- Around line 166-183: In setZoomRatio, guard against invalid ratio inputs and
null/empty zoomRatios: validate the float ratio passed into
Camera1Provider.setZoomRatio (reject or clamp NaN and Infinity and ensure it
falls within a sensible range, e.g., 0.0–1.0 or derived from parameters) and
check that params.getZoomRatios() is not null and not empty before using size()
or iterating; if the list is empty or zoom is unsupported, return early. Also
ensure you handle the case where CameraInstance.getInstance().getParams()
returns null (early return) and only compute bestIndex when zoomRatios is
present. Use the existing symbols (CameraInstance.getInstance().getParams(),
params.isZoomSupported(), params.getZoomRatios(), and the bestIndex loop) to
locate and apply these guards.
- Around line 159-163: The code in Camera1Provider indexes
params.getZoomRatios() without validating the list; add defensive checks in the
method that fetches zoom ratio: retrieve List<Integer> ratios from
Camera.Parameters, return 1.0f if ratios is null or empty, and if ratios.size()
<= params.getMaxZoom() use a safe index (e.g., Math.min(params.getMaxZoom(),
ratios.size() - 1)) to pick the ratio; keep the rest of the logic (divide by
100.0f) the same so vendor-broken implementations won't crash when calling
params.getMaxZoom().

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6568b70 and 06488b1.

📒 Files selected for processing (1)
  • library/src/main/java/org/wysaid/camera/Camera1Provider.java

wysaid added 2 commits March 1, 2026 00:54
- getMaxZoomRatio: guard against null/empty getZoomRatios() list
  and use Math.min to avoid ArrayIndexOutOfBoundsException on
  vendor devices where list size < getMaxZoom() + 1
- setZoomRatio: reject NaN/Infinity/non-positive ratio early;
  guard against null/empty zoomRatios list; use long arithmetic
  to avoid int overflow in diff computation

Addresses coderabbitai review comments (Critical + Major).
Eliminate repeated CameraInstance.getInstance().getParams() calls (5 sites)
and the duplicated zoom-support guard (params == null || !isZoomSupported)
by introducing two private helpers:

- getParams(): shorthand wrapper, no behavioral change
- getZoomParams(): returns params only when camera is open and zoom is
  supported; used by isZoomSupported, getMaxZoomRatio, setZoomRatio

Pure structural cleanup, zero logic change.
@wysaid wysaid merged commit e672a8e into master Feb 28, 2026
6 checks passed
@wysaid wysaid deleted the feature/zoom-ratio branch February 28, 2026 17:12
wysaid added a commit that referenced this pull request Mar 6, 2026
- Rename CHANGE.md -> CHANGELOG.md (standard Keep a Changelog convention)
- Rewrite in standard Markdown format (## [version] — date headings)
- Fill in missing history gaps between v2.5.0 (2018) and v3.1.1 (2026):
  - v3.1.2, v3.1.1, v2.7.0-alpha with full feature/fix/perf/chore entries
  - Source: GitHub Releases, merged PRs (#510#566), and git log
- Add [Unreleased] section tracking master commits not yet tagged
- Fix copyright year range in LICENSE: 2017 -> 2017-2026
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.

是否可以支持一下缩放

2 participants