-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add support for trimming (#491) #492
Conversation
|
||
// find the value of the pixel at (0, 0) ... we will search for all pixels | ||
// significantly different from this | ||
std::vector<double> background = image(0, 0); |
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.
Maybe we should let the users define the the point from where the trimming color is picked. Don't know how we should handle this (by a color or a position). For now it's always the top-left color.
I guess you'd need to scan to find the crop area, then close and reopen to crop and shrink. This would halve speed for things like PNG. |
Wow, that was fast, thanks Kleis! I don't think this needs to be overly-configurable for now, so let's have it (attempt to) trim all edges and always start with the top-left pixel. A test with a 16-bit input image is probably a must given lossless PNG will likely be the format of choice here. Making the |
VImage profileBottomV; | ||
VImage profileBottomH = rows.flipver().profile(&profileBottomV); | ||
|
||
int left = (int) profileLeftV.min(); |
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.
Please can these use static_cast<int>(floor( ... ))
.
I suppose the threshold could be a percentage. That would avoid having to change it for 8 and 16-bit images. |
@@ -406,7 +406,9 @@ namespace sharp { | |||
|
|||
// we need to smooth the image, subtract the background from every pixel, take | |||
// the absolute value of the difference, then threshold | |||
VImage mask = (image.median(3) - background).abs() > threshold; | |||
// TODO: Not sure if this calculation supports tolerance. Or should we do this?: | |||
// VImage mask = (image.median(3) - background).abs() > (MaximumImageAlpha(image.interpretation()) / 100 * tolerance); |
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 think I'd have this as max * tolerance / 100
. I guess this should be uncommented too?
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.
Thanks! Committed by mistake.
it('16-bit PNG with alpha channel', function(done) { | ||
sharp(fixtures.inputPngWithTransparency16bit) | ||
.resize(32, 32) | ||
.trim() |
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.
If I change this to trim(100)
then it will fail:
Uncaught Error: extract_area: parameter width not set
extract_area: parameter height not set
Debug:
(sharp:6296): GLib-GObject-WARNING **: value "-32" of type 'gint' is invalid or out of range for property 'width' of type 'gint'
(sharp:6296): GLib-GObject-WARNING **: value "-32" of type 'gint' is invalid or out of range for property 'height' of type 'gint'
[Error: extract_area: parameter width not set
extract_area: parameter height not set
]
It looks like only values from 1-99 are permitted.
Squashed, rebased, added logic to |
int bottom = rows.height() - static_cast<int>(floor(profileBottomH.min())); | ||
|
||
// and now crop the original image | ||
return image.extract_area(left, top, right - left, bottom - top); |
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 guess even with a 99% tolerance we could see rounding errors that lead to a 100%-like failure. How about a non-zero check for the width and height passed to extract_area
?
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.
Should we throw a VError
if width or height is less than or equal to 0? Or should we return the 'untouched' input image?
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.
Good question. Not failing here could produce unexpected results so I think throwing a VError
is the right thing to do.
I "fixed" the Appveyor CI builds via 8dd554b so after a rebase against master this PR should start passing again :) |
All builds are passing, thanks! |
Dank je! |
Usage:
trim()
or defining athresholdpercentaged tolerance between0-2550-100:trim(20)
2 test cases included (a test with a 16-bit PNG and a normal PNG, both with an alpha channel). Trimming is always performed before any resize operation.
I was working on an optional argument defining the border(s) that should be trimmed away. By default the trimming is performed on all borders. Let me know if you want such additional argument.