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

时间:2012-12-18 18:50:40

标签: 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;

这使图像变亮。但是当我从每个像素减少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;

降低亮度:

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;

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

我做错了什么?

2 个答案:

答案 0 :(得分:5)

谷歌快速搜索显示:

adjust bitmap image brightness/contrast using 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?

Johannes Jendersie 说的是真的,你的问题是:

免得说你有一个有这个值的像素

R = 100;
G = 210;
B = 20;

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

R = 200;
G = 255; // It was 310 but you have to clamp it to 255.
B = 120;

现在你减去那些相同的100:

R = 100; // same
G = 155; // different!, this have to be 210!!
B = 20;  // same

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

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

所以你要么保留图像的备份和某处的brightnesCorrection值,每次值改变时,你都会在图像上重新应用修正,或者你只需​​要接受这样一个事实:你将无法将图像恢复到以前的荣耀xD(至少没有这种亮度校正,不确定是否有更好的方法)。

希望它有所帮助。

答案 1 :(得分:5)

由于数值的舍入和钳位,图像上的许多操作都是不可逆的。

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

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


对更新的反应

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

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

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