I have a question about count pixels of an image in Canvas, please see code below:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pixel Counting</title>
<script type="text/javascript">
window.onload = function() {
var img = new Image();
img.src="lena.jpg";
img.onload = function() {
countPixel(img)
};
}
function countPixel(img) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// Draw the image to canvas.
context.drawImage(img, 0, 0);
// Now we can get the image data from the canvas.
var imageData = context.getImageData(0, 0, img.width, img.height);
var data = imageData.data;
// Do the pixel counting.
var redCount = new Array(256);
var greenCount = new Array(256);
var blueCount = new Array(256);
for (var i = 0; i < 256; i++) {
redCount[i] = 0;
greenCount[i] = 0;
blueCount[i] = 0;
}
for (var i = 0; i < data.length; i += 4) {
redCount[data[i]]++; // red
greenCount[data[i + 1]]++; // green
blueCount[data[i + 2]]++; // blue
}
// Write the result to table.
var pixelTable = document.getElementById('pixel_table');
for (var i = 0; i < 256; i++) {
var row = pixelTable.insertRow(-1);
row.insertCell(-1).innerHTML = i;
row.insertCell(-1).innerHTML = redCount[i];
row.insertCell(-1).innerHTML = greenCount[i];
row.insertCell(-1).innerHTML = blueCount[i];
}
}
</script>
</head>
<body>
<div>
<canvas id="canvas" width="500" height="500">
</canvas>
</div>
<div>
<table id="pixel_table" border="1">
<caption style="font-size:25px;font-weight:bold;">Pixel Count</caption>
<tr id="header"><th>Intensity</th><th>Red</th><th>Green</th><th>Blue</th></tr>
</table>
</div>
</body>
</html>
I do not understand this for loop:
for (var i = 0; i < 256; i++) {
redCount[i] = 0;
greenCount[i] = 0;
blueCount[i] = 0;
}
What does this loop here mean? This is the beginning part of the count, but why make all value to zero?
It's needed as none of the elements in the declared array are defined at that point. The loop starts at first element in the array, then goes through each single one to set an initial value to 0 (otherwise it would be undefined which would give you problems later when you try to add a number to it).
However, the better option in this case, is to replace this block:
var redCount = new Array(256);
var greenCount = new Array(256);
var blueCount = new Array(256);
for (var i = 0; i < 256; i++) {
redCount[i] = 0;
greenCount[i] = 0;
blueCount[i] = 0;
}
with typed arrays, which do have all their values initialized to 0 as well as being faster than node-based arrays:
var redCount = new Uint32Array(256);
var greenCount = new Uint32Array(256);
var blueCount = new Uint32Array(256);
If you don't do that the array will be filled with undefined values.
new Array(5);
will result in:
[undefined, undefined, undefined, undefined, undefined]
Related
i am getting frames from gif using Libgif.
and then i am appending those frames in the div with Id = frames.
then i am taking those frames and trying to add each frames one after the other in canvas to make a spritesheet.
in the end i am getting an image in canvas but instead of getting different frames i am getting same image in the spritesheet.
Please help me find the issue.
I had taken canvas width 10000 assuming a gif wont have frames more than 100.
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
ctx.clearRect(0, 0, ctx.width, ctx.height);
ctx.beginPath();
var imageGiF = "";
var total = 0;
let canvasWidth = 0;
let canvasHeight = 0;
$('div.gifimage img').each(function(idx, img_tag) {
var total = 0;
if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
var rub = new SuperGif({
gif: img_tag,
progressbar_height: 0
});
rub.load(function() {
for (let i = 0; i < rub.get_length(); i++) {
total += 1;
rub.move_to(i);
// var canvas = cloneCanvas(rub.get_canvas());
var canvas = rub.get_canvas().toDataURL("image/png");
img = $('<img id = "gifframe' + i + '"src= "' + canvas + '" class= frameimages>');
$("#frames").append(img);
}
var frameimages = document.getElementById("frames").querySelectorAll(".frameimages");
var totalimages = frameimages.length;
x = 0;
y = 0;
for (let i = 0; i < frameimages.length; i++) {
img = document.getElementById("gifframe" + i + "");
img.onload = function() {
ctx.drawImage(img, i * 100, 0, 100, 100);
total++;
console.log(total);
}
}
totalwidth = (total) * 100;
c.width = totalwidth;
c.height = 100;
setTimeout(() => {
imageGiF = c.toDataURL("image/png");
console.log(imageGiF);
// addBgimg(imageGiF)
}, 10);
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/buzzfeed/libgif-js/master/libgif.js"></script>
<div class="gifimage" id="placehere">
<img src="https://media1.giphy.com/media/bzUwzbxcvJ3XQlcnoi/giphy.gif" alt="">
</div>
<div id="frames" class="classGIF"></div>
<canvas id='myCanvas' width="10000" height="300"></canvas>
You were looping through the images, using img in your event handler.
However, this variable img in the outer scope was overridden by every loop, until it was finished looping through everything, then img was stuck on the last frame added.
Then when the event handler triggered, it added the last frame in every instance, because that was the value of img at that point. The loop was done before the images could load.
By adding it to it's own scope by wrapping it in a function, the variable is preserved.
I also modified your code to store the DOM img elements in an array, so you don't need expensive DOM lookups which makes your code a tad bit faster.
I added comments in the code to explain my changes.
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
ctx.clearRect(0, 0, ctx.width, ctx.height);
ctx.beginPath();
var imageGiF = "";
var total = 0;
let canvasWidth = 0;
let canvasHeight = 0;
$('div.gifimage img').each(function(idx, img_tag) {
var total = 0;
if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
var rub = new SuperGif({
gif: img_tag,
progressbar_height: 0
});
rub.load(function() {
// An array for the image references
let images = [];
// Keep the reference to save on expensive DOM lookups every iteration.
let frames = $("#frames");
for (let i = 0; i < rub.get_length(); i++) {
total += 1;
rub.move_to(i);
// var canvas = cloneCanvas(rub.get_canvas());
var canvas = rub.get_canvas().toDataURL("image/png");
img = $('<img id = "gifframe' + i + '"src= "' + canvas + '" class="frameimages">');
// Use the reference to append the image.
frames.append(img);
// Add image to images array with the current index as the array index.
// Use the jQuery get method to get the actual DOM element.
images[i] = img.get(0);
}
var frameimages = document.getElementById("frames").querySelectorAll(".frameimages");
var totalimages = frameimages.length;
x = 0;
y = 0;
// Loop through all the images in the image array
// Using a scope so the reference to img won't be overridden.
images.forEach((img, index) => {
img.onload = () => {
ctx.drawImage(img, index * 100, 0, 100, 100);
total++;
console.log(total);
}
})
totalwidth = (total) * 100;
c.width = totalwidth;
c.height = 100;
setTimeout(() => {
imageGiF = c.toDataURL("image/png");
console.log(imageGiF);
// addBgimg(imageGiF)
}, 10);
});
}
});
#frames { display:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/buzzfeed/libgif-js/master/libgif.js"></script>
<div class="gifimage" id="placehere">
<img src="https://media1.giphy.com/media/bzUwzbxcvJ3XQlcnoi/giphy.gif" alt="">
</div>
<div id="frames" class="classGIF"></div>
<canvas id='myCanvas' width="10000" height="300"></canvas>
I'm trying to change image position using JavaScript using my code but for some reason it doesn't work. Can someone explain the reason.
var walk, isWaveSpawned = true;
var walkers = [];
function start()
{
walk = document.getElementById("walk");
draw(); //Animation function
}
function draw()
{
if(isWaveSpawned) //Generate a wave of 5 "walkers"
{
isWaveSpawned = false;
for(var i = 0; i < 5; i++
walkers.push(new createWalker());
}
for(var o = 0; o < walkers.length; o++) //Add 1px to x position after each frame
{
walkers[o].x += walkers[o].speed;
walkers[o].image.style.left = walkers[o].x;
walkers[o].image.style.top = walkers[o].y;
}
requestAnimationFrame(draw);
}
function createWalker()
{
this.x = 0;
this.y = 100;
this.speed = 1;
this.image = walk.cloneNode(false); //Possible cause of issue
}
<!DOCTYPE html>
<html>
<body onload="start()">
<img id="walk" src="https://i.imgur.com/ArYIIjU.gif">
</body>
</html>
My GIF image is visible in top left corner but doesn't move.
P.S. Added a HTML/JS snippet but it outputs some errors while in my end these errors are not seen.
First let's modify the way you're cloning the gif - get rid of this line:
this.image = walk.cloneNode(false);
and insert this:
this.image = document.createElement("img");
This will create a fresh empty HTML image element.
Now assign it's .src property the source of your gif:
this.image.src=document.getElementById("walk").src;
and set the CSS position property to absolute:
this.image.style="position:absolute;";
finally add this new image element to the body using:
document.body.appendChild(this.image);
If you hit run you will still not see any movement because there's still a little fix to do!
Find this line:
walkers[o].image.style.left = walkers[o].x;
and change it to this:
walkers[o].image.style.left = walkers[o].x + "px";
var walk, isWaveSpawned = true;
var walkers = [];
function start() {
walk = document.getElementById("walk");
draw(); //Animation function
}
function draw() {
if (isWaveSpawned) //Generate a wave of 5 "walkers"
{
isWaveSpawned = false;
for (var i = 0; i < 5; i++)
walkers.push(new createWalker());
}
for (var o = 0; o < walkers.length; o++) //Add 1px to x position after each frame
{
walkers[o].x += walkers[o].speed;
walkers[o].image.style.left = walkers[o].x + "px";
walkers[o].image.style.top = walkers[o].y + "px";
}
requestAnimationFrame(draw);
}
function createWalker() {
this.x = 0;
this.y = 100;
this.speed = 1;
this.image = document.createElement("img");
this.image.src = document.getElementById("walk").src;
this.image.style = "position:absolute;";
document.body.appendChild(this.image);
}
start();
<body>
<img id="walk" src="https://i.imgur.com/ArYIIjU.gif">
</body>
I am trying to resize my image with javascript.
First, I place the image on the canvas, so I can manipulate it.
I can make it smaller but the problem is I can't make it bigger with Scale transformation. To make it easy, I will insert my code here
<!DOCTYPE HTML>
<html>
<body>
<canvas id='canvas1'></canvas>
<hr>
<button id='read'>READ IMAGE</button>
<hr>
Scale <input type='range' value='1' min='0.25' max='2' step='0.25' id='scale'>
<br><button id='default2'>Default Scalling</button>
<hr/>
</body>
<script src='imagine.js'></script>
<script>
var canvas = document.getElementById('canvas1')
var obj = new pc(canvas)
obj.image2canvas("565043_553561101348179_1714194038_a.jpg")
var tes = new Array()
document.getElementById('read').addEventListener('click',function(){
tes = obj.image2read()
})
document.getElementById('scale').addEventListener('change',function(){
var scaleval = this.value
var xpos = 0
var ypos = 0
var xnow = 0
var ynow = 0
var objW = obj.width
var objH = obj.height
tesbackup = new Array()
for(var c=0; c<tes.length; c++){
temp = new Array()
for(var d=0; d<4; d++){
temp.push(255)
}
tesbackup.push(temp)
}
for(var i=0; i<tes.length; i++){
xpos = obj.i2x(i)
ypos = obj.i2y(i)
xnow = Math.round( (xpos)*(scaleval))
ynow = Math.round( (ypos)*(scaleval))
var idxnow = obj.xy2i(xnow,ynow)
tesbackup[idxnow][0] = tes[i][0]
tesbackup[idxnow][1] = tes[i][1]
tesbackup[idxnow][2] = tes[i][2]
}
obj.array2canvas(tesbackup)
})
</script>
And then for the script that used on that html file, is a js file named imagine.js.
imagine.js
function info(text){
console.info(text)
}
function pc(canvas){
this.canvas = canvas
this.context = this.canvas.getContext('2d')
this.width = 0
this.height = 0
this.imgsrc = ""
this.image2read = function(){
this.originalLakeImageData = this.context.getImageData(0,0, this.width, this.height)
this.resultArr = new Array()
this.tempArr = new Array()
this.tempCount = 0
for(var i=0; i<this.originalLakeImageData.data.length; i++){
this.tempCount++
this.tempArr.push(this.originalLakeImageData.data[i])
if(this.tempCount == 4){
this.resultArr.push(this.tempArr)
this.tempArr = []
this.tempCount = 0
}
}
info('image2read Success ('+this.imgsrc+') : '+this.width+'x'+this.height)
return this.resultArr
}
this.image2canvas = function(imgsrc){
var imageObj = new Image()
var parent = this
imageObj.onload = function() {
parent.canvas.width = imageObj.width
parent.canvas.height = imageObj.height
parent.context.drawImage(imageObj, 0, 0)
parent.width = imageObj.width
parent.height = imageObj.height
info('image2canvas Success ('+imgsrc+')')
}
imageObj.src = imgsrc
this.imgsrc = imgsrc
}
this.array2canvas = function(arr){
this.imageData = this.context.getImageData(0,0, this.width, this.height)
if(this.imageData.data.length != arr.length*4){
error("array2canvas Failed to Execute")
return false
}
for(var i = 0; i < arr.length; i++){
this.imageData.data[(i*4)] = arr[i][0]
this.imageData.data[(i*4)+1] = arr[i][1]
this.imageData.data[(i*4)+2] = arr[i][2]
this.imageData.data[(i*4)+3] = arr[i][3]
}
this.context.clearRect(0, 0, this.width, this.height)
this.context.putImageData(this.imageData, 0, 0)
info('Array2Canvas Success ('+this.imgsrc+')')
}
this.i2x = function(i){
return (i % this.width)
}
this.i2y = function(i){
return ((i - (i % this.width))/ this.width)
}
this.xy2i = function(x,y){
return (y * this.width) + (x)
}
}
I screenshot the output of the script, the image can be zoomed to a smaller image but can't be zoomed to a bigger image canvas
Original size of the image
Image size after I change the value to smaller value
But when I try to scroll it to a bigger value, the canvas get bigger but the images is disappeared. And I get the error "Cannot set property '0' of undefined".
Image size when I change the value to bigger value
Can someone point out what should I add or remove to get the image resize to bigger using this code??
Thanks in advance
I was trying to create an array of image objects and load the images after the windows has loaded in canvas.
Here is my code:
var canvasObj = document.getElementById('myCanvas');
var ctx = canvasObj.getContext('2d');
var imgsrcs = ["1.png", "2.png", "3.png"];
var imgs = [];
for(var i=0; i<imgsrcs.length; i++){
imgs[i] = new Image();
imgs[i].onload = function () {
ctx.drawImage(imgs[i], xb,yb);
}
imgs[i].src = imgsrcs[i];
}
however, I am getting this error in console:
TypeError: Argument 1 of CanvasRenderingContext2D.drawImage could not be converted to any of: HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, ImageBitmap.
ctx.drawImage(imgs[i], xb,yb);
What am I doing wrong?
Thanks in advance
By the time onload event is invoked, for-loop is iterated hence value of i is length+1, as there is no element at index length+1, undefined is passed as first argument for ctx.drawImage
Use this context in the drawImage method where this === Image-Object
var canvasObj = document.getElementById('myCanvas');
var ctx = canvasObj.getContext('2d');
var imgsrcs = ["http://i.imgur.com/gwlPu.jpg", "http://i.imgur.com/PWSOy.jpg", "http://i.imgur.com/6l6v2.png"];
var xb = 0,
yb = 0;
var imgs = [];
for (var i = 0; i < imgsrcs.length; i++) {
imgs[i] = new Image();
imgs[i].onload = function() {
console.log(imgs[i]); //Check this value
ctx.drawImage(this, xb, yb);
xb += 50;
yb += 50;
}
imgs[i].src = imgsrcs[i];
}
<canvas id="myCanvas"></canvas>
So I'm making a game in JavaScript and I'm trying to place "Sprites" I've defined inside an array.
This is what my Sprite object looks like
function Sprite(imgsrc)
{
this.x = 0;
this.y = 0;
this.velocity_xr = 0;
this.velocity_xl = 0;
this.velocity_yu = 0;
this.velocity_yd = 0;
this.velocity_x = 0;
this.velocity_y = 0;
this.IMG = new Image();
this.IMG.src = imgsrc;
this.visible = false;
}
So I've done this:
var buttons = [];
var b = new Sprite("https://i.imgur.com/qDH38qs.png");
buttons.push(b):
And then tried to draw it using this line, with no success.
ctx.drawImage(bullets[0].IMG,300,300);
However, this works:
ctx.drawImage(b.IMG,300,300);
What am I missing?