I'd like to create Level correction with help Pixel Bender. I made correction for each channel (r, g, b), it works. But I don't know how to make correction for midtone for each one.
Is there some formula or example?
Unfortunately google hasn't got solution
I use the next code for each channel, for instance, the red channel will be look like
dst.r = ((dst.r-red[0])/(red[1]-red[0])-rgb[1]-rgb[0]), where red[n], rgb[n] are the values which can be changed by user
I'm not sure I'm understanding exactly what you're wanting. There is a gamma tutorial with some glsl shaders at:
http://www.geeks3d.com/20101001/tutorial-gamma-correction-a-story-of-l inearity/
A PixelBender shader for the channel by channel gamma is:
<languageVersion : 1.0;>
kernel channelByChannelGamma
< namespace : "cfr";
vendor : "AIF";
version : 1;
>
{
input image4 src;
output pixel4 dst;
parameter float3 gammaRGB <defaultValue:float3(1.0, 1.0, 1.0);>;
void
evaluatePixel()
{
dst = sampleNearest(src,outCoord());
dst.rgb = pow(dst.rgb, 1.0 / gammaRGB);
}
}
gammaRGB is a float3. If you wanted to alter the gamma for G and leave the others unchanged, you can set that parameter to (1.0, greenGamma, 1.0). The pow function and the 1.0 divide in the kernel are componentwise. This line instead would have been equivalent, but does make the intention clearer:
dst.rgb = pow(dst.rgb, float3(1.0, 1.0, 1.0) / gammaRGB);
Most of the intrinsic functions will return vectors if their operands are vectors. Intrinsitcs like dot, any, and all, which specifically reduce a vector input to a scalar output, are the exceptions.
thanks for your reply! so, if i wanna change gamma for each channel separately i have to change your code so:
dst.rgb = pow(dst.rgb, float3(red[1], green[1], blue[1])/gammaRGB)
where red[1], green[1], blue[1] are the parameters of gamma
i compared the result which i've got and it's different from photoshop's
so, now my code looks like this
{
parameter float3 red
<
minValue: float3(0.0,0.0,1.0);
maxValue: float3(1.0,1.0,1.0);
defaultValue: float3(0.0,1.0,1.0);
>;
parameter float3 green
<
minValue: float3(0.0,0.0,0.0);
maxValue: float3(1.0,1.0,1.0);
defaultValue: float3(0.0,1.0,1.0);
>;
parameter float3 blue
<
minValue: float3(0.0,0.0,0.0);
maxValue: float3(1.0,1.0,1.0);
defaultValue: float3(0.0,1.0,1.0);
>;
parameter float3 RGB
<
minValue: float3(0.0,0.0,0.0);
maxValue: float3(1.0,1.0,1.0);
defaultValue: float3(0.0,1.0, 1.0);
>;
input image4 src;
output pixel4 dst;
void
evaluatePixel()
{
pixel4 p = sampleNearest(src,outCoord());
float rgbdiff = RGB[2] - RGB[0];
p.r = ( (p.r - red[0])/(red[2] - red[0]) - RGB[0])/rgbdiff;
p.g = ( (p.g - green[0])/(green[2] - green[0]) - RGB[0])/rgbdiff;
p.b = ( (p.b - blue[0])/(blue[2] - blue[0]) - RGB[0])/rgbdiff;
p.rgb = pow(p.rgb, float3(red[1], green[1], blue[1]) / RGB[1]);
dst = p;
}
}
upd: i tried to apply this filter again and it seems to me it works! Thank you very much for your correct answer. Maybe you know how to use photoshop's 'output panel', this parameter increases/decreases values of channel. Photoshop has this parameter in the bottom of level's panel.
I'm glad I was able to help. I'm not certain what the exact formula the Photoshop team is using, so I was going on one in the gamma tutorial website I was pointed out earlier in this thread. That seemed to follow the standard gamma formulation I've seen on wiki and in the CG texts I have in my office.
I did have a look at the panel you suggested. I don't think I've used that one before, so thanks for the pointer.
Best,
Chuck.