Is it possible to use ImageData array object to get an Image() object. My eventual goal is to use drawImage instead of putImageData since putImageData is too slow (from stackoverflow similar qs and my own tests). All I have is ImageData array that I want to draw on top of an existing image on a canvas .
You can create an ImageBitmap from an ImageData and pass that to drawImage().
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap
Something like:
const imgdata = ...;
const ctx = ...;
createImageBitmap(imgdata).then(function(imgBitmap) {
ctx.drawImage(imgBitmap, ...remaining args);
});
I was able to do this to scale some ImageData I had, since putImageData does not have arguments for scaling. Unfortunately, it looks like IE, Edge, and Safari do not support createImageBitmap().
It's worth mentioning that for my case (resizing the ImageData), createImageBitmap() does have extra options for resizing the resulting ImageBitmap on its own.
Related
i've just try to resize image in javascript before upload using canvas. I follow the instruction here: https://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/.
When I scale the image to 1, which mean, follow the original width and height, the output size of the image is almost double the size of original image. Before that, when I readDataAsURL using FileReader, the output string length is bigger than the image size. How to use html canvas and FileReader correctly?
Thank you.
You could consider using Blobs instead. Data-URI in the browser uses Base-64 encoding which increase the size by 33%, and some change in form of a data-uri header.
To use blobs instead you will need to have in mind that the code becomes asynchronous. Also, there are no guarantee that the resulting image is smaller than the original due to the simple fact that the exported image from the browser is always in RGBA format, while the original PNG source image can be indexed, gray-scale, RGB only, have better compression and so forth.
In the case of FileReader you can use the File object directly with createObjectURL() bypassing the use of FileReader. A File object is basically a Blob with some extended information such as file name etc.
Example Reading Blob/File wo/FileReader
This assumes the input field uses changeHandler below to handle the event (and this example only handles a single file):
function changeHandler() {
var img = new Image();
img.onload = drawImageToCanvas;
img.src = (URL || webkitURL).createObjectURL(this.files[0]);
}
function drawImageToCanvas() {
// modify canvas size here if needed
ctx.drawImage(this, 0, 0); // draw image to canvas
// since we're async., continue from here (or use promises)
}
Example Blob Export (toBlob)
Exporting using blob:
canvas.toBlob(function(blob) {
// blob now contains the PNG file
// This code is called asynchronous, so continue from here.
}, "image/png");
You can now upload the blob instead which will be smaller compared to a Data-URL.
Some browsers may need a polyfill for toBlob() (or simply do a feature detect and use toDataURL() as a fallback in those browsers).
I have a primary canvas element which I perform drawing operations on using the context. I can successfully draw images, shapes, and also transform those objects using the context.
I now need my own textbox. I want to create another canvas, render the text to that canvas, then copy that data onto the primary canvas... the catch is I want to have it transformable, almost is if I was just calling the drawImage function.
There exists the getImageData and putImageData methods, but those do not work because it does not take into consideration the transformation.
I am looking for something like this...
var tempcanvas = document.createElement("canvas");
var ctx = tempcanvas.getContext('2d');
ctx.fillRect(0,0,5,5);
then on my primary canvas which I already have, I would like to draw that as if it were an image object.
context = maincanvas.getContext('2d');
context.translate(50,50);
context.rotate(180);
context.drawImage(tempcanvas)
I am streaming video over a WebSocket by sending each frame in the raw ImageData format (4 bytes per pixel in RGBA order). When I receive each frame on the client (as an ArrayBuffer), I want to paint this image directly onto the canvas as efficiently as possible, using putImageData.
This is my current solution:
// buffer is an ArrayBuffer representing a properly-formatted image
var array = new Uint8ClampedArray(buffer);
var image = new ImageData(array, width, height);
canvas.putImageData(image, 0, 0);
But it is rather slow. My theories as to why:
the array (which is ~1MB in size) is being copied thrice, once into the Uint8ClampedArray, once into the ImageData, and lastly into the canvas, each frame (30 times per second).
I am using new twice for each frame, which may be a problem for the garbage collector.
Are these theories correct and if so, what tricks can I employ to make this as fast as possible? I am willing to accept an answer that is browser-specific.
No, both your ImageData image and your TypedArray array share the exact same buffer buffer.
These are just pointers, your original buffer is never "copied".
var ctx = document.createElement('canvas').getContext('2d');
var buffer = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height).data.buffer;
var array = new Uint8ClampedArray(buffer);
var image = new ImageData(array, ctx.canvas.width, ctx.canvas.height);
console.log(array.buffer === buffer && image.data.buffer === buffer);
For your processing time issue, the best way would be to simply send directly the video stream to a videoElement and use drawImage.
How to convert an Image(png) to byte code in Javascript. I've used this code but in IE8 there is no use in this code because there is no support of canvas element in IE8.
function getBase64Image(){
p=document.getElementById("fileUpload").value;
img1.setAttribute('src', p);
canvas.width = img1.width;
canvas.height = img1.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img1, 0, 0);
var dataURL = canvas.toDataURL("image/png");alert("from getbase64 function"+dataURL );
return dataURL;
}
Is any other way to get image byte code in IE8. I need either from Image to base64 byte code in a html page or from any image url base64 byte code.
My image url is like this is there any other way to get image byte code in javascript.
Simple answer is unfortunately you can't - out of the box.
As you say, IE8 does not support the canvas element so there is no way to extract the image data as bytes as you would need to go by the canvas and then use toDataURL or getImageData.
There are poly-fills for IE8 that allows you to use the basic functions such as excanvas. This however does not support pixel extraction as with the two above mentioned metods.
There are two work-arounds:
Use server: send image to server and process it there
Use Flash-based canvas "poly-fills" which allow you to do this.
For the latter point there are a few options such as this one:
http://flashcanvas.net/
I want to do pixel-true rendering of some images on my Canvas. Right now, I obtain the images through Javascript, so my images are HTMLImageElement instances. I can draw these on the Canvas' rendering context with drawImage. However, this performs anti-aliasing on the image, which I don't want.
There appears to be a lower-level image manipulation method named putImageData, operating on ImageData objects. Does this method perform any anti-aliasing? If not, it's a fine candidate for what I'm looking for, but I haven't found out how I can convert or blit an HTMLImageElement to an ImageData instance.
Any advice would be welcome!
Edit: my original problem was solved, I accidentally had a coordinate that was fractional, which forces anti-aliasing. The conversion-to-image-data question still stands though.
The only way to convert an image into an ImageData object is to draw it to a canvas first, so you'll need to create a temporary canvas, draw the image on it, and get the image data from there.
function imageToImageData(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0);
return ctx.getImageData(0, 0, canvas.width, canvas.height);
}
Note though, that the same-origin policy prevents you from calling getImageData if you draw an image from a different domain to the canvas, so this will only work on images from the same domain as the document. If you need to draw images from other domains, your only option is to call drawImage on the context for you main canvas directly, making sure there are no transformations that will affect the accuracy.