HTML5画布上的Gamma调整?

时间:2012-12-23 15:32:43

标签: html5-canvas

我找到了一种增加伽玛的方法,但没办法减少它! This article陈述了增加伽玛的公式。即使我在画布的新实例上应用缩小,该公式也可用于增加伽玛而不是减少。我尝试重新绘制画布并使用负值进行伽玛计算,但我不会将原始画布恢复。

//For increasing, I tried
gamma = 0.5;
gammacorrection = 1/gamma;
r = Math.pow(255 * (r / 255), gammacorrection);
g = ...
b = ...

//For decreasing
gamma = -0.5;
gammacorrection = 1/gamma;
r = Math.pow(255 * (r / 255), gammacorrection);
g = ...
b = ...

第一部分有效。第二个没有。

3 个答案:

答案 0 :(得分:2)

没有负伽马校正。您应该保存原始值并在进行伽玛更改时使用它们,并将伽玛值设置为1.0以恢复原始值。

另请注意,您的操作顺序错误(指数在乘法之前出现)。

var originals = { r: r, g: g, b: b };

// increase
gamma = 0.5;
gammacorrection = 1/gamma;
r = 255 * Math.pow(( originals.r / 255), gammacorrection);
g = ...
b = ...

// revert to original
gamma = 1;
gammacorrection = 1/gamma;
r = 255 * Math.pow(( originals.r / 255), gammacorrection);
g = ...
b = ...

答案 1 :(得分:1)

为了完整起见,这是一段有效的代码

async function adjustGamma(gamma) {
    const gammaCorrection = 1 / gamma;
    const canvas = document.getElementById('canvasOutput');
    const ctx = canvas.getContext('2d');
    const imageData = ctx.getImageData(0.0, 0.0, canvas.width, canvas.height);
    const data = imageData.data;
    for (var i = 0; i < data.length; i += 4) {
        data[i] = 255 * Math.pow((data[i] / 255), gammaCorrection);
        data[i+1] = 255 * Math.pow((data[i+1] / 255), gammaCorrection);
        data[i+2] = 255 * Math.pow((data[i+2] / 255), gammaCorrection);
    }
    ctx.putImageData(imageData, 0, 0);
}

此处,该功能根据OP上ID为“ canvasOutput”的Canvas上OP链接的文章中的公式来调整伽玛值

答案 2 :(得分:0)

伽马没有负值。理想情况下,此值介于0.017.99之间。因此,应该可以通过创建具有图像原始值的新画布实例,然后实例化它,或者通过使用原始图像创建像素池并还原为它来实现将伽玛恢复为原始值。 / p>

我写了一个脚本,我将如何构建降低伽玛的算法。

var gamma = 0.5;
var gammaCorrection = 1 / gamma;

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0.0, canvas.width, canvas.height);   

function GetPixelColor(x, y) {   
    var index = parseInt(x + canvas.width * y) * 4;
    var rgb = {
        r : imageData.data[index + 0],
        g : imageData.data[index + 1],
        b : imageData.data[index + 2]
    };

    return rgb;
}

function SetPixelColor(x, y, color) {
    var index = parseInt(x + this.width * y) * 4;
    var data = imageData.data;

    data[index+0] = color.r;
    data[index+1] = color.g;
    data[index+2] = color.b;
};


for (y = 0; y < canvas.height; y++) {
     for (x = 0; x < canvas.width; x++) {
         var color = GetPixelColor(x, y)
         var newRed   = Math.pow(255 * (color.r / 255), gammaCorrection);
         var newGreen = Math.pow(255 * (color.g / 255), gammaCorrection);
         var newBlue  = Math.pow(255 * (color.b / 255), gammaCorrection);

         var color = {
             r: newRed,
             g: newGreen,
             b: newBlue
         }

         SetPixelColor(x, y, color);
     }
}

我不知道应用程序应该如何调整gamma值,但我想这是通过值调整器来完成的。如果是这样,您应该动态调整伽玛值,给出最小和最大范围。我没有测试代码,这不是我的范围,但希望清楚这个想法。

修改 要了解伽马校正的原理,首先要如何定义伽玛。

Gamma是改变像素输入的显示器特性。伽玛校正是将该过程反转为线性RGB值的行为,以使最终输出保持线性。例如,如果计算出对象的光强度为0.5,则不会将结果存储为像素中的0.5。将其存储为pow(0.5, 1.0/2.2) = 0.73。当您向监视器发送0.73时,它将对该值应用一个伽玛并生成pow(0.73, 2.2) = 0.5,这就是您想要的。为此,请应用反伽马函数。

o=pow(i, 1.0/gamma)

其中

o是输出值。

i是输入值。

gamma是显示器使用的gamma值。

因此,伽马校正只不过是输入值上升到伽马相反的幂。因此,要将伽玛恢复为原始值,请在应用伽马校正之前应用公式。

enter image description here enter image description here

蓝线表示在将像素发送到显示器之前需要应用于像素的反伽马曲线。当您的显示器将其伽玛曲线(红线)应用于像素时,结果是一条线性线(绿线),表示您想要的RGB像素值。