selective saturation with a color matrix?

I’m using Haeberli’s color matrix stuff to do color correction.
<http://www.graficaobscura.com/matrix/index.html>
Using a 4x4 matrix I’ve got hue rotation, general saturation, brightness, contrast, etc.

Now I need to do saturation on the r,g,b primaries. Basically we need to isolate saturation on red, green, and blue. Say you have a picture of a green lawn and a blue sky. Lowering the saturation on “green” should interpolate the green stuff toward gray, leaving the sky alone. So it’s not a simple per-channel blend to gray.

I know there is probably a magical matrix solution where you rotate the matrix to get the green channel to line up somehow, then just multiply by some numbers and then rotate back (sort of like was done for the hue/saturation matrix), but the math and order of operations escapes me.

Does anyone have any insight on how this can be done, without going entirely into HSL space?

Maybe:


float mat[4][4] = {
	a,      b,      c,      0.0,
	d,      e,      f,      0.0,
	g,      h,      i,      0.0,
	0.0,    0.0,    0.0,    1.0,
};


float rs,gs,bs; // your saturations

float s = rs+gs+bs;

if(s>1.0){ // tune this
	rs/=s;
	gs/=s;
	bs/=s;
	s=1;
}


a = (1.0-s)*rwgt + rs;
b = (1.0-s)*rwgt;
c = (1.0-s)*rwgt;
d = (1.0-s)*gwgt;
e = (1.0-s)*gwgt + gs;
f = (1.0-s)*gwgt;
g = (1.0-s)*bwgt;
h = (1.0-s)*bwgt;
i = (1.0-s)*bwgt + bs;