-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Optimise ImageOps.fit by combining resize and crop #3409
Merged
Merged
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,14 @@ | ||||||
5.4.0 (unreleased) | ||||||
----- | ||||||
|
||||||
|
||||||
Other Changes | ||||||
============= | ||||||
|
||||||
ImageOps.fit | ||||||
^^^^^^^^^^^^ | ||||||
|
||||||
Now uses the one resize operation with ``box`` argument internally | ||||||
instead of the crop and scale operations sequence. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
This improves the performance and accuracy of cropping since | ||||||
``box`` parameter accepts float values. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ Release Notes | |
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
5.4.0 | ||
5.3.0 | ||
5.2.0 | ||
5.1.0 | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -380,9 +380,10 @@ def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)): | |
(width, height) tuple. | ||
:param method: What resampling method to use. Default is | ||
:py:attr:`PIL.Image.NEAREST`. | ||
:param bleed: Remove a border around the outside of the image (from all | ||
:param bleed: Remove a border around the outside of the image from all | ||
four edges. The value is a decimal percentage (use 0.01 for | ||
one percent). The default value is 0 (no border). | ||
Cannot be greater than or equal to 0.5. | ||
:param centering: Control the cropping position. Use (0.5, 0.5) for | ||
center cropping (e.g. if cropping the width, take 50% off | ||
of the left side, and therefore 50% off the right side). | ||
|
@@ -400,66 +401,50 @@ def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)): | |
# [email protected] | ||
# http://www.cazabon.com | ||
|
||
# ensure inputs are valid | ||
if not isinstance(centering, list): | ||
centering = [centering[0], centering[1]] | ||
# ensure centering is mutable | ||
centering = list(centering) | ||
|
||
if centering[0] > 1.0 or centering[0] < 0.0: | ||
centering[0] = 0.50 | ||
if centering[1] > 1.0 or centering[1] < 0.0: | ||
centering[1] = 0.50 | ||
if not 0.0 <= centering[0] <= 1.0: | ||
centering[0] = 0.5 | ||
if not 0.0 <= centering[1] <= 1.0: | ||
centering[1] = 0.5 | ||
|
||
if bleed > 0.49999 or bleed < 0.0: | ||
if not 0.0 <= bleed < 0.5: | ||
bleed = 0.0 | ||
|
||
# calculate the area to use for resizing and cropping, subtracting | ||
# the 'bleed' around the edges | ||
|
||
# number of pixels to trim off on Top and Bottom, Left and Right | ||
bleedPixels = ( | ||
int((float(bleed) * float(image.size[0])) + 0.5), | ||
int((float(bleed) * float(image.size[1])) + 0.5) | ||
) | ||
|
||
liveArea = (0, 0, image.size[0], image.size[1]) | ||
if bleed > 0.0: | ||
liveArea = ( | ||
bleedPixels[0], bleedPixels[1], image.size[0] - bleedPixels[0] - 1, | ||
image.size[1] - bleedPixels[1] - 1 | ||
) | ||
bleed_pixels = (bleed * image.size[0], bleed * image.size[1]) | ||
|
||
liveSize = (liveArea[2] - liveArea[0], liveArea[3] - liveArea[1]) | ||
live_size = (image.size[0] - bleed_pixels[0] * 2, | ||
image.size[1] - bleed_pixels[1] * 2) | ||
|
||
# calculate the aspect ratio of the liveArea | ||
liveAreaAspectRatio = float(liveSize[0])/float(liveSize[1]) | ||
# calculate the aspect ratio of the live_size | ||
live_size_ratio = float(live_size[0]) / live_size[1] | ||
|
||
# calculate the aspect ratio of the output image | ||
aspectRatio = float(size[0]) / float(size[1]) | ||
output_ratio = float(size[0]) / size[1] | ||
|
||
# figure out if the sides or top/bottom will be cropped off | ||
if liveAreaAspectRatio >= aspectRatio: | ||
# liveArea is wider than what's needed, crop the sides | ||
cropWidth = int((aspectRatio * float(liveSize[1])) + 0.5) | ||
cropHeight = liveSize[1] | ||
if live_size_ratio >= output_ratio: | ||
# live_size is wider than what's needed, crop the sides | ||
crop_width = output_ratio * live_size[1] | ||
crop_height = live_size[1] | ||
else: | ||
# liveArea is taller than what's needed, crop the top and bottom | ||
cropWidth = liveSize[0] | ||
cropHeight = int((float(liveSize[0])/aspectRatio) + 0.5) | ||
# live_size is taller than what's needed, crop the top and bottom | ||
crop_width = live_size[0] | ||
crop_height = live_size[0] / output_ratio | ||
|
||
# make the crop | ||
leftSide = int(liveArea[0] + (float(liveSize[0]-cropWidth) * centering[0])) | ||
if leftSide < 0: | ||
leftSide = 0 | ||
topSide = int(liveArea[1] + (float(liveSize[1]-cropHeight) * centering[1])) | ||
if topSide < 0: | ||
topSide = 0 | ||
|
||
out = image.crop( | ||
(leftSide, topSide, leftSide + cropWidth, topSide + cropHeight) | ||
) | ||
crop_left = bleed_pixels[0] + (live_size[0]-crop_width) * centering[0] | ||
crop_top = bleed_pixels[1] + (live_size[1]-crop_height) * centering[1] | ||
|
||
crop = (crop_left, crop_top, crop_left + crop_width, crop_top + crop_height) | ||
|
||
# resize the image and return it | ||
return out.resize(size, method) | ||
return image.resize(size, method, box=crop) | ||
|
||
|
||
def flip(image): | ||
|
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.
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.