I am not good at JavaScript and have been trying to get Ivan Kuckir's Fastest Gaussian Blur code to work with no success. When I load the page, it becomes unresponsive so that I will have to close the window somehow. The code I use follows. What am doing wrong?
<html>
<head>
<script src="Path_To_GaussianBlur.js"></script>
</head>
<body>
<img id="sourceImage" src="SomeImage_200px_x_200px.jpg" />
<canvas id="canvas1" width="200" height="200" style="border: 1px solid blue"></canvas>
<canvas id="canvas2" width="200" height="200" style="border: 1px solid red"></canvas>
<script>
document.getElementById("sourceImage").onload = function () {
var c1 = document.getElementById("canvas1");
var c2 = document.getElementById("canvas2");
var ctx1 = c1.getContext("2d");
var ctx2 = c2.getContext("2d");
var img = document.getElementById("sourceImage");
ctx1.drawImage(img, 0, 0);
ctx2.drawImage(img, 0, 0);
var source = ctx1.getImageData(0, 0, c1.width, c1.height);
var target = ctx2.getImageData(0, 0, c2.width, c2.height);
for (var i = 0; i < source.data.length; i += 4) {
// red chanel
gaussBlur_4(source.data[i], target.data[i], c1.width, c1.height, 2);
// green channel
gaussBlur_4(source.data[i + 1], target.data[i + 1], c1.width, c1.height, 2);
// blue channel
gaussBlur_4(source.data[i + 2], target.data[i + 2], c1.width, c1.height, 2);
}
ctx2.putImageData(target, 0, 0);
};
</script>
</body>
</html>
As stated in comments you need to split the rgba array into separate channels. You can do this in several ways, here is one:
Split
var idata = ctx.getImageData(0, 0, w, h), // assumes ctx/w/h to be defined
rgba = idata.data,
len = w * h,
rSrc = new Uint8Array(len), // source arrays
gSrc = new Uint8Array(len),
bSrc = new Uint8Array(len),
aSrc = new Uint8Array(len),
// define target arrays the same way as above
i = 0, offset = 0;
for(; i < len; i++) {
rSrc[i] = rgba[offset++];
gSrc[i] = rgba[offset++];
bSrc[i] = rgba[offset++];
aSrc[i] = rgba[offset++];
}
Now you can pass each of those arrays to the blur function using target arrays set up in a similar manner as the source arrays, then merge back the result to rgba format.
Apply
gaussBlur_4(rSrc, rTrg, w, h, radius);
gaussBlur_4(gSrc, gTrg, w, h, radius);
gaussBlur_4(bSrc, bTrg, w, h, radius);
gaussBlur_4(aSrc, aTrg, w, h, radius);
Additional tip: if you're using images (as in photos) you can skip blurring the alpha channel as there is none (or technically, is fully opaque in canvas).
Merge
To merge, simply do:
for(i = 0, offset = 0; i < len; i++) {
rgba[offset++] = rTrg[i];
rgba[offset++] = gTrg[i];
rgba[offset++] = bTrg[i];
rgba[offset++] = aTrg[i]; // or just increase offset if you skipped alpha
}
ctx.putImageData(idata, 0, 0);
Due to license conflict on SO a running example can be found in this fiddle (and here is an alternative split/merge using 32-bits approach).
Related
My application stop working in Chrome 104, 105. Can anyone confirm this issue?
steps:
transparentDataArray: Uint8ClampedArray = new Uint8ClampedArray(w, h);
insert some values, leave 0,0,0,0 for transparent points
putImageData on context
drawImage over another context holding an image
=> expected (and working until 104) - replaces only non-transparent points
=> chrome 104 - replace transparent points with white color
const canvasMain = document.getElementById('main');
const contextMain = canvasMain.getContext('2d');
const canvas2 = document.createElement('canvas')
const context2 = canvas2.getContext('2d');
const drawData = () => {
console.log("draw data")
contextMain.putImageData(canvasDataInitial, 0, 0);
const dataArray = new Uint8ClampedArray(w * h * 4);
for (let i = 0; i < w * h; i = i + 4) {
dataArray[i] = 0;
dataArray[i + 1] = 150;
dataArray[i + 2] = 35;
dataArray[i + 3] = i > w * h / 3 ? 0 : 255;
}
canvas2.width = w;
canvas2.height = h;
context2.putImageData(new ImageData(dataArray, w, h), 0, 0);
contextMain.drawImage(canvas2, 0, 0);
}
let canvasDataInitial;
let w,h;
const image = new Image();
image.onload = () => {
w = image.width;
h = image.height;
contextMain.drawImage(image, 0, 0, w, h);
canvasDataInitial = contextMain.getImageData(0, 0, canvasMain.width, canvasMain.height);
drawData();
drawData();
setTimeout(drawData, 1000);
}
image.src = 'data:image/png;base64,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';
<!doctype html>
<html>
<body>
<canvas id="main" width="200" height="200" ></canvas>
</body>
</html>
The answer is "Yes, it's confirmed". The code snippet above proves Chrome behaves differently and oddly. Reported to chromium buglist.
I am trying to delete the existing canvas and create a new one with the modified content (of the old one).
Below is the code I have tried.
/* Identifying the Canvas child inside the div parent */
var c = document.getElementById("myCanvasDiv"),
canv = '',
cv = '';
for (i = 0; i < c.childElementCount; i++) {
console.log(c.children[i].nodeName);
if (c.children[i].nodeName == "CANVAS") {
//console.log(c.children[i].getContext('2d'));
canv = c.children[i];
cv = c.children[i].getContext('2d');
}
}
var new_cv = cv
var items = new_cv.canvas.aa.nodes.bi.ud
var keys = []
/* Retrieving the keys */
for (var i in items){
//console.log(items[i].value.Zd["key"]);
keys.push(i + "|" +items[i].value.Zd["key"]);
}
/* Modifying the Content */
for (var i in items){
var strVal = items[i].value.Zd["key"];
//console.log(items[i].value.Zd["key"]);
for (var j in keys){
if(items[i].value.Zd["key"] && items[i].value.Zd["key"].substring(0,items[i].value.Zd["key"].length-1) == keys[j].split("|")[1]){
items[i].value.Zd["key"] = keys[j].split("|")[1];
}
}
console.log(strVal + "----->" + items[i].value.Zd["key"]);
}
/* Trying to reset the canvas content */
for (i = 0; i < c.childElementCount; i++) {
if (c.children[i].nodeName == "CANVAS") {
/*c.removeChild(c.children[i]);
var newcanvas = document.createElement("canvas");
newcanvas.id="canvas1";
newcanvas.getContext = new_cv;
c.appendChild(newcanvas);*/
//cHeight = c.children[i].height;
//cWidth = c.children[i].width;
//cv.clearRect(0,0,c.children[i].width,c.children[i].height);
//c.children[i] = new_cv;
//cv.setContext(new_cv);
canv.getContext = new_cv;
console.log(cv);
}
}
is there any way I can achieve this.
Thanks in advance.
The simplest way to do it is this:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 50, 50);
ctx.clearRect(0,0, c.width, c.height);
ctx.fillStyle = "black";
ctx.fillRect(10, 10, 50, 50);
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<button onclick="copy()">Copy</button>
<p id="cont"> FillStyle Content</p>
However if you want to use pixel manipulation (much more expensive) you can do this:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 50, 50);
var imgData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
// for every pixel if the red channel value is 255 (i.e. red) then make it black (0)
for (var i = 0; i < imgData.data.length; i += 4) {
if (imgData.data[i + 0] == 255) {
imgData.data[i + 0] = 0;
}
}
// put the modified image back
ctx.putImageData(imgData, 0, 0);
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<button onclick="copy()">Copy</button>
<p id="cont"> FillStyle Content</p>
I am trying to create a template for initiating as many waterfall objects as I wish without having to create a new canvas for each of them. I want two waterfalls with different colors but it doesn't work. I can't figure out why and I'm on it since a few hours. How can I make both red and blue waterfalls appear where the first has a lower z index than the last instantiation?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var w = canvas.width = window.innerWidth;
var h = canvas.height = window.innerHeight;
function waterfall(color) {
var self = this;
this.color = color;
this.water = [];
this.Construct = function(y, vel, acc) {
this.y = y;
this.vel = vel;
this.acc = acc;
}
for(var i = 0; i < 1000; i++) {
this.water.push(new this.Construct(Math.random() * 65, 0.1 + Math.random() * 4.3, 0));
}
this.flow = function(color) {
ctx.clearRect(0, 0, w, h);
for(var i = 0; i < this.water.length; i++) {
this.water[i].vel += this.water[i].acc;
this.water[i].y += this.water[i].vel;
ctx.beginPath();
ctx.arc(0 + i * 0.5, this.water[i].y, 2, 0, Math.PI * 2, false);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
for(var i = 0; i < this.water.length; i++) {
if(this.water[i].y > window.innerHeight) {
this.water[i].y = 0;
}
}
requestAnimationFrame(function() {
self.flow.call(self);
});
}
this.flow(this.color)
}
new waterfall("blue");
new waterfall("red");
Here's my working code: https://jsfiddle.net/testopia/d9jb08xb/5/
and here again my intention to create two separate waterfalls but this time with the prototype inheritance:
https://jsfiddle.net/testopia/d9jb08xb/8/
I do prefer the latter but I just cant get either working.
The problem is that you are clearing the canvas in each waterfall. One is overpainting the other. You can immediately see that by commenting out the line
ctx.clearRect(0, 0, w, h);
Of course the water smears that way.
You have to manage your waterfalls in a way that in each animation frame you first clear the canvas then let them paint all.
Here is a quick attempt using a master flow_all() function:
https://jsfiddle.net/kpomzs83/
Simply move this line...
ctx.clearRect(0, 0, w, h);
... to here...
requestAnimationFrame(function() {
ctx.clearRect(0, 0, w, h); // ensure that w and h are available here.
self.flow.call(self);
});
This ensures that you do not clear the canvas before the 2nd waterfall is drawn. This clears the canvas, then draws the two waterfalls. Make sure you've added them to your water array, of course.
I'm a new programmer, and I've been trying to create a grayscale function through JS for practice.
My code:
<canvas width='400' height='400'></canvas>
<script>
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var image = new Image();
image.onload = function() {
ctx.drawImage(image, 0, 0);
grayscale();
}
image.src = 'images/fry.jpg';
function grayscale () {
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var pixelCount = data.length / 4;
for (var i = 0; i < pixelCount; i++) {
var gray = (data[i] * 0.3) + (data[i+1] * 0.59) + (data[i+2] * 0.11);
data[i] = gray;
data[i+1] = gray;
data[i+2] = gray;
}
ctx.putImageData(imageData, 0, 0);
}
</script>
But when I run the code in Safari and Firefox, this is what happens: grayscale only partly affects image
But, I noticed that if I change the canvas.height dimension in imageData to dimensions significantly larger than the canvas (such as 2000), then the entire image is grayscaled. The fry.jpg file only has dimensions of 387x315 on my computer.
What am I doing wrong?
You are only looping through 1/4 of the image when you divide the imageData.data array by 4.
Each pixel takes 4 values, one each for each channel red, green, blue, and alpha.
The quickest way to iterate them all is
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var channelCount = data.length; // Total number of channel data
var i = 0; // counter
var gray; // computered Gray scale
while(i < channelCount){ // while not done all
gray = (data[i] * 0.3) + (data[i+1] * 0.59) + (data[i+2] * 0.11);
data[i++] = data[i++] = data[i++] = gray; // assign pixel RGB
i++; // skip the alpha
}
// put it back onto the canvas.
ctx.putImageData(imageData, 0, 0);
I'm trying to get the mean color of an image, to compare to the mean color of various slices of the image, to find the area that is most different from the mean. it's part of a project to crop an image automatically, based on areas of greatest interest.
I was getting strange results, so I created a demo page that compares a totally flat red image with slices thereof. each slice should have the same color as the image (192,0,0,255). but, as you can see, they don't:
http://gschoppe.com/projects/jQuery.smartCrop/demo.html (all data goes to the console)
Here's the average color function from the demo:
var getAverageColor = function(canvas) {
var context = canvas.getContext('2d');
var imgdata = context.getImageData(0, 0, canvas.width, canvas.height);
var pixels = imgdata.data;
var color = {red:0,green:0,blue:0,alpha:0};
// Loop over each pixel.
for (var i = 0, n = pixels.length; i < n; i += 4) {
color.red += pixels[i ]/255; //red
color.green += pixels[i+1]/255; //green
color.blue += pixels[i+2]/255; //blue
color.alpha += pixels[i+3]/255; //alpha
}
color.red = color.red/(pixels.length/4);
color.green = color.green/(pixels.length/4);
color.blue = color.blue/(pixels.length/4);
color.alpha = color.alpha/(pixels.length/4);
return color;
}
and here's the (simplified) version of the loop where it's called:
var findPointOfInterest = function(canvas) {
var sliceSize = Math.round(canvas.width/20);
var avgColor = getAverageColor(canvas);
console.log("avg color: ");
console.log(avgColor);
var sliceColor = null;
for(var i=0;i<canvas.width;i+=sliceSize) {
if(i+sliceSize > canvas.width)
sliceSize = canvas.width % sliceSize;
var temp = document.createElement('canvas');
temp.width = sliceSize;
temp.height = canvas.height;
var context = temp.getContext('2d');
context.clearRect ( 0, 0, sliceSize, canvas.height );
context.drawImage(canvas, i, 0, sliceSize, canvas.height, 0, 0, sliceSize, canvas.height);
sliceColor = getAverageColor(temp);
console.log(sliceColor);
}
}
I made a simpler version of the issue for JSFiddle, but it doesn't seem to have the bug! GAH! Here's the simple version: http://jsfiddle.net/tLMPk/ (everything logs to the console)
can anyone help me track this thing down?