fix: Round resized dimensions to whole pixels - #147
Merged
Merged
Conversation
ImageProcessor#resize truncated the size it was handed and left vips to
fit the image inside the truncated box. A size that didn't land on a
whole pixel lost a pixel on the other axis: Model#resize("100x100") on
a 320x200 image rewrote the stored file at 99x62 rather than 100x63,
and ProcessedImage recorded 100x63 on the variant while storing a 99x62
blob.
Fit in Ruby at full precision, round once, and have vips hit that size
exactly instead of fitting a second time against the truncated box.
The render path is unaffected. The controller resizes to the integer
size parsed from the URL, and old and new code render those
identically.
This was referenced Sep 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ImageProcessor#resizetruncated the size it was handed and left vips to fit the image inside the truncated box, so a size that didn't land on a whole pixel lost a pixel on the other axis:Model#resize("100x100")on a 320x200 image rewrote the stored file at 99x62 rather than 100x63, andProcessedImagerecorded 100x63 on the variant while storing a 99x62 blob. It now fits in Ruby at full precision, rounds once, and has vips hit that size exactly rather than fitting a second time against the truncated box.The render path is unaffected: the controller resizes to the integer size parsed from the URL, and old and new code render those identically across all 2725 sizes the helpers generate for a 320x200 image. That path does lose a pixel, for a separate reason — the helper floors the fitted size into the URL and the pipeline refits it against the source instead of honoring it — which is left for a follow-up.