I want to convert my s3 image link into a file object using JavaScript.
I've found out how to do this with an image URI but wasn't able to figure out how to convert the image URL into a URI. Once I do this I could convert it into a file object
Heres the image link:
http://s3.us-east-2.amazonaws.com/rentpop/298%2F2014-mclaren-650s-Spyder-Tarocco-Orange-2.jpg
Source for this code
function getDataUri(url, callback) {
var image = new Image();
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
canvas.getContext('2d').drawImage(this, 0, 0);
// Get raw image data
callback(canvas.toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, ''));
// ... or get as Data URI
callback(canvas.toDataURL('image/png'));
};
image.src = url;
}
// Usage
getDataUri('local_location_to_image.extension', function(dataUri) {
// Do whatever you'd like with the Data URI!
});
I have a regular HTML page with some images (just regular <img /> HTML tags). I'd like to get their content, base64 encoded preferably, without the need to redownload the image (ie. it's already loaded by the browser, so now I want the content).
I'd love to achieve that with Greasemonkey and Firefox.
Note: This only works if the image is from the same domain as the page, or has the crossOrigin="anonymous" attribute and the server supports CORS. It's also not going to give you the original file, but a re-encoded version. If you need the result to be identical to the original, see Kaiido's answer.
You will need to create a canvas element with the correct dimensions and copy the image data with the drawImage function. Then you can use the toDataURL function to get a data: url that has the base-64 encoded image. Note that the image must be fully loaded, or you'll just get back an empty (black, transparent) image.
It would be something like this. I've never written a Greasemonkey script, so you might need to adjust the code to run in that environment.
function getBase64Image(img) {
// Create an empty canvas element
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// Copy the image contents to the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Get the data-URL formatted image
// Firefox supports PNG and JPEG. You could check img.src to
// guess the original format, but be aware the using "image/jpg"
// will re-encode the image.
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
Getting a JPEG-formatted image doesn't work on older versions (around 3.5) of Firefox, so if you want to support that, you'll need to check the compatibility. If the encoding is not supported, it will default to "image/png".
This Function takes the URL then returns the image BASE64
function getBase64FromImageUrl(url) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width =this.width;
canvas.height =this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
};
img.src = url;
}
Call it like this :
getBase64FromImageUrl("images/slbltxt.png")
Coming long after, but none of the answers here are entirely correct.
When drawn on a canvas, the passed image is uncompressed + all pre-multiplied.
When exported, its uncompressed or recompressed with a different algorithm, and un-multiplied.
All browsers and devices will have different rounding errors happening in this process
(see Canvas fingerprinting).
So if one wants a base64 version of an image file, they have to request it again (most of the time it will come from cache) but this time as a Blob.
Then you can use a FileReader to read it either as an ArrayBuffer, or as a dataURL.
function toDataURL(url, callback){
var xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.responseType = 'blob';
xhr.onload = function(){
var fr = new FileReader();
fr.onload = function(){
callback(this.result);
};
fr.readAsDataURL(xhr.response); // async call
};
xhr.send();
}
toDataURL(myImage.src, function(dataURL){
result.src = dataURL;
// now just to show that passing to a canvas doesn't hold the same results
var canvas = document.createElement('canvas');
canvas.width = myImage.naturalWidth;
canvas.height = myImage.naturalHeight;
canvas.getContext('2d').drawImage(myImage, 0,0);
console.log(canvas.toDataURL() === dataURL); // false - not same data
});
<img id="myImage" src="https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png" crossOrigin="anonymous">
<img id="result">
A more modern version of kaiido's answer using fetch would be:
function toObjectUrl(url) {
return fetch(url)
.then((response)=> {
return response.blob();
})
.then(blob=> {
return URL.createObjectURL(blob);
});
}
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Edit: As pointed out in the comments this will return an object url which points to a file in your local system instead of an actual DataURL so depending on your use case this might not be what you need.
You can look at the following answer to use fetch and an actual dataURL: https://stackoverflow.com/a/50463054/599602
shiv / shim / sham
If your image(s) are already loaded (or not), this "tool" may come in handy:
Object.defineProperty
(
HTMLImageElement.prototype,'toDataURL',
{enumerable:false,configurable:false,writable:false,value:function(m,q)
{
let c=document.createElement('canvas');
c.width=this.naturalWidth; c.height=this.naturalHeight;
c.getContext('2d').drawImage(this,0,0); return c.toDataURL(m,q);
}}
);
.. but why?
This has the advantage of using the "already loaded" image data, so no extra request is needed. Additionally it lets the end-user (programmer like you) decide the CORS and/or mime-type and quality -OR- you can leave out these arguments/parameters as described in the MDN specification here.
If you have this JS loaded (prior to when it's needed), then converting to dataURL is as simple as:
examples
HTML
<img src="/yo.jpg" onload="console.log(this.toDataURL('image/jpeg'))">
JS
console.log(document.getElementById("someImgID").toDataURL());
GPU fingerprinting
If you are concerned about the "preciseness" of the bits then you can alter this tool to suit your needs as provided by #Kaiido's answer.
its 2022, I prefer to use modern createImageBitmap() instead of onload event.
*note: image should be same origin or CORS enabled
async function imageToDataURL(imageUrl) {
let img = await fetch(imageUrl);
img = await img.blob();
let bitmap = await createImageBitmap(img);
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = bitmap.width;
canvas.height = bitmap.height;
ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
return canvas.toDataURL("image/png");
// image compression?
// return canvas.toDataURL("image/png", 0.9);
};
(async() => {
let dataUrl = await imageToDataURL('https://en.wikipedia.org/static/images/project-logos/enwiki.png')
wikiImg.src = dataUrl;
console.log(dataUrl)
})();
<img id="wikiImg">
Use onload event to convert image after loading
function loaded(img) {
let c = document.createElement('canvas')
c.getContext('2d').drawImage(img, 0, 0)
msg.innerText= c.toDataURL();
}
pre { word-wrap: break-word; width: 500px; white-space: pre-wrap; }
<img onload="loaded(this)" src="https://cors-anywhere.herokuapp.com/http://lorempixel.com/200/140" crossorigin="anonymous"/>
<pre id="msg"></pre>
This is all you need to read.
https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString
var height = 200;
var width = 200;
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
ctx.strokeStyle = '#090';
ctx.beginPath();
ctx.arc(width/2, height/2, width/2 - width/10, 0, Math.PI*2);
ctx.stroke();
canvas.toBlob(function (blob) {
//consider blob is your file object
var reader = new FileReader();
reader.onload = function () {
console.log(reader.result);
}
reader.readAsBinaryString(blob);
});
In HTML5 better use this:
{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
Earlier this day, I have succeed in converting SVG file to JPEG using javascript. The main steps are:
Get SVG image from a url
Add image to HTML5 Canvas
Convert the Canvas to JPEG encoded in base64
I replicate the getImageFromUrl function on jsPDF-master to achieve this.
var getImageFromUrl = function (url, callback) {
var img = new Image,
data, ret = {
data: null,
pending: true
};
img.onError = function () {
throw new Error('Cannot load image: "' + url + '"');
}
img.onload = function () {
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// Grab the image as a jpeg encoded in base64, but only the data
data = canvas.toDataURL('image/jpeg').slice('data:image/jpeg;base64,'.length);
// Convert the data to binary form
data = atob(data)
document.body.removeChild(canvas);
ret['data'] = data;
ret['pending'] = false;
if (typeof callback === 'function') {
callback(data);
}
}
img.src = url;
return ret;
}
From that function, the image to be converted is actually a file. In my case, I don't have a file but only the raw code (text when you open a SVG file with text editor).
My question is:
How do you add raw code of a SVG file into the HTML canvas? Is this process also have .onload event attribute like image object?
Thank you
You can convert a "raw" (inline) SVG to image by converting it to a Blob and then use that as an image source:
function drawInlineSVG(ctx, rawSVG, callback) {
var
/// create Blob of inlined SVG
svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
/// create URL (handle prefixed version)
domURL = self.URL || self.webkitURL || self,
url = domURL.createObjectURL(svg),
/// create Image
img = new Image;
/// handle image loading
img.onload = function () {
/// draw SVG to canvas
ctx.drawImage(this, 0, 0);
domURL.revokeObjectURL(url);
callback(this);
};
img.src = url;
}
Then call it like this:
var rawSVG = '<svg ... >';
drawInlineSVG(ctx, rawSVG, function(img) {
console.log('done!');
});
An error handler should of course be included for production code (not shown here).
Important to note: You cannot draw inline SVG's if they contain external references (CSS styles, images and so on). This is due to browser's security policies. You would have to convert all external references to inline data (ie. images to data-uris and so on).
I made a script which takes an image from a form input and prepares it to be put in javascript localstorage. The script is below:
bannerImage = document.getElementById('image');
imgData = getBase64Image(bannerImage);
function getBase64Image(img) {
// Create an empty canvas element
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// Copy the image contents to the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Get the data-URL formatted image
// Firefox supports PNG and JPEG. You could check img.src to guess the
// original format, but be aware the using "image/jpg" will re-encode the image.
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
// Create new JSON entry
var json_entry = {'title': titleField.val(),
'image': imgData,
'content': contentField.val(),
'location': location};
The problem is that I get an error when i submit the form:
[Error] TypeError: Type error
getBase64Image (script.js, line 138)
submitForm (script.js, line 128)
dispatch (jquery.min.js, line 3)
i (jquery.min.js, line 3)
The line from the error is ctx.drawImage(img, 0, 0);
what am I doing wrong?
I'm making an plugin(add-on) to upload image on any page.
I only can get the url of the image, but I want to get the image data or local cache of image.
by javascript on chrome or firefox.
I did it in my extension via canvas.
I created two functions. First getting image data from canvas using "toDataURL()" method (Returns the content of the current canvas as an image that you can use as a source for another canvas or an HTML element (such as img)), and then using this data to get BLOB object.
function getImageDataURL(url) {
var data, canvas, ctx, blob;
var img = new Image();
img.onload = function() {
canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
try {
data = canvas.toDataURL();
blob = dataURIToBlob(data);
} catch(e) {
// Handle errors here
alert(e);
}
};
img.src = url;
};
function dataURIToBlob (dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ab = [];
for (var i = 0; i < byteString.length; i++)
ab.push(byteString.charCodeAt(i));
return new Blob([new Uint8Array(ab)], { type: mimeString });
};
Here in the "blob" variable we have BLOB object with full image data.
You could use indexeDB (internal browser data base) that takes objets to store instead of URL. See Google dev tutorials for detailled use.