Skip to content

fix: make px crops export at a deterministic size#35

Open
paodb wants to merge 1 commit into
masterfrom
issue-33
Open

fix: make px crops export at a deterministic size#35
paodb wants to merge 1 commit into
masterfrom
issue-33

Conversation

@paodb

@paodb paodb commented Jul 20, 2026

Copy link
Copy Markdown
Member

Configured px crops mapped to the exported image via rendered (on-screen) pixels, so the output size varied with how the browser scaled the image at crop time (e.g. a 500×500 px crop could export at ~500 or ~667 px). This makes the mapping deterministic.

Changes

  • Store the crop as % (resolution-independent): onChange/onComplete now use react-image-crop's percentCrop.
  • onImageLoad normalizes the configured crop against the image's natural size; a px crop is interpreted as source (natural) pixels.
  • _updateCroppedImage maps the crop with convertToPixelCrop against naturalWidth/naturalHeight, dropping the rendered→natural rescaling.
  • Remove the now-redundant ResizeObserver/resizeCrop workaround (a % crop needs no rescaling on layout changes) and guard makeAspectCrop against an unset aspect.
  • Document that crop units are source pixels while the min/max crop constraints remain in rendered pixels.

Close #33

Summary by CodeRabbit

  • Bug Fixes

    • Improved crop stability across responsive layouts by keeping crop selections consistent through layout changes.
    • Ensured crop rendering and generated output are mapped using the image’s natural dimensions.
    • Improved handling when setting crop programmatically, including correct percent/% vs pixel conversions and aspect-ratio enforcement.
  • Documentation

    • Clarified meaning of % (resolution-independent) versus px (based on the image’s natural/source pixels).
    • Documented how crop min/max constraints are applied in rendered/on-screen pixels.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

Crop normalization

Layer / File(s) Summary
Crop unit semantics
src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java, src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java
Javadocs clarify that % crops are resolution-independent, px crops use natural image pixels, and min/max constraints use rendered pixels.
Percent crop rendering
src/main/resources/META-INF/resources/frontend/src/image-crop.tsx
Crop initialization and ReactCrop state now use percentages, while canvas rendering converts the crop directly to natural-pixel coordinates.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: javier-godoy

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The code and docs implement issue #33 by using percent crops, natural dimensions, and removing the resize workaround.
Out of Scope Changes check ✅ Passed The changes stay within the issue scope and only add related crop-handling and documentation updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: making px crop exports deterministic.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-33

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/resources/META-INF/resources/frontend/src/image-crop.tsx`:
- Around line 144-157: Update the onImageLoad normalization to preserve
explicitly supplied x and y coordinates by removing the unconditional
makeAspectCrop and centerCrop calls. Move px-to-% conversion into a useEffect
that observes the crop state and image dimensions, converting programmatic
server updates before passing the crop to ReactCrop while leaving percentage
crops unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44225dc7-6409-410f-952f-89ba91e1c764

📥 Commits

Reviewing files that changed from the base of the PR and between c9c2cc8 and a7c450c.

📒 Files selected for processing (3)
  • src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java
  • src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java
  • src/main/resources/META-INF/resources/frontend/src/image-crop.tsx

Comment thread src/main/resources/META-INF/resources/frontend/src/image-crop.tsx
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/resources/META-INF/resources/frontend/src/image-crop.tsx (1)

271-278: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Prevent IndexSizeError crash on zero-dimension crops.

If the crop region has a width or height of zero (e.g., from an uninitialized state or programmatic update), outWidth or outHeight will evaluate to 0. Calling drawImage with a zero source width or height throws an IndexSizeError (or InvalidStateError) in browsers, which crashes the script execution and prevents subsequent logic from running. Consider adding an early return to handle this gracefully.

🛡️ Proposed fix
 				const outWidth = Math.round(ccrop.width);
 				const outHeight = Math.round(ccrop.height);
 
+				if (outWidth <= 0 || outHeight <= 0) {
+					return;
+				}
+
 				// Setting canvas dimensions resets the 2D context, so it must happen
 				// before any drawing/clipping state is configured below.
 				canvas.width = outWidth;
 				canvas.height = outHeight;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/resources/META-INF/resources/frontend/src/image-crop.tsx` around
lines 271 - 278, Add an early return in the crop-rendering flow after computing
outWidth and outHeight, before assigning canvas dimensions or calling drawImage,
when either dimension is zero or otherwise non-positive. Preserve the existing
rendering path for positive dimensions and allow subsequent logic to continue
without throwing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/main/resources/META-INF/resources/frontend/src/image-crop.tsx`:
- Around line 271-278: Add an early return in the crop-rendering flow after
computing outWidth and outHeight, before assigning canvas dimensions or calling
drawImage, when either dimension is zero or otherwise non-positive. Preserve the
existing rendering path for positive dimensions and allow subsequent logic to
continue without throwing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 808376d8-5c44-4867-9897-a49725681424

📥 Commits

Reviewing files that changed from the base of the PR and between a7c450c and 1464c6a.

📒 Files selected for processing (3)
  • src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java
  • src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java
  • src/main/resources/META-INF/resources/frontend/src/image-crop.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java

@paodb
paodb marked this pull request as ready for review July 20, 2026 21:01
@paodb
paodb requested review from javier-godoy and scardanzan July 20, 2026 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To Do

Development

Successfully merging this pull request may close these issues.

Configured px crops don't map deterministically to the output size

1 participant