Reputation: 197
We want to implement an HSL
color adjustment filter in an iOS 8.0+
app using CoreImage
.
After loading an image, the user selects a color (like red), and then is able to adjust the hue, saturation, and luminance of only that color within the image. This filter may be applied many times in a second while showing a preview, so performance is extremely important.
The filter should accept parameters of inputImage, target color, and then adjustments of hue, saturation, and luminance.
CIImage *inputImage
UIColor *targetColor
float hueAdjustment (identity 0)
float saturationAdjustment (identity 0)
float luminanceAdjustment (identity 0)
We already tried this method, and since this applies HSB
filters to whole image and not certain colors, we cannot use this
How to apply HSB color filters to UIImage
I have a feeling that this involves CIColorMatrix
, but I’m not sure how we would only make the matrix apply to a specific color range.
Upvotes: 2
Views: 3063
Reputation: 3633
Edit: Completed filter (in Swift) is available here!
OK, how about another approach then. You could apply individual treatments to each band with a Core Image color kernel which would include code along the lines of:
kernel vec4 rgbChannelCompositing(__sample pixel, vec3 hsl0, vec3 hsl1, [...])
{
float hue = rgb2hsv(pixel).x; // there are lots of rgb2hsv() on the internet :)
if (hue < color1)
{
return treatment(pixel, hsl0);
}
else if (hue >= color1 && hue < color2)
{
return treatment(pixel, hsl1);
}
[...]
The treatment()
function will do the magic based on the hue, saturation and luminance values passed into the kernel function. This could be as simple as tweaking the HSV values, converting them back to RGB with one of the many hsv2rgb()
implementations on the internet and returning that.
You may get some banding, in which case a smoothstep()
will help. I've done something similar to create a pseudo-color filter. In my case, I'm defining the bands based on luminosity rather than color, but the fundamental approach is the same (I think!).
Take a look at PseudoColor
in my CustomFilters.swift file.
Upvotes: 2
Reputation: 3633
If you're willing to have controls simply for red, green and blue, there is a simple solution. I wrote a small CIColorKernel
that accepts three images and combines them into one by individual channels:
kernel vec4 rgbChannelCompositing(__sample red, __sample green, __sample blue)
{
return vec4(red.r, green.g, blue.b, 1.0);
}
This means that you can apply three CI filter chains controlling hue (CIHueAdjust
), saturation and luminance (CIColorControls
) to your single image and combine them with my kernel.
It so happens, I've done something along those lines - you can see my Swift code here: https://github.com/FlexMonkey/Filterpedia/blob/master/Filterpedia/customFilters/RGBChannelCompositing.swift
Hope that helps!
Simon
Upvotes: 4