Page 1 of 1

HSL offsets to 'some' pixels of an image

Posted: 2011-08-19T11:32:32-07:00
by jdespatis
Hello,

I'd like to add some HSL offsets to an image (add some lightness, add some hue to change the color, etc...)

I can do the trick with -modulate:
http://www.imagemagick.org/Usage/color_mods/#modulate

But I'd like to modulate only specific pixels, for example the pixels that are not white or black, and maybe also not modulate the pixels that are in the grayscale

Any idea how to do that ?

Re: HSL offsets to 'some' pixels of an image

Posted: 2011-08-19T11:38:59-07:00
by fmw42
Create a binary mask of the pixels that you want to change (white) and you want to not change (black). Some kind of thresholding or -fill xx -opaque yy ,etc.

then process the image with -modulate

then use the mask to composite the original and modulated image together.

see
http://www.imagemagick.org/Usage/color_basics/#replace
http://www.imagemagick.org/Usage/compose/

If you want to provide an image, we can try to show you the commands.

Re: HSL offsets to 'some' pixels of an image

Posted: 2011-08-19T12:33:51-07:00
by jdespatis
Here is a test image (indeed a sprite image):
Image

Test 1:
Let's add to the original image H: 75, S: 55, L: -25 to all pixels of the image
It should be something like: (thanks to a windows soft)
Image

Test 2:
Let's add now to the original image the same values H: 75, S: 55, L: -25 to all pixels of the image that are not black and not white (in fact we change all pixels but keep the blacks and whites)
It should be something like:
Image

Test 3:
Let's add now to the original image the same values H: 75, S: 55, L: -25 to all pixels of the image that are not in the grayscale (in fact we change all pixels but keep the grays)
It should be something like:
Image


Test 1 can be achieved with -modulate (inspired for the values to use for imagemagick from post: viewtopic.php?f=1&t=19044&p=74121&hilit=hsl#p74121)
(for IM) H = 75 * 200 / 360 + 100 = 142
(for IM) S = 100 + 55 = 155
(for IM) L = 100 - 25 = 75
=> the command could be: convert input.png -set option:modulate:colorspace hsl -modulate 75,155,142 output.png
which gives the resulting image:
Image

I don't understand well why this image is not exactly the same as the one from test 1, but nevermind, they have both the same problem, too darkish, so I prefer to leave the black and whites (test 2), or for some other images I prefer to keep the grays (test 3)

If you have some code for doing test 2 and test 3, go ahead ;)

Re: HSL offsets to 'some' pixels of an image

Posted: 2011-08-19T13:28:11-07:00
by fmw42
How did you achieve your results 2 and 3? If you know how to do it, why are you asking? Did you use some other tool? Was that other tool using HSL or HSB colorspace. That is important to get the right colors. What do the numbers H: 75, S: 55, L: -25 mean? That is in what range are they. Are they additive or multiplicative? It is important to know what your other tool was doing in order to figure out how to utilize IM and if modulate can even be used.

Looks to me like your other tool may be adding to H,S,L and not multiplying as -modulate does.

Please note that -modulate will not be able to change saturation on anything that is black/white/gray as it is 0 to start with. Thus a multiplier (expressed as a percent) will still be 0. And modulate won't change the hue of black/white/gray as it has no unique hue. All you can do is change the lightness of the gray/white/black pixels with -modulate.


So far the best I can tell is that your software is doing more of an add than a multiply as in -modulate. It is also treating shades of gray/black/white in some special way, which appears to be perhaps some complement of what I get from the following. Furthermore, your background is gray and so thresholding is not distinguishing the white/black/gray in the image from the hidden gray under the transparency. I also had to fudge your numbers a little. I will try to work on it some more as I have time.

Here is what I have done. Basically convert to HSL space and add some percent to each of the H,S,L channels. I had to extract the alpha channel and add it back again. In the second one, I tried to threshold the S channel to get another mask to composite with the original alpha channel to preserve the gray/white/black.


convert checkboxRadioButtonStates.png \
\( -clone 0 -colorspace HSL -separate \) \
\( -clone 1 -evaluate add 17% \) \
\( -clone 2 -evaluate add 45% \) \
\( -clone 3 -evaluate add -25% \) \
\( -clone 4 -clone 5 -clone 6 -set colorspace HSL -combine -colorspace RGB \) \
\( -clone 0 -alpha extract \) \
-delete 0-6 -alpha off -compose copy_opacity -composite \
checkboxRadioButtonStates3.png

Image

convert checkboxRadioButtonStates.png \
\( -clone 0 -colorspace HSL -separate \) \
\( -clone 1 -evaluate add 17% \) \
\( -clone 2 -evaluate add 45% \) \
\( -clone 3 -evaluate add -25% \) \
\( -clone 4 -clone 5 -clone 6 -set colorspace HSL -combine -colorspace RGB \) \
\( -clone 0 -alpha extract \) \
\( -clone 2 -threshold 0 \) \
\( -clone 8 -clone 9 -compose multiply -composite \) \
-delete 1-6,8,9 -alpha off -compose over -composite \
checkboxRadioButtonStates4.png

Image

Re: HSL offsets to 'some' pixels of an image

Posted: 2011-08-20T02:28:06-07:00
by jdespatis
Thanks for your answer.

This windows soft is a windows soft coded in c# with a gui (the cli is buggy for now)
But I need to run the equivalent on a linux on batch mode
(I want to avoid mono for running this soft)

As I'm going to change the images with php, I've had a look at imagick yesterday, and the fact is I can access the HSL values of each pixel
So, as a test, I've coded a little script that loop on each pixel, and add some HSL offsets.
As I get each pixel, I can perform a test:
- if pixel is white or black, don't add HSL offset (for test 2)
- if pixel is gray, don't add HSL offset (for test 3)

Here are my results:

Test 1, add H: 75 S: 55 L: -25 values (like -modulate):
Image (compared to Image, with the windows soft)

Test 2, add H: 75 S: 55 L: -25 values, but keep the blacks and whites:
Image (compared to Image, with the windows soft)

Test 3, add H: 75 S: 55 L: -25 values, but keep the grays:
Image (compared to Image, with the windows soft)

As you can see, a process per pixel gives nearly same result as this windows soft
I guess it's a slow method, but for now, that's the only solution I've found so far...

I'm looking deeper in that direction right now, until finding better

Re: HSL offsets to 'some' pixels of an image

Posted: 2011-08-20T10:00:15-07:00
by fmw42
Do you have the C# algorithm code? It would be interesting to see what they are actually doing to get the color shift, esp where they get orange and IM gets green.