0
votes

Subject. I want to achieve colorization of one pixel by other pixel like "Color" blending mode in Photoshop (with 100% opacity). What I do now:

  1. get hue of mask pixel;
  2. convert source pixel from RGB to HSL;
  3. replace hue and convert back to RGB;

If you are interested in the formula - check this: Please explain this color blending mode formula so I can replicate it in PHP/ImageMagick

But for this task converting back'n'forth from/to HSL/RGB seems too excessive.

So I am looking for a faster approach. I guess there should be way to calculate RGB-multiplying coefficients somehow and then for source pixel just simply do something like this:

 src_R *= mult_R;
 src_G *= mult_G;
 src_B *= mult_B;

UPD: Actually I don't need it to be exactly like in Photoshop. I mentioned PS blending mode just for example. I use it in my custom convolving routine, so I want it to be fast, but precision is not important, so it even if it could be approximated by a few percents. It's just that I want to find an approach to change pixel's tone without these complex HSL/RGB conversions...


UPD2: After some tests I've realized that my approach (replacing hue) is actually pretty far from what I wanted. Also after some digging I've found that "Color" blend-mode in PS replaces not only Hue but also Saturation. And surprisingly that makes algorithm not more complex, but on a contrary a bit simpler (faster):

  1. we need to get not only Hue, but also Saturation of mask-pixel
  2. but now we don't need to convert src-pixel from RGB to HSL, cuz all we need is luminocity which calculated much faster than full RGB->HSL routine...
  3. with src-Luminocity, mask-Hue and Sat. we convert it to RGB...

It is still pretty complex though, and I still believe it could be simplified.

1
If accuracy is not that important, maybe you could make a lookup table (LUT) with just 64 pre-calculated entries and round your values to the nearest 4 before looking up.Mark Setchell
@MarkSetchell it's nice idea, didn't thought bout cache-tables. But i don't get it bout 64 entries... I don't rly sure what i should put in the table lol)) if i knew how to get multiplying coefficients - the table will not be needed, but with this hue approach i don't see how can i use the table at allMarkus_13
It would help, if you were to post example input and output images showing what exactly you are trying to achieve.fmw42

1 Answers

1
votes

You can do Photoshop-like blending in ImageMagick using -compose colorize or -compose luminize. What is done is to transfer either the intensity (luminance) channel between images (luminize) or the combination of Hue and Saturation channels (colorize) between images, via RGB->HCL->RGB colorspace.

Note that it is usually easier to add color than to remove it. But I try to do the latter here.

Input Images:

enter image description here

enter image description here

You can make the first image look more like the second image using either -compose luminize or -compose colorize. It just depends upon the order of the two input images.

convert zelda1.jpg zelda1_tint.jpg  -compose colorize  -composite result.jpg

convert zelda1_tint.jpg zelda1.jpg -compose luminize -composite result.jpg


enter image description here

If you reverse the order, then you get:

convert zelda1_tint.jpg zelda1.jpg -compose colorize -composite result2.jpg

convert zelda1.jpg zelda1_tint.jpg -compose luminize -composite result1.jpg


enter image description here

I am not sure which way you want to go.

If you take the latter and add some brightness and contrast, then you can get closer to the first image.

convert zelda1.jpg zelda1_tint.jpg -compose luminize -composite -brightness-contrast 15,-5 result1.jpg


enter image description here

Another approach is to match the brightness (mean) and contrast (standard deviation) between the two images. I use one of my Unix bash shell scripts to do that.

The matching uses the mean and standard deviations from each image according to the equation: (I2-Mean2)/Std2 = (I1-Mean1)/Std1. This equation represents a normalized intensity such that it has zero mean and approximately the same range of values due to the division by the standard deviations. We solve this equation to form a linear transformation between I1 and I2 according to I2=A*I1+B, where A=(Std2/Std1) is the slope or gain and B=(Mean2-A*Mean1) is the intercept of bias. The matching can be done in different colorspaces. Here I use LAB, but it can also be done in RGB or YCbCr.

See also https://www.pyimagesearch.com/2014/06/30/super-fast-color-transfer-images/ and http://im.snibgo.com/gainbias.htm

matchimage -c lab zelda1_tint.jpg zelda1.jpg result.jpg


enter image description here

Finally another way is to use histogram matching between two images. I use one of my scripts to do that. It also can do that in various colorspace. Here I use RGB. See https://en.wikipedia.org/wiki/Histogram_matching

histmatch -c rgb zelda1.jpg zelda1_tint.jpg result3.jpg


enter image description here

As you can see, this seems to be the better approach in this case.

For anyone interested, my scripts can be found at http://www.fmwconcepts.com/imagemagick/index.html