javascriptmathcolorscolor-theory

Get the rgb of overlaying colors (elements)


Let's say I have the following setup

body {
    background: rgba(0,0,0,0.5);
}
#first {
    width: 200px;
    height: 100px;
    background: rgba(255,0,0,0.5);
}
#second {
    width: 50px;
    height: 50px;
    background: rgba(86, 185, 11, .5);
    position: absolute;
    top: 20px;
    left: 20px;
}

How can I get/calculate the color of the #second div?


I took a screenshot of the divs and checked their RGBs in Photoshop.

Body                 -> 128,128,128
First red div        -> 192,65,65
Second yellowish div -> 140,125,38

enter image description here

I found a way to calculate the first div's rgb by experimenting. Adding the two values together and then applying the alpha.

R: (128 + 255) * 0.5 = 191.5
G: (128 + 0)   * 0.5 = 64
B: (128 + 0)   * 0.5 = 64

Tried to use the same method on the second div, but it gets trickier now.

R: (((128 + 255) * 0.5) + 86)  * 0.5 = 138.5
G: (((128 + 0)   * 0.5) + 185) * 0.5 = 124.5
B: (((128 + 0)   * 0.5) + 11)  * 0.5 = 37.5

I can round the G and B to get the exact result, but R is off by 1.5. And if I increase the number of the color layers, I don't know what kind of results I'll get.

Is there a better way to calculate it?


Update : As Kaiido suggested, I tried using canvas. Created the same thing using rectangles: Fiddle. Used getImageData to extract the rgb of the second rectabgle. The returned value was [122, 105, 6, 223]. Not used to using 8-bit integers for the alpha value, so it's [122, 105, 6, 0.8754]. Even though I've extracted some rgb value, it's not a solid color and it's definitely not what I measured in Photoshop which is 140,125,38.

Also when I took a screenshot of the canvas and checked the second rectangle's color, it was 139, 124, 37, but the color of the #second div is 140,125,38. They are not exactly the same.

Anyway, I searched for a way to convert the returned value from the getImageData that is 122, 105, 6, 0.8754 to 140,125,38. I thought if I compensate for the missing opacity with the following example, I'd get the desired value

122 * (255/223) = 139.5 // 140
105 * (255/223) = 120   // 125
6   * (255/223) = 6.86  // 38

which I did for R, but the same method doesn't work for G, and B. I came to think that canvas won't really help unless there's a way to convert the transparent color to a solid color.


Solution

  • Using Kaiido's approach, I managed to get the end result of the overlaying colors using canvas.

    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    // default background
    context.beginPath();
    context.rect(0, 0, canvas.width, canvas.height);
    context.fillStyle = "white";
    context.fill();
    
    // body
    context.beginPath();
    context.rect(0, 0, canvas.width, canvas.height);
    context.fillStyle = "rgba(0,0,0,.5)";
    context.fill();
    
    // first div
    context.beginPath();
    context.rect(10, 10, 200, 100);
    context.fillStyle = "rgba(255,0,0,0.5)";
    context.fill();
    
    // second div
    context.beginPath();
    context.rect(20, 20, 50, 50);
    context.fillStyle = "rgba(86, 185, 11, .5)";
    context.fill();
    
    var imageData = context.getImageData(25, 25, 1, 1).data;
    
    console.log(imageData); // 139,124,37
    html, body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
    }
    canvas {
      display: block;
    }
    <canvas id="canvas"></canvas>

    Although this gives me what I want, I still would like to this mathematically.