
RGB Curves, Color Balance, Selective Color, and HSL adjustments are powerful for color processing in Photoshop. A much less-used option is the Channel Mixer in color mode. This is extremely unfortunate as, to my mind, it is the single most powerful adjustment layer for color correction, enhancement, and photorealistic color grading.
The channel mixer is set up with 3 (R,G, and B) input channels, and 3 output channels (R’, G’, B’). I’ll use the convention through this article that R/G/B refer to the color channels we start with (our base image before any change in the sliders) and R’/G’/B’ refer to the final result after changing sliders. Below is the Red Output Channel, and the three sliders are the Red, Green, and Blue Input Channels (for the Red Output Channel).

Input channels define where an effect happens (R, G, or B regions of an image), and output channels define what happens there (adding or removing R, G, or B). So if I’m working on the Red output channel, I’m determining where Red is added (positive moves in any of the sliders), or where Red is taken away (negative moves in any of the channels). If I don’t change anything (100/0/0 as above) then all my Red is going to where things are already Red, so nothing changes.
The channel mixer is a 3 x 3 matrix color transform, utilizing our starting color information (input channels) to influence where we shift colors into our output image.
In matrix terminology rr, gg, and bb are the matrix “diagonals”, and the other terms are off-diagonals. In a new CM layer, the diagonals are by default set to 100 (Photoshop uses percentages so 100 is equivalent to 1 in our matrix equations), and the off-diagonals channels are set to 0. For clarity, diagonals are the Photoshop CM sliders in which the input and output channels are the same, and off-diagonals are where the input and output channels are different (also called cross-channels).
You’ll see from the equations that if rr, gg, and bb are all 1 (100 in Photoshop’s percentage system), and all other terms are 0, then R’=R, G’=G, and B’=B. In other words, we have no change to our colors.
rg in my notation means the red output channel, green slider/input, and so forth. That notation order is on purpose, so when I write it, I’m thinking how much red am I putting into the green regions. To relate to our Photoshop CM user dialogue the “r” in rg is the red output channel dialogue window we’re working in, and the “g” in rg is the green slider of that window.
Let’s go through some basic examples to improve our intuition. I found that, when I was still stuck at the “play-with-sliders” stage of CM (which is quite powerful in its own right), it was easier to think about each output channel as “where am I adding – or subtracting – this color”. For example, if I’m in the green output channel, and I move the red input channel to 10 (gr=10), I’m telling CM to put more green into the red-enriched areas of our base image (the higher the R value of our input pixel, the more green will be added to the current G value of that same pixel).

Let’s try that on a single pixel. Suppose it’s a 20% saturated red, and our input RGB pixel is 146/118/118. Now I move the gr slider to 10%, or 0.10 in decimal terms. Our output pixel then becomes
R’=1.0*R + 0*G + 0*B = 146
G’=0.10*R + 1.0*G + 0*B = 0.1*146+118+0 =132.6
B’=0*R + 0*G + 1.0*B = 118
All we’ve done is change the green pixel value (Because we only changed the Green output channel), but how much we changed it is proportional to the value of the input R pixel value. Our new pixel now has the RGB values of 146/132.6/118. If I plug those RGB and RGB values into an RGB to HSB converter my starting hue is 0 and my final hue is around 31 degrees, so we’ve changed the color of that pixel from red to orange by increasing the green value.
If instead we decrease the gr slider to -10, we’re decreasing green in the red areas. So our starting pixel then becomes
R’=146
G’=-0.1*146+118
B’=118
The final RGB values are now 146/103.4/118, which has a hue of ~340, closer to magenta. This makes intuitive sense if I remove green from a reddish pixel.
So visually, putting more green in red areas will shift the reds towards yellow, a positive change in hue. Alternatively, if I move the red input slider of the green output channel to -10, I’m telling CM to put less green into red areas of our base image, resulting in a magenta shift of the reds.
Let’s look at some CM perturbations in my Desmos hue strip. First let’s change gr to 20. That means we’re increasing the G value of a given pixel in proportion to that same pixel’s R value. So you’ll see if I change gr to 20, it’s my green curve that’s moving to higher values, but it’s moving the most in areas of the hue strip where the red curve is the strongest. It’s a little easier to visualize if I plot the change in green, or G’-G (new green minus the original green). That’s the dashed green line in the plot, and hopefully it’s clear that that dashed line has exactly the same shape as the red curve. In fact, the G’-G curve is just a 20% scaling of the R (input) curve (because my gr value was 20).

Likewise, if I only change gg (green output/green input) to 120, I get the following new green curve, and the change in green (G’-G) now mimics the shape of the green curve. I’ve added green where things were already green.

Finally, if I only change gb to +20, my change in green mimics the shape of the blue curve.

Saturation with Channel Mixer
What if I just want to increase the saturation (or chroma) of the red-biased areas of our base image? That means increasing the purity – how much red relative to blue and green – of the red channel, and I can do that in two ways. Most simply, and most intuitively, I can just increase the R input value of the R’ output channel (rr 100–>110 for example). That will indeed make my reds redder. Alternatively, I can reduce the “contamination” of the red channel by greens and blues. That means moving the red input channel – where red lives in our base image – into negative values for both the G and B output channels.
Note, however, from our equations above, that when we set these values, we are doing multiplicative scaling. So 110 for the rr value means R’=1.1*R, which will actually increase the brightness of our image. Incidentally, this same effect can be closely approximated by using a curves layer and moving the white point of the red channel inward to around 232 (232 * 1.1 ~ 255). On the other hand, our alternative approach of reducing cross-channel contamination (which curves simply cannot do!) will increase saturation of the reds while not affecting calculated “brightness” of the red areas: if the area is red, that means its highest RGB value is still R, and calculated brightness (eg the B in HSB) is simply the value of the highest R, G, or B for any given pixel. Although B in HSB is unchanged, these adjustments will actually impact perceived luminosity.
Preserving Neutrality
Before we go any further, there is a foundational principle in CM transforms that there is something important about keeping the values of any single output channel summing to 100. While many CM tutorials exhort us to satisfy this constraint in order to preserve overall image brightness, I believe that point is slightly misplaced (and in fact, generally incorrect if we’re talking about luminosity, or perceived brightness). The far more important aspect of this constraint (which we will happily break later when we get to color grading) is that it preserves neutrality. What is preserving neutrality? It means not adding color where it didn’t exist. Put another way, it means don’t make gray stuff (anywhere where R=G=B) colorful.
So what if I go back to my idea to increase saturation of the reds in my image, while attempting to preserve neutrality. If I set rr to 110, and also set rg and rb to -5, I will preserve neutrality: 110+(-5)+(-5)=100. And that does indeed give me increased saturation in the reds, while having absolutely no impact on neutral/gray colors. Great! But something else is also happening. Obviously, the increase of rr from 100 to 110 will give me more red in my red areas. But what are the other terms doing? Setting rg and rb both to -5 means I’m also decreasing red in both the green and blue areas. So I’m inadvertently increasing saturation of cyans, (where green and blue intersect), the color opposite of red. In fact, this setup gives me an equal saturation boost in the reds and cyans of my image. That’s not necessarily a bad thing, and proponents of color theory might even say this is a useful transform. Similar neutrality-preserving moves in the green output channel will give me increased green and magenta saturation, and in the blue output channel will give me increases in blue and yellow. Finally, if I make all the same settings for all output channels, I get a global saturation boost. More correctly, I get a global boost in chroma.
I used 110/-5/-5 in my examples, but the general form of this saturation transform is 100+2a/-a/-a, where a is the magnitude of effect we’re going for.
so for example if I use a = 0.1 I’ll get this matrix
in Photoshop percentage terms that’s the following
| Output Channel | Red Input | Green Input | Blue Input |
| Red Output | 120 | -10 | -10 |
| Green Output | -10% | 120 | -10 |
| Blue Output | -10 | -10 | 120 |
Is a global saturation CM transform useful? Why not just use an HSL adjustment layer and increase saturation with that? Well, it depends how much of a purist you are, and likely depends on how much you saturation you’re adding.
Let’s go to Desmos and look at a model for this CM saturation, and compare it to a similar increase in HSL saturation. But first you may want to read this earlier post on the construction of my Desmos hue strip to get some hints at some of the problems with HSL.
If I set the a value of my CM saturation transform to 33 (which means 166 for all my diagonals and -33 for all my off-diagonals), under the current scenario, this gives me an adjusted chroma value of around 60, which you can see from the RGB curves is as high as I can go without clipping shadows or highlights. In spite of this rather extreme increase, everything remains very smooth, including the calculated luminosity (black curve).

Now let’s look at what an HSL- saturation increase does for a similar increase in chroma. Now our output hue strip looks much less smooth, almost unsightly. And the calculated luminosity (black line) has become rather jagged.

The culprit here is the sector-based approach used in HSL, and can be more specifically tied to the lightness L parameter that is used in the HSL calculations. Finally, note the difference in the output RGB curves we got from our CM saturation boost, versus the RGB curves from the HSL saturation boost. They remain completely smooth for CM while we get discontinuous bumps and dips with HSL saturation. This jumpy behavior for HSL saturation is exactly why we’re advised in various color tutorials to be careful about large saturation boosts using the HSL adjustment layer, which can lead to color banding in our hard-earned photographs.
The key difference in these two approaches is that Channel Mixer applies a single linear transformation across all colors, while HSL operates using piecewise definitions that vary by hue sector. This is why CM preserves smoothness, while HSL can introduce discontinuities.
Despite the arguably more pure approach of CM saturation, the biggest advantage of the HSL layer is it gives you a smooth continuous slider. Applying a 100+2a/-a/-a CM operation is not as straightforward. Nevertheless, it’s hard to unsee the messy behavior of HSL-S, so I’m personally sticking with CM saturation from here on out. To make it as simple as HSL-S, I’ve created a set of actions with a = 10, 20, or 30, then adjust strength accordingly using the opacity slider. I’ll also combine these actions for selective enhancement using my various color range masks.
While the 1+2a/-a/-a formula is great for increasing saturation with positive a values, it is equally useful for decreasing saturation using negative a values. And I think this is may be the strongest argument for using CM to control saturation and other properties. Since these transforms are extremely smooth across hues, I have no qualms about stacking them. With so many tools at our disposal it is all too easy to overdo things, and I’ll frequently add a 1-2a/a/a (in all channels) desaturation transform as a final tweak to back off on whatever I’ve done in the first round of adjustments. In color processing terms, this kind of transform is called crosstalk, and is often used to provide a more filmic look.
| Output Channel | Red Input | Green Input | Blue Input |
| Red Output | 80 | +10 | +10 |
| Green Output | +10% | 80 | +10 |
| Blue Output | +10 | +10 | 80 |
Here’s an animated simulation of Channel Mixer Saturation/desaturation using the matrices in the tables above. As you can see from the clip, the desaturation matrix, because it’s decreasing the values of the RGB channels across the board, would likely require a brightness correction. The positive saturation operator goes the other way, so be mindful of undesired brightness changes there as well. One could alternatively change the blend mode of the CM layer to color, which will preserve luminosity.
Hue rotation with CM
So, now we’ve derived one very solid general CM transform for a neutral-preserving saturation increase. But there is another transform that preserves saturation and is foundational in color models and transforms.
Recall, if I only play with the off-diagonal elements (the input channels that don’t match the output channels), I can do things like introduce more green into the red regions by changing gr from 0 to +10 for instance. And I can remove green from the red regions by changing gr from 0 to -10. The first will shift my reds toward yellow, and the second will shift my reds towards magenta, changing hue in the red regions (or red-dominant pixels). But those are actually very strong changes in hue of the reds.
Let’s start off smaller, and try to preserve neutrality at the same time. Let’s change gr to +1, and gb to -1. Adding green in the reds, as discussed earlier, will shift reds toward yellow, a positive hue shift (red is 0 on the hue wheel and yellow is 60). Our second move, setting gb to -1, will remove greens from the blues, shifting the blues towards magenta, also a positive hue shift. So now we have a simple hue rotator that preserves neutrality.
How do we make positive shifts with the other output channels? For red, if I change rg to -1, I’m taking red away from green, shifting greens more positive, and if I want to preserve neutrality, I change rb to +1, which means adding red to blue, shifting toward magenta, also a positive change in hue. Finally, for the blue output channel, changing br to -1 takes blue away from reds, shifting positive again, while changing bg to +1 will add blues to green, again shifting positive while preserving neutrality. So if I want a global hue rotation in the positive direction I just combine all of those channel moves. And of course I just need to do the reverse of that set to all channels to give me a global negative hue shift.
But why stop there? As it turns out, the moves I just described are just a first approximation of the Rodrigues rotation matrix, developed for physics applications in the 19th century.
Here is the Rodrigues matrix for hue rotation in full glory
Now, you’re never going to need all that, and in general it’s shocking how little hue rotation a typical image can take without looking very strange. While I’d love to make a CM hue rotator for just +/-3 degrees, we have one limitation within Photoshop to contend with, and that is floating point error. Photoshop, in its percentage usage, can only take double digit CM values, so we can never get a perfectly clean hue rotation because the Rodriguez matrix is almost never going to output a whole set of matrix values with only two decimal values. My solution was to find a single hue rotation value that minimizes floating point error, then control the amount of actual hue rotation using layer opacity. The smallest value I found that gives me an exceedingly small floating point error is +/-14 degrees.
Here’s a table of my 14 degree positive hue shift CM values.
| Output Channel | Red Input | Green Input | Blue Input |
| Red Output | 98% | -13% | 15% |
| Green Output | 15% | 98% | -13% |
| Blue Output | -13% | 15% | 98% |
And a -14 degree hue shift looks like this
| Output Channel | Red Input | Green Input | Blue Input |
| Red Output | 98% | 15% | -13% |
| Green Output | -13% | 98% | 15% |
| Blue Output | 15 | -13% | 98% |
Obviously, two +/-14 degree hue rotation CM actions aren’t particularly useful to us. But of course we can control the opacity on the created CM layer to modulate its strength. That actually works quite nicely, since an opacity of 1% gives me a subtle shift of 1.4 degrees, just enough for a visible difference.
To help visually how perfectly smooth these Rodrigues rotations can be, here’s an animation of the matrix applied for a +/- 30 degree rotation of hues.
Beyond neutrality
Thus far we’ve focused on neutrality preserving CM transforms, which is an excellent foundation with, I believe, superior enhancement of color compared to the HSL adjustments.
In the future article, we’ll explore neutrality-breaking matrices, into the world of color grading. To my mind, neutral preserving transforms fall into the category of color enhancement (saturation control) and color correction (hue shift), whereas when we break neutrality we are now color grading, where we add light and mood. I’ve found that CM is a powerful color grading tool when controlled properly, with superior – more photorealistic – results compared to more common methods such as gradient maps or solid fill layers in soft light or linear light blend modes.
One final note:
These color matrix transforms are not unique to Photoshop, they are also found in cinematic color grading tools like Davinci Resolve (called RGB mixer) and pretty much any professional grade color processing tool. Indeed, some of what I’ve learned in exploring the channel mixer is derived from posts I’ve seen about the “RGB mixer” in Davinci Resolve, and everything I’ve described here is directly applicable to those tools as well.
Leave a Reply