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

问题描述 投票:0回答:2

正如有一个将图像转换为灰度的公式,是否有一个相同级别的图像亮度增加和降低的公式?我尝试为每个 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;

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

我做错了什么?

image-processing html5-canvas
2个回答
5
投票

谷歌快速搜索显示:

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

链接:

https://web.archive.org/web/20091229041814/http://www.kweii.com/site/color_theory/2007_LV/BrightnessCalculation.pdf

https://web.archive.org/web/20140825114946/http://bobpowell.net/image_contrast.aspx

记得在发帖之前寻找类似的问题 :).

编辑:

另外两个链接:

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

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

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

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”现在是先前过滤的图像。

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

希望有帮助。


5
投票

由于值的舍入和限制,许多图像操作是不可逆的。

你的每一个颜色通道

p[i]
可能是字节类型?如果是这样,则只能存储 0 到 255 之间的值。例如,如果将 100 添加到 223,您最终将得到 323,这是 1 个字节中无法保存的。这应该会导致溢出到 67,或者它被固定到 255(最大可能的数字)。 减去 100 不会恢复 223,但会得到 155.

您应该尝试乘以颜色,而不是添加偏移量。但这包含在 AngelCastillo 的回答中。 (在那里你也会丢失信息,但结果更好)


对更新的反应

我的意思是,限制值(例如您的实际实施)会导致数据丢失。就像上面解释的例子一样,一个太大的值变成 255。所以再次减去 100 会将所有颜色设置为 155,这在原来的 155 或更大。较亮颜色(>155)的信息丢失了。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.