Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Color Mixing With JavaScript
Adam Nathaniel Davis
Adam Nathaniel Davis

Posted on

     

Color Mixing With JavaScript

[NOTE: The live web app that encompasses this functionality can be found here:https://www.paintmap.studio. All of the underlying code for that site can be found here:https://github.com/bytebodger/color-map.]

In the previous articles in this series, I talked about many aspects of color theory - and real-worldpaints - as they apply to web development (i.e., RGB) colors. Soon I'm going to show you how to apply algorithmically-created palettes to a digital image. But first, we need to cover a basic task: Virtually "mixing" paints with code.

Honestly, there are a bunch of sites out there that can already do this for you. But I didn't see too many that actually talk abouthow you do it. So I'm going to illustrate that here.


Image description

RGB mixing

Obviously, the RGB color space is comprised of... numbers. Three numbers, to be exact, representing red, green, and blue. So if you wanted to mix two (or more) RGB colors, the mathematical way to do that is to simply average the reds, and the greens, and the blues. The resulting average will yield the new, mixed color.

I've already determined the RGB equivalents for each paint in my inventory. For example: Golden: Light Magenta is:

constgoldenLightMagenta={red:208,green:117,blue:127,}
Enter fullscreen modeExit fullscreen mode

Image description

And Golden: Cobalt Blue is:

constgoldenCobaltBlue={red:21,green:41,blue:134,}
Enter fullscreen modeExit fullscreen mode

Image description

So if we mix those two together, the resulting color would be:

constnewColor={red:Math.round((208+21)/2),green:Math.round((117+41)/2),blue:Math.round((127+134)/2),}
Enter fullscreen modeExit fullscreen mode

Which comes out to:

constnewColor={red:115,green:79,blue:131,}
Enter fullscreen modeExit fullscreen mode

Image description


Image description

CMYK mixing

CMYK also consists of... numbers. But it has four numbers - cyan, magenta, yellow, and key - instead of red, green, blue. The color mixing I've implemented on Paint Map Studio uses CMYK mixing. Why? Because CMYK is asubtractive color space, and using CMYK values tends to lead to mixing results that areslightly better, in my experience.

For example, when I mix Golden: Cobalt Blue with Golden: Light Magenta, it gives me the following result:

constnewColor={red:100,green:74,blue:137,}
Enter fullscreen modeExit fullscreen mode

Image description

And themixRgbColorsSubtractively() function looks like this:

constmixRgbColorsSubtractively=(rgbColors=[rgbModel])=>{letcmykColors=rgbColors.map(rgbColor=>convertRgbToCmyk(rgbColor));letcyan=0;letmagenta=0;letyellow=0;letkey=0;cmykColors.forEach(cmykColor=>{cyan+=cmykColor.cyan;magenta+=cmykColor.magenta;yellow+=cmykColor.yellow;key+=cmykColor.key;});constcmykColor={cyan:Math.round(cyan/cmykColors.length),magenta:Math.round(magenta/cmykColors.length),yellow:Math.round(yellow/cmykColors.length),key:Math.round(key/cmykColors.length),};returnconvertCmykToRgb(cmykColor);};
Enter fullscreen modeExit fullscreen mode

Since I'm building all of this in a web-based application, I'm always starting from an RGB color. That's why the function expects an array of RGB values. Inside the function, we convert the values to CMYK, calculate the average, and then convert that average back into RGB.

You can see this logic in action by going tohttps://www.paintmap.studio/mix. On that page, you'll be able to pick any colors from the palette of heavy body acrylic paints, mix them together in different proportions, and see the resulting color.

It may surprise you to see that the RGB model yields a color mix that's so visually similar to the CMYK model. Well... let's explain that.


Image description

Beware of color confusion!

In my experience, it's really easy to get your head wrapped up in knots when thinking about colormixing. I think this confusion comes about because of the way that we talk about color mixing and color models.

For example, I found this quote on a site that talks about RGB vs CMYK colors:

The color systems used by scientists and artists are entirely different. An artist will mix blue and yellow paint to get a shade of green; a scientist will mix green and red light to create yellow.


To be perfectly clear, this quote isn't "wrong". But it definitely has the potential to screw up our thinking because it's talking abouttwo different types of mixing. Specifically, there's a difference betweenmixing and...combining. Let me show you.

According to that quote, a scientist would mix green and red light to create yellow. But that's a bit misleading, because the term "mixing" implies that I have two RGB colors - one green, and one red - and we're mixing them up.

So using the basic calculation that we outlined above for RGB colors, that means that we would be mixing these two colors:

constgreen={red:0,green:255,blue:0,}constred={red:255,green:0,blue:0,}
Enter fullscreen modeExit fullscreen mode

What happens when we "mix" those up? We get this:

constmixedColor={red:(green.red+red.red)/2,green:(green.green+red.green)/2,blue:(green.blue+red.blue)/2,}
Enter fullscreen modeExit fullscreen mode

Which comes out to this (values rounded):

constmixedColor={red:128,green:128,blue:0,}
Enter fullscreen modeExit fullscreen mode

And that RGB value looks like this:

Image description

That's hardly what most people would call "yellow". Sure, it's kinda sorta... yellow-ish. But it's far from true yellow. (I think it would best be identified as a dirtychartreuse.)

Here's where the quote isn't entirelywrong, but it's definitely somewhat confusing. In the RGB color space, combining pure red and pure greenin a single color will indeed create yellow. In other words, this value:

constfullRedAndFullGreen={red:255,green:255,blue:0,}
Enter fullscreen modeExit fullscreen mode

Creates this color:

Image description

Nowthat is yellow! But it only happens when we combine red and green into a single color. It'snot what happens when youmix red and green together.

Here's another way to think about it. Imagine that the scientist mentioned above has a laser on his desk that emits wavelengths of pure red light. And he has another laser that emits wavelengths of pure green light. Using the RGB color space, we could represent his lasers as such:

constgreenLaser={red:null,green:255,blue:null,}constredLaser={red:255,green:null,blue:null,}
Enter fullscreen modeExit fullscreen mode

Notice that for the red laser, I didn't define thegreen andblue values as0. I defined them as...null. And on the green laser, I defined thered andblue values as...null. If you understand the difference between0 andnull (and if you're reading programming blogs, I sure-as-hellhope that you understand the difference), you'll realize that an RGB object withnull values is not the same as one with0 values.

Now if that scientist were tocombine the light coming from the red and green lasers, the resulting color would indeed be yellow.

But if that same scientist was creating a web site to present his findings, and he wanted to "mix" the RGB color red with the RGB color green, the resulting color would be chartreuse.Not yellow!

The exact same thing happens if we use a color space that's subtractive (like CMYK) rather than one that's additive (like RGB). The CMYK Venn diagram tells us that combining pure yellow with pure magenta should give us... red. But let's look at what happens if we don'tcombine them, but instead, wemix them.

Our colors would look like this:

constyellow={cyan:0,magenta:0,yellow:100,key:0,}constmagenta={cyan:0,magenta:100,yellow:0,key:0,}
Enter fullscreen modeExit fullscreen mode

Mixing them is accomplished like this:

constnewColor={cyan:(yellow.cyan+magenta.cyan)/2,magenta:(yellow.magenta+magenta.magenta)/2,yellow:(yellow.yellow+magenta.yellow)/2,key:(yellow.key+magenta.key)/2,}
Enter fullscreen modeExit fullscreen mode

Which would come out like this:

constnewColor={cyan:0,magenta:50,yellow:50,key:0,}
Enter fullscreen modeExit fullscreen mode

And the here's the resulting color:

Image description

That's, umm... red-ish. But it's far frompure red. It's much more like a "salmon" color. (In fact, it's incredibly similar to the Golden: Light Magenta color illustrated near the top of this article.)

This is why, IMHO, colormixing can sometimes lead people down rabbit holes. They spin up a color-mixing algorithm that uses CMYK, for example, then they throw pure yellow and pure magenta into the mix, and when the resulting color isn't purered, they think that there's some kinda flaw in their methodology. (I've read many threads that complain about this exact same "problem" on places like Stack Overflow.)

But if you have a pure yellow-colored paint, and you mix it with a pure-magenta colored paint, I promise you that you willnot end up with pure red. You'll end up with... salmon.


Image description

In the next installment...

Although this topic interestsme from the perspective of further understanding color theory, I didn't take you down this path purely for academic reasons. Being able to accurately mix paints,algorithmically, will have significant benefits in our quest to create a palette of (near) perfectly-matched paint colors against a digital image. In the next article, I'll show how we can leverage this to greatly increase the accuracy of our transformed images.

That being said, even if you're not interested in trying to match a digital image to a given palette of paints, it can be extremely useful to be able to "mix" paintsvirtually. I'm sure that skilled artists already have a good feel for the colors that result when they mix any two (or more) paints from their inventory. But for the rest of us, it's nice to be able to see the results without having to create an endless stream of paint swatches.

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
fruntend profile image
fruntend
Highly qualified front-end industry research organization
  • Education
    university
  • Work
    CEO
  • Joined

Сongratulations 🥳! Your article hit the top posts for the week -dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍

CollapseExpand
 
tdhofstetter profile image
TDHofstetter
  • Joined

But that's all projected colors. What of reflected colors, of which pure red, pure blue, and pure yellow are the three primaries?

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

React acolyte, jack-of-all-(programming)trades, full-stack developer
  • Location
    New Orleans, LA
  • Work
    Frontend Software Engineer
  • Joined

More fromAdam Nathaniel Davis

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp