Javascript Canvas takes too much CPU - javascript

Heyo, before asking a question I have to admit that javascript hasnt been to kind to me and would ask to not throw too many rocks at me for this question.
So I am writing a canvas based player with live video but the page where canvas is being executed consumes and insane amount of CPU power.
This is the routine that draws on the given canvas(player is the canvas that was passed)
var requestFrames = function(player) {
console.log('Requesting frames for videoId ' + requestStream.videoId);
//var imageElement = player;
var ctx = player.getContext("2d");
var displayImage = function(frame) {
if (frame && frame.imageURL) {
var img = new Image();
img.src = frame.imageURL;
img.onload = function(){
ctx.drawImage(img, 0,0)
};
}
sendFrameRequest(requestStream.videoId, displayImage);
};
sendFrameRequest(requestStream.videoId, displayImage);
};
Please send help, thanks
EDIT : sendFrameRequest is a function that requests latest image from the server. I am working with a server that sends out live images from cameras(Its a video management system)

Related

Image won't stop flickering on refresh

I've looked through and tried many solutions to this issue and nothing has worked. I have an image on a website that needs to be updated 10-30x a second (live video feed) so I have the javascript request the image every 100ms. When the image stays the same, no flickering. When the image changes, I see flickering on the image for 2-3 seconds.
function initImg() {
var canvas = document.getElementById("diagimg");
var context = canvas.getContext("2d");
img = new Image();
img.onload = function() {
var scale = .73;
canvas.setAttribute("width", 640*scale);
canvas.setAttribute("height", 480*scale);
context.scale(scale, scale); //scale it to correct size
context.drawImage(this, 0, 0);
}
img.onerror = function() {
img.src="images/wait.jpeg"; //if error during loading, display this image
}
refreshImg();
}
function refreshImg() {
img.src = "images/IMAGE.png?time="+new Date().getTime();
window.setTimeout("refreshImg()", 100);
}
initImg();
I've turned your code into an example to test this behaviour, but I don't see any flickering at all.
Is it possible that the flickering is caused by server-side code?
let images = [
'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Mercury_in_color_-_Prockter07-edit1.jpg/220px-Mercury_in_color_-_Prockter07-edit1.jpg',
'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/PIA23791-Venus-NewlyProcessedView-20200608.jpg/220px-PIA23791-Venus-NewlyProcessedView-20200608.jpg',
'https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/The_Earth_seen_from_Apollo_17.jpg/220px-The_Earth_seen_from_Apollo_17.jpg',
'https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/OSIRIS_Mars_true_color.jpg/220px-OSIRIS_Mars_true_color.jpg'
];
let i = 0;
function getImage() {
i++;
if (i >= images.length)
i = 0;
return images[i];
}
//--------------------------------------
function initImg() {
var canvas = document.getElementById("diagimg");
var context = canvas.getContext("2d");
img = new Image();
img.onload = function() {
var scale = .73;
canvas.setAttribute("width", 640 * scale);
canvas.setAttribute("height", 480 * scale);
context.scale(scale, scale); //scale it to correct size
context.drawImage(this, 0, 0);
}
refreshImg();
}
function refreshImg() {
img.src = getImage() + "?time=" + new Date().getTime();
window.setTimeout("refreshImg()", 500);
}
initImg();
<canvas id="diagimg" />
Fixed the problem - turned out to be that I was trying to write an image at the same time that it was being read.
Quick summary of my setup: websocket connection between website and java program, the image being loaded onto the webpage is constantly being overwritten by an external program.
The fix was to have the website request the websocket server to copy the image. The server (java program) copies the image, checks if the copy is equal to the original, and sends a message to the website that the image is ready to be read. The device ID is also appended to the filepath so that each connected device (each instance of the website open) has its own image that will only be changed when it requests an update (it requests a new image once it's done loading).
This means that images are only overwritten when the client requests them, and the client only reads them when the java websocket says that it's done being copied.
I'm sure it's inefficient but it only needs to refresh at 10hz and the entire process only takes about 10ms on its own thread, so doesn't really matter.

Execute Function After Canvas toDataURL() Function is Complete

I'm converting images to base64 using canvas. What i need to do is convert those images and then show the result to the user (original image and base64 version). Everything works as expected with small images, but when i try to convert large images (>3MB) and the conversion time increases, the base64 version is empty.
This might be is caused because the result is shown before the toDataURL() function is completed.
I need to show the result after all the needed processing has ended, for testing purposes.
Here's my code:
var convertToBase64 = function(url, callback)
{
var image = new Image();
image.onload = function ()
{
//create canvas and draw image...
var imageData = canvas.toDataURL('image/png');
callback(imageData);
};
image.src = url;
};
convertToBase64('img/circle.png', function(imageData)
{
window.open(imageData);
});
Even though i'm using image.onload() with a callback, i'm unable to show the result after the toDataURL() has been processed.
What am i doing wrong?
UPDATE: I tried both the solutions below and they didn't work. I'm using AngularJS and Electron in this project. Any way i can force the code to be synchronous? Or maybe some solution using Promises?
UPDATE #2: #Kaiido pointed out that toDataURL() is in fact synchronous and this issue is more likely due to maximum URI length. Since i'm using Electron and the image preview was for testing purposes only, i'm going to save the file in a folder and analise it from there.
Your code seems absolutely fine. Not sure why isn't working you. Maybe, there are some issues with your browser. Perhaps try using a different one. Also you could use a custom event, which gets triggered when the image conversion is competed.
// using jQuery for custom event
function convertToBase64(url) {
var image = new Image();
image.src = url;
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = canvas.toDataURL();
$(document).trigger('conversionCompleted', imageData);
};
};
convertToBase64('4mb.jpg');
$(document).on('conversionCompleted', function(e, d) {
window.open(d);
});
This approach might work for you. It shows the image onscreen using the native html element, then draws it to a canvas, then converts the canvas to Base64, then clears the canvas and draws the converted image onto the canvas. You can then scroll between the top image (original) and the bottom image (converted). I tried it on large images and it takes a second or two for the second image to draw but it seems to work...
Html is here:
<img id="imageID">
<canvas id="myCanvas" style="width:400;height:400;">
</canvas>
Script is here:
var ctx;
function convertToBase64(url, callback)
{
var image = document.getElementById("imageID");
image.onload = function() {
var canvas = document.getElementById("myCanvas");
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx = canvas.getContext("2d");
ctx.drawImage(image,0,0);
var imageData = canvas.toDataURL('image/png');
ctx.fillStyle ="#FFFFFF";
ctx.fillRect(0,0,canvas.width,canvas.height);
callback(imageData);
};
image.src = url;
};
var imagename = 'images/bigfiletest.jpg';
window.onload = function () {
convertToBase64(imagename, function(imageData) {
var myImage = new Image();
myImage.src = imageData;
ctx.drawImage(myImage,0,0);
});
}
Note that I also tried it without the callback and it worked fine as well...

Saving an image for offline use in a Chrome App

I have an image that is being shown in a Chrome App and is from a remote site. I want to be able to save the image locally in case network connection is unavailable.
I've been researching and found some APIs that might help me such as chrome.fileSystem, however, there aren't any simple examples like this.
Would someone be able to provide me with a simple example on how to do this?
It is preferred if the user doesn't have to press save or anything, having the downloading happen in the background. The image changes at random so I need this to be automated if possible.
what about storing it in localStorage?
var image = document.getElementById('bannerImg');
imgData = getBase64Image(image);
localStorage.setItem("imgData", imgData);
then to restore (adapted from this answer):
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;

Fetching image from url with javascript

I am trying to show an image on my page from a different url.
<body>
<div id="container">
<br />
<canvas width="500px" height="375px" id="canvas">
</canvas>
<img src="http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png" />
</div>
<script>
var img = new Image;
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png";
var timer = setInterval(function () { MyTimer() }, 200);
function MyTimer() {
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0,500,675);
img = new Image;
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png";
}
</script>
The image on the other site is being saved every 1.5 seconds.
The result is that I cant view the image.
Any ideas why?
Thanks!
1. Cache issue
Your MyPicture.png returns Cache-Control: max-age=31536000 in HTTP response. So browser may get image from its cache on second time. You need to add query string something like thie:
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png?time=" + (new Date()).getTime();
2. Too short fetching period.
I think fetching period 200msec is too short. It's better to bind onload event handler to the image object. See How to fetch a remote image to display in a canvas?.
function copyCanvas(img) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
}
function loadImage() {
var img = new Image();
img.onload = function () {
copyCanvas(img);
};
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png?time=" + (new Date()).getTime();
}
3. Double buffering
I think your script intend to pre-load image. So it's better to make a double buffering.
Single Buffering version: http://jsfiddle.net/tokkonoPapa/dSJmy/1/
Double Buffering version: http://jsfiddle.net/tokkonoPapa/dSJmy/2/
You have not defined canvas. Define it first with:
var canvas = document.getElementById('canvas');
Then, use load event to draw image on to the canvas.
Checkout the fiddle, LoadImgURL which demonstrates the whole process.

Display Image using canvas in JavaScript/jQuery

I have the following code :
function createImage(source) {
var pastedImage = new Image();
pastedImage.onload = function() {
document.write('<br><br><br>Image: <img src="'+pastedImage.src+'" height="700" width="700"/>');
}
pastedImage.src = source;
}
Here I am displaying the image through html image tag which I wrote in document.write and provide appropriate height and width to image.
My question is can it possible to displaying image into the canvas instead of html img tag? So that I can drag and crop that image as I want?
But how can I display it in canvas?
Further I want to implement save that image using PHP but for now let me know about previous issue.
Try This
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image(); // Create new img element
img.onload = function(){
// execute drawImage statements here This is essential as it waits till image is loaded before drawing it.
ctx.drawImage(img , 0, 0);
};
img.src = 'myImage.png'; // Set source path
Make sure the image is hosted in same domain as your site. Read this for Javascript Security Restrictions Same Origin Policy.
E.g. If your site is http://example.com/
then the Image should be hosted on http://example.com/../myImage.png
if you try http://facebook.com/..image/ or something then it will throw security error.
Use
CanvasRenderingContext2D.drawImage.
function createImage(source) {
var ctx = document.getElementById('canvas').getContext('2d');
var pastedImage = new Image();
pastedImage.onload = function(){
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage = source;
}
Also MDN seems to be have nice examples.

Categories