-
-
Notifications
You must be signed in to change notification settings - Fork 177
Change rotated crop area output #312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change rotated crop area output #312
Conversation
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 64f2d91:
|
f5737c0 to
7ce1770
Compare
7ce1770 to
ff21a02
Compare
|
Thanks a lot for this PR and the effort! 🙂 I quickly had a look to the changes from my phone but I'll do a more extensive review of the code this week. I have a few remarks/suggestions already:
|
Thank you (and the rest of contributors) for the lib :)
The reason for these changes is that to calculate rendered media size, the solution was to use You are correct in saying that it doesn't sound right to change all the e2e tests, but the reason for this in my view is the fact that these tests test implementation details instead of actual results. What matters to the user is what the lib outputs - in our case it's
Ah! Sorry, didn't notice it there, thought it was somewhere else. Updated!
Will do |
|
I completely agree that current e2e tests are not very valuable. I think that we should replace most of them with visual regression tests as what matters is the visual output. Regarding using the container size, did you check that it works with all possible values of the |
|
Ah! I didn't, that will probably break, I'll fix it asap. Thank you |
Yeah, maybe like Chromatic or something similar, but I think just to test |
|
|
ValentinH
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a few suggestions and reported a few small issues.
Except for this, the PR looks great to me! To be honest, I think this is one of the most advanced and detailed PR I've received on this repository, congrats! 🎉 👏
Thank you very much for this PR and for adding a detailed migration guide + a nice example with sharp (this one should be added to the official list of example once this is merged)! 😍
7cb6deb to
8a63c1e
Compare
|
I published an alpha version with your branch: |
|
This was released as v4.0.0: https://github.com/ricardo-ch/react-easy-crop/releases/tag/v4.0.0 Thank you very much @trurl-master for the awesome work 👏 |
|
@all-contributors please add @trurl-master for code and examples |
|
I've put up a pull request to add @trurl-master! 🎉 |
Fixes #240
Motivation
croppedAreareturned byonCropCompletewhen used together with non-zero rotation is not very useful, the values are more like temporary variables necessary for subsequent calculation ofcroppedAreaPixelsand do not make much sense on their own. I wanted to change that and unify the output ofcroppedAreaandcroppedAreaPixelswhen used with rotation and withoutinitialCroppedAreaPixels. The problem with pixels is that the process that generates them also post-processes them (recalculates based on passedaspectand rounds to the nearest integer), which results in slowly drifting crop zone when saved -> restored multiple timesThis solution
croppedAreareturn values from 0 to 100 (unlessrestrictPositionis false). It behaves the same as before when rotation is 0˚, but when it's not 0˚ the percentages are calculated within the bounding box size of the rotated image. This approach greatly simplifies crop operations, forsharpfor example, it's extremely easy to just plug the values intorotate(), thenextract()to get the correct result. (Breaking change)croppedAreaPixelsis also changed, it also returns values within the bounding box of the rotated image with improved accuracy and rounded to the nearest integer (as before) (Breaking change)initialCroppedAreaPercentagesthat uses the exact inverse algorithm that generatescroppedArea. It minimizes the losses of save/restore operations. They're still present on some occasions as the JS floating-point operations accuracy is limited, but it allows to preserve the crop for much longer.initialCroppedAreaPixelsstill can be used, but it's a bit riskyA PoC of server-side crop using sharp - https://codesandbox.io/s/test-easy-crop-next-e51oi
Official example with client-side crop remade for this PR - https://codesandbox.io/s/react-easy-crop-demo-with-cropped-output-forked-z0cgp
Migration guide
The main impact this PR has is on the
croppedAreaPixelswhen used together with the rotation. As it now generates bounding box relative values, you will need to remake the part that generates the final image, taking that into account.Here's an example implementation (codesandbox):
First, calculate the bounding box size:
Second, create a canvas element with the size of the bounding box:
Then, rotate the canvas context around the center of the canvas:
Set context to point to the top-left corner of the rotated image:
Draw the image onto the rotated context:
What you have in the canvas at this point is a rotated image inside its bounding box. Now, you just need to extract the result using
croppedAreaPixelsand repaint it on a canvas with the size of the final image:croppedAreaIf you somehow managed to use
croppedAreawith rotation before - you're smarter than me. If not - now is the time. The approach is basically the same as withcroppedAreaPixels- you just need to convert percentages to pixels based on the image you're croppingHere's how you can use percentages server-side and crop using sharp (codesandbox):
Rotate the image:
Get rotated image bounding box size (basically you need to create a new image out of the rotated one, otherwise the metadata won't change):
Alternatively, you can calculate the bounding box size using the same method we used for the client-side crop
Convert percentages to pixels:
Extract the image: