I have a web app where users can use the filter contrast in order to modify an image : filter: contrast(1.1)
that I would like to reproduce in VIPS. (In Ruby)
Though I have not found any information on how to do that in Vips yet. I saw Vips implement CLAHE algorithm https://github.com/libvips/libvips/issues/1576 but it is overkill for me and may not return the same kind of contrast adjustmeent similar to the CSS filter.
Also I checked this thread of adjustments examples yet I can't find anything for contrast adjustment : https://github.com/libvips/libvips/issues/59 ...
Also I ended up on W3 explanation page where they cleanly explain what is done for contrast adjustment : https://www.w3.org/TR/filter-effects/#contrastEquivalent
<filter id="contrast">
<feComponentTransfer>
<feFuncR type="linear" slope="[amount]" intercept="-(0.5 * [amount]) 0.5"/>
<feFuncG type="linear" slope="[amount]" intercept="-(0.5 * [amount]) 0.5"/>
<feFuncB type="linear" slope="[amount]" intercept="-(0.5 * [amount]) 0.5"/>
</feComponentTransfer>
</filter>
Definitely awesome.
Now I know they use a linear fonction (that I know how to leverage in Vips) and they stay in RGB colorspace. I have understood that a slope is just a multiplication being done. Which is easy to do as I just need to pass an array as the first argument of the Vips Linear function. http://libvips.github.io/ruby-vips/Vips/Image.html#linear-instance_method
Though I have basically no clue of what Intercept is and if Vips Linear function offers similar tool.
Any idea?
EDIT EDIT
Ok seems like W3 has been doing something funny.
The solution to exactly match CSS filter contrast
with Vips is :
divider = 256
contrast = 1.5
intercept = 0.5-(contrast*0.5)
im = Vips::Image.new_from_file "pic.jpg", access: :sequential
im = ((im * contrast / divider) intercept)*divider
im.write_to_file "output.jpg"
CodePudding user response:
Yes, just multiply to change contrast. From the CSS docs, linear
just computes:
C' = C * slope intercept
So in ruby-vips you could write:
#!/usr/bin/ruby
require 'vips'
contrast = 1.1
image = Vips::Image.new_from_file ARGV[0], access: :sequential
image = image.colourspace("scrgb")
image = image * contrast - (0.5 * contrast - 0.5)
image = image.colourspace("srgb")
image.write_to_file ARGV[1]
scRGB is sRGB but with linear floats in the range 0 - 1 for black to white.
You could use linear
rather than the operator overloads, it'd be slightly quicker.
image = image.linear contrast, -0.5 * contrast - 0.5