在Canvas上调整亮度/对比度的公式?

Rut*_*rde 4 image-processing html5-canvas

就像有一个将图像转换为灰度的公式一样,是否有一个公式可以增加图像的亮度并将其降低到相同的水平?我尝试为每个r,g和b像素添加一个值.它确实增加了亮度,但当我减少相同的值时,我没有得到原来的值.

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]+100;
p[i+1] = p[i+1]+100;
p[i+2] = p[i+2]+100;
Run Code Online (Sandbox Code Playgroud)

这使图像变亮.但是当我从每个像素减少100时,我没有得到原始图像.

我在网上看到,有一些公式可以正确计算.有人能解释一下吗?同样对比度和伽玛?

更新:

谢谢大家的建议.经过以下的一些帖子后我尝试了这个.

为了增加亮度:

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]+100 < 255 ? p[i]+100 : 255;
p[i+1] = p[i+1]+100 < 255 ? p[i+1]+100 : 255;
p[i+2] = p[i+2]+100 < 255 ? p[i+2]+100 : 255;
Run Code Online (Sandbox Code Playgroud)

并为降低亮度:

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]-100 >= 0 ? p[i]-100 : 0;
p[i+1] = p[i+1]-100 >= 0 ? p[i+1]-100 : 0;
p[i+2] = p[i+2]+100 >= 0 ? p[i+2]-100 : 0;
Run Code Online (Sandbox Code Playgroud)

我可以看到增量工作正常,但是当我减少它时,我仍然没有得到原始图像,原始图像和增亮图像之间有一点差别!

我究竟做错了什么?

Ang*_*llo 5

在谷歌上快速搜索显示:

使用c ++调整位图图像亮度/对比度

链接:

http://www.kweii.com/site/color_theory/2007_LV/BrightnessCalculation.pdf

http://www.bobpowell.net/image_contrast.htm

在发布一个:)之前,请记住寻找类似的问题.

编辑:

另外两个链接:

图像处理算法第5部分:对比度调整:

http://thecryptmag.com/Online/56/imgproc_5.html

图像处理算法第4部分:亮度调整:

http://www.dfstudios.co.uk/articles/image-processing-algorithms-part-4/

编辑:

您发布的第二个代码块中有错误:

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]-100 >= 0 ? p[i]-100 : 0;
p[i+1] = p[i+1]-100 >= 0 ? p[i+1]-100 : 0;
p[i+2] = p[i+2]+100 >= 0 ? p[i+2]-100 : 0; // <- Tha p[i+2]+100 should be a p[i+2]-100 right?
Run Code Online (Sandbox Code Playgroud)

什么约翰内斯Jendersie说的是真的,你的问题是这样的:

不要说你有一个像这个值的像素

R = 100;
G = 210;
B = 20;
Run Code Online (Sandbox Code Playgroud)

你为每种颜色添加100,现在你有:

R = 200;
G = 255; // It was 310 but you have to clamp it to 255.
B = 120;
Run Code Online (Sandbox Code Playgroud)

现在你减去那100个:

R = 100; // same
G = 155; // different!, this have to be 210!!
B = 20;  // same
Run Code Online (Sandbox Code Playgroud)

这就是为什么这种操作不可逆转的原因.您可以执行的操作始终是原始图像的副本,每次更改该值时,都会应用亮度校正.

因此撤消添加100的操作的方法不是减去100,而是将亮度校正值设置为0.这是多少图像编辑程序工作,你有一个滑块,当你在滑块窗口改变你可以的值如果将原始图像设置为0,则始终获取原始图像,但是一旦"应用"校正,则无法撤消,当您重新打开滑块窗口时,"0"现在是先前已过滤的图像.

因此,您要么保留图像的备份和某处的brightnesCorrection值,每次值更改时,您都会在图像上重新应用更正,或者您只需接受无法恢复图像的事实.图像到昔日的辉煌xD(至少没有这种亮度校正,不确定是否有更好的方法).

希望能帮助到你.


Joh*_*sie 5

由于值的舍入和钳位这一事实,对图像的许多操作是不可逆的.

您的每个颜色通道p[i]可能都是字节类型?如果是这样,它只能存储0到255之间的值.如果你添加100到例如223,你将最终在323,什么不能保存在1字节.这应该导致溢出到67或者它被钳位到255(最大可能的数字).减去100将不会恢复223,但结果为155.

不要添加偏移量,而应尝试乘以颜色.但AngelCastillo的回答涵盖了这一点.(那里你也会丢失信息,但结果更好)


对更新的反应:

我的意思是,钳位值(例如您的实际实现)会导致数据丢失.与上面解释的例子中一样,太大的值变为255.因此,再次减去100会将所有颜色设置为155,原始值为155 或更大.更亮的颜色(> 155)的信息丢失.

在其他情况下(对比度和伽玛变化),您也会丢失信息,因为舍入将以前的不同颜色设置为相同的值.

避免这种情况的唯一方法是使用其他格式,每个频道有更多信息.例如> 16位有符号整数或浮点数.我怀疑你的画布有选项可以做到这一点,所以你需要拥有自己的背景副本(具有更高的值范围).对副本执行所有转换,只显示画布上的图像.