We have 2 colors, set in RGB, 1 byte per color.

If you take and fold each of the colors, then divide by 2, it turns out in my opinion is not quite right. Suppose FF0000 and 00FF00 give birth to 7F7F00 in this way, which looks much darker than both its "parents". If in this way we assume the average between FF0000 and FFFF00, then it will be FF7F00, which is apparently closer to FF0000 than to FFFF00. At a glance, the average between them is about FFAA00.

In each pixel of the monitor, we have 3 subpixels, the power supplied to which varies from 0 to 255 (some points) at a given color depth, if I understand correctly. I want to find out how to calculate mathematically a color that would be “average” between two given ones, namely, it would be similar to each of them in equal measure, while having an average brightness between them. Perhaps there are standard libraries in development environments that do something like this?

div { width: 6em; height: 6em; display: inline-block; font-family: monospace; text-indent: -12ch; overflow: hidden; } div:after { content: attr(style); } 
 <div style=background:#FF0000></div> <div style=background:#7F7F00></div> <div style=background:#00FF00></div> <br><br> <div style=background:#FF0000></div> <div style=background:#FF7F00></div> <div style=background:#FFFF00></div> 

  • 2
    What is “mathematically average color”? Depending on the definition, a different code will be correct. How to determine the brightness of the color and how much it looks like a different color? - VladD
  • one
    @VladD if I knew the algorithm, I would not ask such a question. The final color should be about the same look like parents, not one more than the other, but at the same time be as bright as they (or not bright, if they are type 005555). For example, if you look at shades of green, they are very similar to each other (or I have such a vision). Mathematically, it means that we need a certain solution algorithm, and not a table for comparison. - Vasily Pupkin
  • one
    Try to take averages not for RGB, but for HSL, or even HSLuv. - D-side
  • 2
    Well, you roll out a new, unfamiliar term (“mathematically average color”) without a definition, and ask how to calculate it correctly. Without a strict definition, we will have to guess what you mean. - VladD
  • one
    @VladD is the crux of the matter. To get accurate figures, I understand that you need to figure out exactly how the computer controls the power of the monitor subpixels. If it seems to you that FF7F00 is more like parents than FFAA00, then I have something with vision. Apparently, the question is not exactly. The number of total power supplied to the monitor's 3 subpixels should be an average of 2 parents, the proportions of each color should also be average. But judging by my perception, the scale of 0-255 is not linearly dependent on power, so a simple division by 2 gives a completely different answer. - Vasily Pupkin

2 answers 2

In RGB it is impossible to calculate the "average" color. First, the brightness of different colors is perceived by the eye in different ways - that is brightness is not "determined by the largest value of any of the 3 colors."

In RGB ( sRGB ) green is brighter than red, red is brighter than blue. FF0000 coincides in brightness with 009B00 (on the right), and not with vygvlazny 00FF00 (on the left):

enter image description here

Secondly, the brightness count is not strictly tied to 0, and a simple halving of the value gives too dark colors. For example, “semi-bright red” is rather A60000, rather than 7F0000, as one would expect.

To mix colors correctly, they should be first converted into a color space reflecting human perception, for example, Lab color space , and calculate the average already in this space. Here are the comparative results for pure RG and B (above — with Lab conversion and averaging, below — with RBG averaging).

enter image description here

enter image description here

enter image description here

It can be seen that averaging over RGB gives a too dark result, and averaging through Lab gives an average over brightness.

In C # it is implemented quite easily, ready-made forums are via links to the wiki above. If you do not want to manually enter the conversion - take the ready library :

 PM> Install-Package ColorMine 

 var color1 = new Rgb() { R = 255 }; var color1Lab = color1.To<Lab>(); var color2 = new Rgb() { G = 255 }; var color2Lab = color2.To<Lab>(); var averageLab = new Lab() { L = (color1Lab.L + color2Lab.L) / 2, A = (color1Lab.A + color2Lab.A) / 2, B = (color1Lab.B + color2Lab.B) / 2, }; var averageLabRgb = averageLab.ToRgb(); 
  • 2
    @ codename0082016 and you have something wrong with the ability to write constructive comments - PashaPash

There are two blending patterns: additive and subtractive color mixing. You can read here https://creativshik.com/pochemu-vret-monitor/

The adjective will be like this (it "works" with the light mixing of the rays, in some graphics programs):

 r = (r1 + r2 ) / 2; g = (b1 + b2 ) / 2; b = (b1 + b2 ) / 2; 

Subtractive

 r = // TODO: g = b = 

The second "mixing" of colors is similar to the usual mixing of "watercolor paints" on a white sheet. More such mixing can be included in Corel Draw.

Adjective - brings color closer to black. A subtractive - to white.

If the task is to determine the "nearest" color, then the sum of rgb with coefficients is used.

 Q = r * Kr + g* Kg + b*Kb; 

Where Q is the "weight" by which you can determine the similarity. This formula translates the image into black and white. For different transformations use different coefficients. Standard for b / w saw somewhere - I will find and write down.


The coefficients found here

Y = 0.299 * R + 0.587 * G + 0.114 * B (V.Porev "Computer Graphics", BHV, 2002. - page 41.)

Y = 0.2125R + 0.7154G + 0.0721V (Photoshop link )

When trying to insert coefficients - they are reduced in the formula, i.e. for Y (R = 255, G = 0, B = 0) = 76.5, Y (R = 0; G = 255; B = 0) = 150.45. The average color will be (128,128,0), but the average brightness will also be average - 113,48. If you want to "raise" the brightness to max (Y (color1), Y (color2)), then you can recalculate the color, taking into account the formula above.

If you have the task "not to lose brightness", then we set the task - to keep the maximum brightness.

  Y(Red=255) = 76,5 Y(Green=255) = 150,45, Y=(Red+Green) = 113,48; t = Ymax / Y = 150,45/113,48 = 1,325 Тогда (адитивное смешение): r` = (r1 + r2)*t/2 = (255 + 0)*1,325/2 = 170 g` = (g1 + g2)*t/2 = (0 + 255)*1,325/2 = 170 b` = (b1 + b2)*t/2 = (0 + 0)*1,325 / 2 = 0 Y(R=170,G=170,B=0) = 150,45 

For subtractive mixing, you can write a similar formula. You can also add a unit in the cycle - a similar value will be released (R = 169, G = 127, B = 42). Below is an example, first R (255.0.0), then the result is “darkened” R + G (128,128,0), then adjusted for brightness (170,170,0), then made an increment (169,127,42). Then green (0,255,0) Addition

And finally, put the checks that the component would not go beyond [0,255], if less than 0, then assign 0, if more than 255, then set 255.

  • four
    It seems to me that this issue should not use rgb. With her, it is unlikely that something plausible will work out. - Qwertiy
  • So it is, you are right about the models. But the fact is that I described above. Judging by the perception, this calculated color is not really average. This means that either the eyes lie, or the scale of 0-255 is not linearly dependent on the real power supplied to the subpixel. And Google doesn’t want to tell you in any way how exactly, for example, adding +1 to the number of color (0-255) will affect the actual power supply to the subpixel of the monitor. - Vasily Pupkin
  • these two models are used by half the world. If you want to make the color lighter - using the third formula, you can raise the three components to the desired level of lightness, which depends on the coefficients. If you want to build your model - try it. But most likely will return to this. - nick_n_a