It is a "blend mode (drawing mode)" function installed in image editing tools such as Photoshop, but it is also implemented in CSS3 with a property called mix-blend-mode
.
Since it is CSS3, it is naturally necessary to unify the appearance in each browser (other than IE), so the calculation formula for each blend mode is listed in the W3C specifications.
Compositing and Blending Compositing and Blending Japanese translation
In addition, it seems that Adobe employees are also involved in the formulation, and it seems that the same formula as the blend mode of Adobe products such as Photoshop is used.
As you read the W3C specifications, the blend modes are divided into two categories: "Separable blend" and "Non-separable blend". "Non-separable blend" is a blend that considers all color component combinations without treating each component individually.
"Separable blend" uses simple formulas such as screen
and ʻoverlay, so there is no problem. There are four problems:
hue,
saturation,
color, and
luminosity`, which are classified as "Non-separable blend".
For example, the hue
mode is a mode in which the hue (Hue) of the source image is applied while maintaining the brightness of the background image.
Let's combine the two images below in hue
mode.
The composition result is as follows.
It's not a simple story, "Because I'm transplanting hue, I convert it to HSV color space and transplant H component ...". While porting the hue, the brightness of the original image must be maintained, that is, when the composite result is monochromed, it must be as follows.
<iclass="fafa-arrow-right"aria-hidden="true">
The duck has completely disappeared.
There are two commonly used color spaces that deal with hue (Hue): the HSV color space and the HSL color space. The HSV color space is composed of Hue, Saturation, and Value.
The HSL color space is composed of three parts: hue, saturation, and lightness.
Wikipedia describes it as Luminance in the HSL color space, which is different from Luminance. Be aware that the word confusion here can be found on various pages.
The general formula for converting from RGB to Luminance is:
r * 0.298912 + g * 0.586611 + b * 0.114478
The conversion formula for HSL to L (Lightness) is as follows.
(MAX(r, g, b) - MIN(r, g, b)) / 2
Clearly, it's completely different. The translation of Lightness varies depending on the material such as "brightness" and "brightness", so it is important not to be confused.
A pseudo-code function called SetSat
is described in the W3C formula.
SetSat(C, s)
if(Cmax > Cmin)
Cmid = (((Cmid - Cmin) x s) / (Cmax - Cmin))
Cmax = s
else
Cmid = Cmax = 0
Cmin = 0
return C;
When I first saw this pseudocode, I didn't understand what it meant.
Cmin
is the minimum value of the RGB components, Cmax
is the maximum value, and Cmid
is the median value.
For example, if C = RGB (0,8, 0.6, 0.3), Cmin
is B element (0.3), Cmax
is R element (0.8), and Cmid
is G element (0.6). I will.
The calculation formula is as follows.
G = (((G - B) x s) / (R - B))
R = s
B = 0.0
It means that.
By the way, it doesn't describe what happens when there are two Cmin
and Cmax
like RGB (0.1, 0.1, 0.5) and RGB (0.5, 0.5, 0.1).
I don't know what the correct answer will be, but it seems that any value will do as long as the following conditions are met.
max(Cred, Cgreen, Cblue) - min(Cred, Cgreen, Cblue) == s
Now that we know the formula, we'll implement it in the Python image library pillow. Pillow is essentially a Python standard image library. It does not have advanced functions like OpenCV, but it can convert data to various libraries and features compact and high-speed image processing.
The blend mode implementation uses the ʻImageMath` module, as described in the PIL / Pillow cheat sheet (http://qiita.com/pashango2/items/145d858eff3c505c100a#_reference-35595a161656dd8d793c).
Let's implement hard-light
as an example.
from PIL import ImageMath
def _hard_light(a, b):
_cl = 2 * a * b / 255
_ch = 2.0 * (a + b - a * b / 255.0) - 255.0
return _cl * (b < 128) + _ch * (b >= 128)
bands = []
for cb, cs in zip(backdrop.split(), source.split()):
t = ImageMath.eval(
"func(float(a), float(b))",
func=_hard_light,
a=cb, b=cs
).convert("L")
bands += [t]
Image.merge("RGB", bands)
The ʻImageMath` module is useful because it allows you to calculate elements like numbers. For simple processing like "Separable blend", you can implement it like this.
The problem is "Non-separable blend", which is quite difficult due to the unexpectedly large amount of calculation and tricky processing. Regarding the implementation, I will publish the code later, so if you are interested, I will implement it by making full use of the private functions of the ʻImageMath` module. If you want to port in another language, I think you will use GLSL etc., I hope it will be helpful.
We have packaged these processes under the module name "Image4Layer". I often use ʻoverlay` composition in image processing systems, so I think there are quite a few things to use.
https://github.com/pashango2/Image4Layer
Installation is easy with pip, pillow (PIL) must be pre-installed to run.
$pip install image4layer
It's easy to use, it's an example of compositing in color-dodge mode.
from PIL import Image
from image4layer import Image4Layer
source = Image.open("ducky.png ")
backdrop = Image.open("backdrop.png ")
Image4Layer.color_dodge(backdrop, source)
It's easy, below is a list of supported blend modes.
Blend mode | image |
---|---|
Image4Layer.normal | |
Image4Layer.multiply | |
Image4Layer.screen | |
Image4Layer.overlay | |
Image4Layer.darken | |
Image4Layer.lighten | |
Image4Layer.color_dodge | |
Image4Layer.color_burn | |
Image4Layer.hard_light | |
Image4Layer.soft_light | |
Image4Layer.difference | |
Image4Layer.exclusion | |
Image4Layer.hue | |
Image4Layer.saturation | |
Image4Layer.color | |
Image4Layer.luminosity |
Although not in CSS3, I also implemented the blend mode that Photoshop has.
Blend mode | image |
---|---|
Image4Layer.vivid_light | |
Image4Layer.pin_light | |
Image4Layer.linear_dodge | |
Image4Layer.subtract |
The license is MIT, so you can use it for free for commercial or personal use.
Version 0.4 did not work with Python 2 and there was a bug in the operation between RGBA, which has been fixed in 0.43.
Compositing and Blending Japanese translation has the expected drawing and the actual browser display, but when I access it with Chrome It will be as follows.
that···? Isn't the color quite different? It seems that the colors of the display around here will differ considerably depending on each browser.
The color seems to be different depending on the version of Chrome, my environment is Ubuntu environment, and it seems that there is a bug in the composition of the alpha value set in backdrop.png.
By the way, the display result of Image4Lyaer is almost the same as the result of Chrome, I think that it has almost the same implementation. If there is any information, I will write it as needed.
Recommended Posts