Skip to content
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

Question: Cropping to a relative portion of the image (in percents) #384

Closed
Sewdn opened this issue Aug 17, 2023 · 10 comments
Closed

Question: Cropping to a relative portion of the image (in percents) #384

Sewdn opened this issue Aug 17, 2023 · 10 comments
Labels
completed Feature or request has been completed documentation Improvements or additions to documentation enhancement New feature or request

Comments

@Sewdn
Copy link

Sewdn commented Aug 17, 2023

Say you want to crop an image to its upper left quadrant. The image should not be resized, only the top-left half of the image (1/4) should be retained. What is the best way to do this?

I understand it is an easy task if the image's dimensions are known beforehand. But what if you would like to skip the extra processing to assess the image's dimensions before cropping (and leave it up to wsrv)?

Is it possible to crop an image to a relative portion of the image, based on a percentage of the original size? Something like cx=0&cy=0&cw=0.5&ch=0.5? In the documentation it looks like you can only give absolute cropping values (in pixels) and would need to know the image dimensions beforehand.

Alignment does support percentage values (or top-left portions), but this is only used when resizing the image and using fit or cover and thus would always resize the image. If you would like to retain the image's ratio, this would always result in a resize without any cropping.

Thanks for your help or suggestions.

@andrieslouw
Copy link
Member

Good question, it would be like https://wsrv.nl/docs/crop.html#rectangle-crop but with percentages indeed.
@kleisauke: Any ideas on this? Does libvips provide any easy way to cut an image in equal sizes? I guess it would be handy to split up large images.

@Sewdn
Copy link
Author

Sewdn commented Aug 18, 2023

Thanks for your response!

It does not necessarily mean to have equal parts, or that libvips needs to cut all all the parts in one go.

The idea is just to request one part at a time, but instead of providing the absolute coordinates of the desired part, providing the relative part in percentages.

When cw equals ch an image of the same ratio of the original image is requested (and indeed this would end up in all equal sizes, if they all would be request):

  • cx=0&cy=0&cw=0.5&ch=0.5 for the upper left quadrant
  • cx=0.5&cy=0.5&cw=0.5&ch=0.5 for the bottom right quadrant
  • cx=0.75&cy=0.25&cw=0.25&ch=0.25 for the image with coordinate (3,1) in a 4x4 grid

But there are also use cases for none equal divisions / layouts for an image:

  • cx=0.25&cy=0.25&cw=0.5&ch=0.5 for the center image spanning 4 coordinates (1,1),(1,2),(2,1),(2,2) in a 4x4 grid
  • cx=0.25&cy=0&cw=0.5&ch=0.75 for an image spanning 6 coordinates (1,0),(2,0),(1,1),(2,1),(1,2),(2,2) in a 4x4 grid

It doesnt seem to me this feature would have a big impact, because the existing cx, cy, cw, ch parameters can be reused (because it would never make sense to request images with smaller dimensions then 1px) and the absolute dimensions of the provided image are known for the image server, so the relative dimensions can easily be converted to absolute dimensions.

If you point me to the right spot in the source, I'm willing to provide you with a PR and we can discuss this further in this PR.

Kind regards,
Pieter

@Sewdn
Copy link
Author

Sewdn commented Aug 18, 2023

The only possible conflict with the current API spec would arise for cx,cy,cw,ch = 1.
This would break the possibility of requesting crops of 1px dimensions, but I don't think this is a real use case

  • cw=0.5&ch=1 would result in the left half crop
  • cw=1&ch=1 would result in the original (non-cropped) image, whereas it current would return the upper left pixel

@Sewdn
Copy link
Author

Sewdn commented Aug 29, 2023

@kleisauke do you see value in adding this feature request?

@kleisauke kleisauke added enhancement New feature or request planned Feature or request is planned labels Aug 31, 2023
@kleisauke
Copy link
Member

kleisauke commented Aug 31, 2023

Sorry for the delay. I think this would be an interesting feature to add, but using a floating point API (i.e. values between 0.0 and 1.0, inclusive) would probably break backward compatibility when using c{x,y,w,h} == 1, as you said.

Perhaps we should use the percent sign (%) to indicate relative crops? Using the above example, that would result in:

  • cx=0&cy=0&cw=50%&ch=50 for the upper left quadrant;
  • cx=50%&cy=50%&cw=50%&ch=50% for the bottom right quadrant;
  • cx=75%&cy=25%&cw=25%&ch=25% for the image with coordinate (3,1) in a 4x4 grid.

(And of course, we need to ensure that percentages with decimal places are also supported, such as 50.5%).

I think this is relatively easy to add code-wise and could possibly be extended to the &w= and &h= parameters as well.

Let's mark this as an enhancement, I'll try to implement this sometime this week.

@Sewdn
Copy link
Author

Sewdn commented Aug 31, 2023

Alright, great!

Another possibility would be to use fraction notation. This would result in a higher precision then using floating points percentages (eg. 1/3 instead of 33.333%). This would also be closer to the actual use cases, where you are looking to divide the image in fractions.

100% would need to be expressed as ‘1/1’ to distinguish from an absolute dimension of 1px

The same examples would be like:

  • cx=0&cy=0&cw=1/2&ch=1/2 for the upper left quadrant;
  • ‘cx=1/2&cy=1/2&cw=1/2&ch=1/2’ for the bottom right quadrant;
  • ‘cx=3/4&cy=1/4&cw=1/4&ch=1/4’ for the image with coordinate (3,1) in a 4x4 grid.

@kleisauke kleisauke added started This issue is being worked on documentation Improvements or additions to documentation and removed planned Feature or request is planned labels Sep 1, 2023
@kleisauke
Copy link
Member

Fraction notation is slightly more difficult to implement because the parser must guard against division by zero and NaN values.

Commit e5489aa allows percentage-based values (denoted by a value ending with %) for the &c[x,y,w,h]= and &[w,h]= parameters. This has just been rolled out to production, thanks for the suggestion!

Documentation will be updated later to reflect this.

@Sewdn
Copy link
Author

Sewdn commented Sep 26, 2023

Hi @kleisauke

I have been using the relative cropping with success. Thanks a lot.
I am now using wsrv cropping urls with external services for other kind of image processing (after the image was cropped), and it seems like these services are url_encoding the % sign, because it is a value of one of the query parameters and it seems like weserv is not url_decoding the parameter values.

As i understand correctly from #334 weserv is url_decoding the url parameter to allow for other query parameters inside this url of the raw image.

My question to you: should weserv now also url_decode the c[w,h,x,y] parameters, since it now can contain special chars like % that are possible being url_encoded? Or is this up to the client, to make sure the parameters are not being url_encoded? What is your opinion?

@kleisauke
Copy link
Member

@Sewdn Looks like a small oversight, fixed with commit fd7a184.

@kleisauke kleisauke added completed Feature or request has been completed and removed started This issue is being worked on labels Mar 23, 2024
@kleisauke
Copy link
Member

Documentation has been updated.
https://wsrv.nl/docs/crop.html#rectangle-crop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completed Feature or request has been completed documentation Improvements or additions to documentation enhancement New feature or request
Development

No branches or pull requests

3 participants