Javascript 为什么可以';我不能还原画布上的亮度吗?

Javascript 为什么可以';我不能还原画布上的亮度吗?,javascript,canvas,Javascript,Canvas,我使用画布设置图像的亮度。如果我只设置一次亮度,这项工作就可以了。但是如果我将亮度重置为0,则不会得到默认图像。我不知道为什么 调用效果的代码: var mainEffect = new CanvasEffect(canvas[0]); var thumbsEffect = new CanvasEffect(thumbs[0]); luminositySlider.change(function() { var intensity = luminositySlider.val();

我使用画布设置图像的亮度。如果我只设置一次亮度,这项工作就可以了。但是如果我将亮度重置为0,则不会得到默认图像。我不知道为什么

调用效果的代码:

var mainEffect = new CanvasEffect(canvas[0]);
var thumbsEffect = new CanvasEffect(thumbs[0]);
luminositySlider.change(function() {
    var intensity = luminositySlider.val();
    mainEffect.apply("luminosity", intensity);
    thumbsEffect.apply("luminosity", intensity);
});
这是我使用的代码,int是从html滑块获得的。以前的亮度存储在一个数组中:

function CanvasEffect(canvas) {
var ctx = canvas.getContext("2d");
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var stack = [];
var imageData;
var data;

this.apply = function(effect, intensity) {
    imageData = ctx.getImageData(0,0, WIDTH, HEIGHT);
    data = imageData.data;
    var int = Number(intensity);
    var refresh =  true;
    switch (effect) {
    case "blur":
        refresh = false;
        stackBlurCanvasRGB('canvas', 0, 0,  WIDTH, HEIGHT, int);
        break;
    case "sharpen":

        break;
    case "luminosity":
        console.log("stack['luminosity'] : " + stack["luminosity"]);
        lastInt = (stack["luminosity"] == undefined) ? 0 : stack["luminosity"];
        newInt = int - lastInt;
        console.log("int : " + int, "lastInt : " + lastInt, "newInt : " + newInt);
        for(var i=0;i < data.length;i+=4) {
            data[i] += newInt; //Red
            data[i+1] += newInt; //Green
            data[i+2] += newInt; //Blue
        }
        break;
    case "contrast":
        lastInt = (stack["contrast"] == undefined) ? 0 : stack["contrast"];
        newInt = int - lastInt;
        var factor = (259 * (newInt + 255)) / (255 * (259 - newInt));
        for(var i = 0; i < data.length ; i+=4) {
            data[i] = factor *  (data[i] - 128) + 128; //Red
            data[i+1] = factor *  (data[i+1] - 128) + 128; //Green
            data[i+2] = factor *  (data[i+2] - 128) + 128; //Blue
        }
        break;
    case "negatif":
        console.log("negatif");
        for(var i=0;i < data.length;i+=4) {
            data[i] = 256-data[i]; //Red
            data[i+1] = 256-data[i+1]; //Green
            data[i+2] = 256 - data[i+2]; //Blue
        }
        break;
    case "b&w":
        console.log("b&w");
        for(var i=0;i < data.length;i+=4) {
            var gris = data[i]*0.3 + data[i+1]*0.59 + data[i+2]*0.11;
            data[i] = gris; //Red
            data[i+1] = gris; //Green
            data[i+2] = gris; //Blue
        }
        break;
    case "sepia":
        console.log("sepia");
        for(var i=0;i < data.length;i+=4) {
            var r = data[i]*0.299 + data[i+1]*0.587 + data[i+2]*0.114;
            data[i] = Math.max(0, Math.min(255, r*1.351)); //Red
            data[i+1] = Math.max(0, Math.min(255, r*1.203)); //Green
            data[i+2] = Math.max(0, Math.min(255, r*0.937)); //Blue
        }
        break;
    default:
        break;
    }

    if(refresh) {
        imageData.data = data;
        ctx.putImageData(imageData,0 ,0);
    }
    // Stores the effect to recalculate if it changes
    stack[effect] = int;
};
函数画布效果(画布){
var ctx=canvas.getContext(“2d”);
var WIDTH=canvas.WIDTH;
var HEIGHT=canvas.HEIGHT;
var堆栈=[];
var图像数据;
var数据;
this.apply=功能(效果、强度){
imageData=ctx.getImageData(0,0,宽度,高度);
data=imageData.data;
var int=数量(强度);
var刷新=真;
开关(效果){
案例“模糊”:
刷新=错误;
stackBlurCanvasRGB(“画布”,0,0,宽度,高度,整数);
打破
案例“锐化”:
打破
案例“亮度”:
log(“stack['luminity']:”+stack['luminity']);
lastInt=(堆栈[“亮度”]==未定义)?0:堆栈[“亮度”];
newInt=int-lastInt;
log(“int:+int,lastin:+lastin,newInt:+newInt”);
对于(变量i=0;i
}

原始图像:

具有最大亮度的图像:

将图像重置为原始图像(亮度0):

您烧掉了图像。您需要从文件中重新加载图像,以恢复过度曝光的像素的信息

画布加载图像后,会“忘记”原始文件,只处理加载的像素。当你增加亮度时,那张图片的一个大区域丢失了信息,因为它“超出了比例”。除非重新加载图片,否则无法恢复丢失的信息

更新:正如@gamealchest所建议的,您可以创建自己的阵列:

var image= new Int32Array(originalByteArray); //Or Float32Array, I'd test both

并在那里存储图像的副本。然后,对该数组执行所有操作,并在图像数据中复制输出,仅取前8位。

如您所知,r、g、b、a分量存储在8位上,这8位太少,无法进行多次操作:在每次操作中,将发生舍入和钳位


解决方案是使用Float32Array存储图像的组件。然后,您可以执行任何种类和数量的操作,并且(几乎)不会损失质量

好吧,这将是一场表演的噩梦。如果我有多个过滤器。我必须重置图像并再次应用所有过滤器?使用int32扩展动态范围是可能的,但需要仔细编程以避免出现溢出/下溢/舍入问题。不值得我这么努力。