我使用画布来设置图像的亮度。如果我只设置亮度一次,这项工作正常。但是如果我将亮度重置为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;
};
}
原始图片:
最高光度的图像:
将图像重置为原始图像(亮度0):
答案 0 :(得分:2)
r,g,b,如你所知,一个组件存储在8位上,这个位太少而不能进行多次操作:在每次操作时,都会发生舍入和钳位。
解决方案是使用Float32Array存储图像的组件。然后你可以进行任何种类和数量的操作(几乎)没有质量损失。
答案 1 :(得分:1)
您刻录了图片losing information。您需要从文件重新加载图像以恢复过度曝光像素的信息。
一旦画布加载图像,它就会“忘记”原始文件,只处理加载的像素。当你增加亮度时,该图片的一个大区域会丢失信息,因为它“超出规模”。除非再次重新加载图片,否则无法恢复丢失的信息。
更新:正如@GameAlchemist建议的那样,您可以创建自己的数组:
var image= new Int32Array(originalByteArray); //Or Float32Array, I'd test both
并在那里存储图像的副本。然后,对该数组进行所有操作并复制图像数据中的输出,只占用前8位。