HTML5 canvas - Only draw image differences? - performance

I'm receiving images via a websocket in base64 format and then drawing the images on a canvas using:
var img=new Image();
img.onload = function() {
cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
};
img.src = "data:image/jpeg;base64,"+imgData;
Is it possible to change this code and somehow only draw the pixels that have changed? And if it is possible, would this even increase the performance? Thanks for the help. :)

What would be more efficient first would be to only send/receive images deltas ( what has changed) between images, then draw that on your canvas.

Related

How to draw Images canvas at faster rate from websocket onmessageevent

I have written a websocket implementation for image transfer from server to javascript client.
In the client side on the event this.webSocket.onmessage we are receiving a png image as base64 and we write as below to display.
if (bIsPngFormat) {
// Draw the image onto canvas using image.onload event
var myImage = new Image();
myImage.onload = () => {
this.ctx.drawImage(myImage, 0, 0);
}
myImage.src = "data:image/png;base64," + renderableImage
}
But the display is not refreshing even through the event is fired at the rate of 90 frames/sec
Just want to know why canvas is not getting refreshed with new incoming image when it comes very fast.
Will it work better when used canvas with openGL context or directly send the RGBA buffer (instead of base64 png) and rendered using below code
Code:
// Apply the uint8array buffer received from websocket onmessage
var iData = new ImageData(new Uint8ClampedArray(renderableImage), width, height);
this.ctx.putImageData(iData, 0, 0);"
Thanks in advance.

How to get base64 image data without call canvas toDataURL?

I'm on a project which requires to support ie9 or ie10.
I'm using d3.js for data visualization.
Now I need to provide a function to export the chart as pdf.
I have been investigate into possible solutions. It seems that canvas + jsPdf is the way to go, below is some code I write.
But the problem is that when toDataURL gets called, it will cause security errors on IE9 and IE10. So I'm wondering if there's some work around to get base64 image data without using canvas since jsPdf only needs base64 image data???
createObjectURL to the root svg element
svgElement = $('svg').get(0);
serializer = new XMLSerializer();
str = serializer.serializeToString(svgElement);
DOMURL = window.URL || window.webkitURL || window;
url = DOMURL.createObjectURL(new Blob([str], {type: 'image/svg+xml;charset=utf-8'}));
draw an image using canvas
img = new Image();
img.onload = function(){
ctx.drawImage(img, 0, 0);
imgData = $canvas.get(0).toDataURL("image/jpeg");
DOMURL.revokeObjectURL(url);
pdf = new jsPDF('landscape', 'pt', 1000, 800);
pdf.addImage(imgData, 'JPEG', 0, 0);
pdf.save('download.pdf');
};
img.src = url;
I finally find the solution which is to use an open source project: canvg

HTML5 canvas, scale image after drawing it

I'm trying to scale an image that has already been draw into canvas.
This is the code:
var canvas = document.getElementById('splash-container');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// draw image at its original size
context.drawImage(imageObj, 0, 0);
};
imageObj.src = 'images/mine.jpeg';
// Now let's scale the image.
// something like...
imageObj.scale(0.3, 0.3);
How should I do?
You're thinking about it wrong. Once you've drawn the image onto the canvas it has no relationship to the imageObj object. Nothing you do to imageObj will affect what's already drawn. If you want to scale the image, do in the drawImage function:
drawImage(imgObj, 0, 0, imgObj.width * 0.3, imgObj.height * 0.3)
If you want to animate the scaling or are looking to achieve some other effect which requires you to draw the image at full size initially you'll have to first clear it before drawing the scaled down image.
What robertc says is correct, but if you really wanted to scale an image on a canvas after drawing it for some reason, you could just scale the whole canvas using the CSS width/height properties and that would scale the image without having to redraw it.

Can we get the real image size through the canvas?

In image tag, if we don't supply width and height property, we will get nothing when retrieving the width and the height of the image. I am using the canvas element to load an image and scale it proportionally. In order to do this, I have to get the actual image size. Is it possible to do that in html 5?
The HTMLImageElement has two properties for this, naturalWidth and naturalHeight. Use those.
As in:
var img = new Image();
img.addEventListener('load', function() {
// once the image is loaded:
var width = img.naturalWidth; // this will be 300
var height = img.naturalHeight; // this will be 400
someContext.drawImage(img, 0, 0, width, height);
}, false);
img.src = 'http://placekitten.com/300/400'; // grab a 300x400 image from placekitten
It is wise to set source only after the event listener is defined, see Phrogz's exploration on that here: Should setting an image src to data URL be available immediately?
You cannot retrieve width/height before image has been loaded.
Try something like:
// create new Image or get it right from DOM,
// var img = document.getElementById("myImage");
var img = new Image();
img.onload = function() {
// this.width contains image width
// this.height contains image height
}
img.src = "image.png";
Anyhow onload will not fire if image has been loaded before script execution. Eventually you can embed script in html <img src="test.jpg" onload="something()">
if I understand you correctly, you can use the getComputedStyle method.
var object = document.getElementById(el);
var computedHeight = document.defaultView.getComputedStyle(object, "").getPropertyValue("width");
Not fully understood your question.
But you can use javascript to get the width and height of the image.
and then pass it into
/ Five arguments: the element, destination (x,y) coordinates, and destination
// width and height (if you want to resize the source image).
context.drawImage(img_elem, dx, dy, dw, dh);
while drawing image on canvas.
or check this if it helps
http://jsfiddle.net/jjUHs/

html5: copy a canvas to image and back

I implemented a zoom in and out function on a canvas element.
it works by scaling the canvas, translating it, and then redraw the whole scene again.
the problem is that it takes a lot of time to redraw everything because i got a lot of things on my canvas.
I need a way to copy the canvas to an image object and than copy the image back to the canvas without loosing quality. what are the specific methods to copy canvas to a javascript variable, and to to copy this variable back to the canvas later?
I'll be glad if you write down the code because I couldn't find any good explanation over the internet.
thanks,
The drawImage() method can draw to a canvas using another canvas instead of an image.
You could create a 'backup' canvas, of the same size as your original, draw the first one to there and then draw that one back to the original when you need it.
e.g.
// Assume we have a main canvas
// canvas = <main canvas>
ctx = canvas.getContext('2d');
..
// create backing canvas
var backCanvas = document.createElement('canvas');
backCanvas.width = canvas.width;
backCanvas.height = canvas.height;
var backCtx = backCanvas.getContext('2d');
// save main canvas contents
backCtx.drawImage(canvas, 0,0);
..
// restore main canvas
ctx.drawImage(backCanvas, 0,0);
There are a few ways to do it theres the getImageData and putImageData methods Reference, However putImageData and getImageData are pretty slow. Another way is to save the data to an image in memory and recall it from that which is much faster, then the third way is the one above mentioned by andrewmu which involves copying to another canvas element. I have included examples for the first and second type.
Image in memory method
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
savedData = new Image();
function save(){
// get the data
savedData.src = canvas.toDataURL("image/png");
}
function restore(){
// restore the old canvas
ctx.drawImage(savedData,0,0)
}
getImageData putImageData method
// Setup our vars, make a new image to store the canvas data
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
canvasData = '';
function save(){
// get the data
canvasData = ctx.getImageData(0, 0, 100, 100);
}
function restore(){
// restore the old canvas
ctx.putImageData(canvasData, 0, 0);
}
added image into canvas
var image = new Image();
image.src = "1.jpg";
image.onload = function () {
context.drawImage(image, 0, 0);
};

Resources