Blob URL to image - javascript

How can I "save" this image?
blob:https%3A//theta360.com/473c6400-b8e7-4c41-8f7a-90f03cbc8787
found on: https://theta360.com/s/lE2in9qQDK6j2CcjPAQcvNhOi
I tried some script I found on SO which uses canvas.toDataURL
But I get an error:
Not allowed to load local resource: blob:https%3A//theta360.com/473c6400-b8e7-4c41-8f7a-90f03cbc8787
Javascript:
var url = "blob:https%3A//theta360.com/473c6400-b8e7-4c41-8f7a-90f03cbc8787"; // document.getElementById("img1").src; // 'img1' is the thumbnail - I had to put an id on it
var canvas = document.getElementById("MyCanvas");
var img = new Image();
img.src = url;
img.onload = function () {
var myImage = canvas.toDataURL("image/jpg");
document.getElementById("dataurl").value = myImage;
}
HTML:
<canvas id="MyCanvas">This browser or document mode doesn't support canvas</canvas>
<input id="dataurl" name="dataurl" type="text" size="50" />

It is not possible to request a URL created by URL.createObjectURL() from a different origin. objectURL exists within the window that created it for the lifetime of the document that created it.
URL.createObjectURL()
The URL.createObjectURL() static method creates a DOMString
containing an URL representing the object given in parameter. The URL
lifetime is tied to the document in the window on which it was
created. The new object URL represents the specified File object or
Blob object.

I found how to get the image but this does not has anything to do with programming anymore.
Look in Chrome's cache with chrome://cache/and do a search for equirectangular_web_optimized

i did this way to get the props sizes of an BLOB Url (file.localDataUrl)
const img = new Image();
img.src = file.localDataUrl;
img.onload = (a) => {
console.log(a);
console.log([a.path[0].width, a.path[0].height]);
};

Related

How to Convert image URL from server (API / ImageURL) to Base64 in Vue.Js

A lot of reference I see about this problem is about upload file and convert to base64 but in my case I want to convert an Image URL from server and convert it to base64 but I still failed to do it, right now I tried it like this, but it still failed since it doesn't show anything
this is my html:
<div v-if="questionData">
<img class="img-preview-download" :src="questionData.image_url? getBase64Image(questionData.image_url) : 'https://via.placeholder.com/640x360'" alt="img-preview">
</div>
this is my method:
getBase64Image(img) {
console.log("cek base64 : ", btoa(img));
return `data:image/jpeg;base64,${btoa(img)}`;
},
I read some using file reader but isn't it only for file when you upload a data using input? can someone help me to solve this? I'm using Vue.Js for the framework
when I used this method I got result like this:
So this is my answer for my future self, who might be forget and stumble again in this problem!
You can solve it by making a new image and inside that image file, you can add your src so the image can be process when still loading or onload.
Remember!
Since it is you, You might be remove the last image.src = url to get a clean code, but this is important, if you remove that line, image.onload will not be trigger because it will search for the image source. and if you try to use image.srcObject to put it with mediaStream it will give you Resolution Overloaded since you still not find the answer for this problem, it is okay, you can use the image first since your step is to achieve how to get file from Image URL. so this is the method you use to solve this problem:
downloadPreview() {
const el = this.$refs.printMe;
const options = {
type: 'dataURL'
};
this.$html2canvas(el, options).then(data => {
this.output = data;
const a = document.createElement('a');
a.style.display = 'none';
a.href = data;
// this is just optional function to download your file
a.download = `name.jpeg`;
document.body.appendChild(a);
a.click();
});
},
convertImgUrlToBase64(url) {
let self = this;
var image = new Image();
image.setAttribute('crossOrigin', 'anonymous'); // use it if you try in a different origin of your web
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext('2d').drawImage(this, 0, 0);
canvas.toBlob(
function(source) {
var newImg = document.createElement("img"),
url = URL.createObjectURL(source);
newImg.onload = function() {
// no longer need to read the blob so it's revoked
URL.revokeObjectURL(url);
};
newImg.src = url;
},
"image/jpeg",
1
);
// If you ever stumble at 18 DOM Exception, just use this code to fix it
// let dataUrl = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
let dataUrl = canvas.toDataURL("image/jpeg");
console.log("cek inside url : ", url);
if(url === backgroundImg) {
self.assignImageBase64Background(dataUrl);
} else {
self.assignImageBase64(dataUrl);
}
};
image.src = url;
},
assignImageBase64(img) {
this.imgBase64 = img;
},
just for information, I use this library to change the div into image file:
vue-html2canvas
Notes:
If you ever wondering why I give self.assignImageBase64(dataUrl); this function in the end, this is because I still wondering how onload works, and how to return Base64 url to the parent thats why I just assign it again in another function since it easier to do.

PreloadJS loaded image, but I cannot insert it to DOM

I'm trying to preload one image using PreloadJS, then insert it to DOM a twice. But I can insert only one image.
var queue = new createjs.LoadQueue();
queue.addEventListener('complete', onComplete);
queue.loadManifest([{
id: 'img',
type: 'image',
src: 'https://i.imgur.com/adSrF00g.png',
}, ]);
queue.load();
function onComplete(event) {
var img = queue.getResult('img');
var imgSrc = img.src;
// this code inserts image to the DOM but 404 not found error appears in console
document.getElementById('game').innerHTML = `<img src="${imgSrc}" />`;
// this code do the same thing and 404 also appears
var DOM_img = document.createElement("img");
DOM_img.src = imgSrc;
document.getElementById('game').appendChild(DOM_img);
// this code insert the image to the DOM succesfully
document.getElementById('game').appendChild(img);
// but the last line does nothing - the img tag does not appear in the DOM and nothing error in the console
document.getElementById('game').appendChild(img);
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>
Screenshot: https://i.imgur.com/VQwAABM.jpg
I cannot understand why only one image appears. What I'am doing wrong? And how can I insert an image a twice? Thanks!
This is easy to fix, but first I want to explain you something.
What are Blob URLs or Object-URLs?
Blob URL/Object URL are a pseudo protocol to allow Blob and File objects to be used as URL source for things like images, download links for binary data and so forth.
In your case, If you try to open this src="blob:https://yada.yada" blob url that is the src of a loaded image it will give you an error and it can't be opened.
Yeah, I know that Teo, but Why if is working with the src tag how it is possible?
Well, Blob URLs can only be generated internally by the browser. So those elements have a special reference to the Blob or File object. These URLs can only be used locally in the single instance of the browser and in the same session (i.e. the life of the page/document).
So in this case the src="blob:https://yada.yada" is linked to the img tag created by the LoadQueue object.
Then, how can I use the same image in multiples elements?
In the LoadQueue docummentation that we can get a Blob object using the getResult() method. So, instead to reuse the Blob URL we can "clone" the Blob object. According to the documentation the getResult (value, [rawResult=false]) methods was overwritten to receive this rawResult optional parameter. If this parameter is true the method will returns a raw result as a Blob object, instead of a formatted result. If there is no raw result, the formatted result will be returned instead.
OK, but how can I use this blob in a <img> element?
Well, we can use URL.createObjectURL() method. This method creates a DOMString containing a new Blob URL representing the Blob object given in the parameter.
As I explained above, this Blob URL lifetime is tied to the document in the window on which it was created.
Here is the implementation:
let queue = new createjs.LoadQueue();
queue.addEventListener('complete', onComplete);
queue.loadManifest([{
id: 'sprite',
type: 'image',
src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, ]);
queue.load();
function onComplete(event) {
// Get Blob object instead of a formatted result
let blob = queue.getResult('sprite', true);
// Create a Blob URL using the Blob object
let urls = [
URL.createObjectURL(blob),
URL.createObjectURL(blob),
URL.createObjectURL(blob),
];
// Create a new <img> element and assign a Blob URL
urls.forEach(function(item, index, array) {
let DOM_img = document.createElement('img');
DOM_img.src = item;
document.getElementById('game').appendChild(DOM_img);
});
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>
Alternative solution (Not recommended for big files)
Also you can use the loadManifest() to load the same image multiple times with different ids. Then we define a fileload event instead of complete event to capture each loaded element, check this example:
let queue = new createjs.LoadQueue();
queue.addEventListener('fileload', onFileLoad);
queue.loadManifest([{
id: 'sprite1',
type: 'image',
src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, {
id: 'sprite2',
type: 'image',
src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, {
id: 'sprite3',
type: 'image',
src: 'https://i.imgur.com/ciIyRtu.jpg?1',
}, ]);
function onFileLoad(event) {
// Get the image element after is successfully loaded
let img = event.result;
// This code insert the image to the DOM succesfully
document.getElementById('game').appendChild(img);
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>
Just found another solution that loads image once and then insert it to dom a twice.
var queue = new createjs.LoadQueue();
queue.addEventListener('complete', onComplete);
queue.loadManifest([{
id: 'img',
type: 'image',
src: 'https://i.imgur.com/adSrF00g.png',
}, ]);
queue.load();
function onComplete(event) {
// get loading results as blob (second argument is set to true)
var blob = queue.getResult('img', true);
// create two blob urls from one blob image source
var blobUrl = URL.createObjectURL(blob);
var blobUrl2 = URL.createObjectURL(blob);
// create new IMG tag and set src as first blob url
var DOM_img = document.createElement("img");
DOM_img.src = blobUrl;
document.getElementById('game').appendChild(DOM_img);
// create new IMG tag and set src as second blob url
var DOM_img2 = document.createElement("img");
DOM_img2.src = blobUrl2;
document.getElementById('game').appendChild(DOM_img2);
}
<script src="https://code.createjs.com/1.0.0/preloadjs.min.js"></script>
<div id="game"></div>

PNG or JPG (not rgb) over websocket with ArrayBuffer without base64

Is there a way to render a PNG image to canvas without having to encode it to base64?
Server sends a PNG in binary, client receives it in an ArrayBuffer
and displays it on the canvas. Only way I could get this to work is by encoding the data to base64 - on the server side - as I need it to be fast. On the client side, I created an image obj with data:image/png;base64 tag.
I know you can create a blob and a file reader but I could not get that to work.
This is the blob version:
var blob = new Blob([image.buffer],{type: "image/png"});
var imgReader = new FileReader();
imgReader.onload = function (e) {
var img = new Image();
img.onload = function (e) {
console.log("PNG Loaded");
ctx.drawImage(img, left, top);
window.URL.revokeObjectURL(img.src);
img = null;
};
img.onerror = img.onabort = function () {
img = null;
};
img.src = e.target.result;
imgReader = null;
}
imgReader.readAsDataURL(blob);
image is Uint8Array. I create a blob from it. The rest is self-explanatory.
Images are correct and valid PNG images. When I send it from the server, I wrote them to a file on the server side and they render fine with an image viewer.
You can create a blob url with createObjectURL without having to do any base64 encoding, just pass the blob you crated to it and you will have a url you can set as img.src
var blob = new Blob([image],{type: "image/png"});
var img = new Image();
img.onload = function (e) {
console.log("PNG Loaded");
ctx.drawImage(img, left, top);
window.URL.revokeObjectURL(img.src);
img = null;
};
img.onerror = img.onabort = function () {
img = null;
};
img.src = window.URL.createObjectURL(blob);
I've only seen it used in this way. If you don't want to send the base64 via the network, then, you can use the btoa to convert the binary data to a base64 on the client side.
Looking at MDN, drawImage takes a CanvasImageSource object. CanvasImageSource represents any object of type HTMLImageElement, ImageBitmap and few others.
On further searching, I found some information related to ImageBitmap, but, not enough to provide a solution.
I could have added this to the comment, but, it would have become a massive comment and lose all the clarity.

Load file into IMAGE object using Phantom.js

I'm trying to load image and put its data into HTML Image element but without success.
var fs = require("fs");
var content = fs.read('logo.png');
After reading content of the file I have to convert it somehow to Image or just print it to canvas. I was trying to conver binary data to Base64 Data URL with the code I've found on Stack.
function base64encode(binary) {
return btoa(unescape(encodeURIComponent(binary)));
}
var base64Data = 'data:image/png;base64,' +base64encode(content);
console.log(base64Data);
Returned Base64 is not valid Data URL. I was trying few more approaches but without success. Do you know the best (shortest) way to achieve that?
This is a rather ridiculous workaround, but it works. Keep in mind that PhantomJS' (1.x ?) canvas is a bit broken. So the canvas.toDataURL function returns largely inflated encodings. The smallest that I found was ironically image/bmp.
function decodeImage(imagePath, type, callback) {
var page = require('webpage').create();
var htmlFile = imagePath+"_temp.html";
fs.write(htmlFile, '<html><body><img src="'+imagePath+'"></body></html>');
var possibleCallback = type;
type = callback ? type : "image/bmp";
callback = callback || possibleCallback;
page.open(htmlFile, function(){
page.evaluate(function(imagePath, type){
var img = document.querySelector("img");
// the following is copied from http://stackoverflow.com/a/934925
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.
window.dataURL = canvas.toDataURL(type);
}, imagePath, type);
fs.remove(htmlFile);
var dataUrl = page.evaluate(function(){
return window.dataURL;
});
page.close();
callback(dataUrl, type);
});
}
You can call it like this:
decodeImage('logo.png', 'image/png', function(imgB64Data, type){
//console.log(imgB64Data);
console.log(imgB64Data.length);
phantom.exit();
});
or this
decodeImage('logo.png', function(imgB64Data, type){
//console.log(imgB64Data);
console.log(imgB64Data.length);
phantom.exit();
});
I tried several things. I couldn't figure out the encoding of the file as returned by fs.read. I also tried to dynamically load the file into the about:blank DOM through file://-URLs, but that didn't work. I therefore opted to write a local html file to the disk and open it immediately.

Load image into FileReader

I want to load an image from an url into filereader in order to obtain a data url of that image. I tried to search for the solution on google but i can only find solutions to read them from the file input on a local computer.
If you want a usable data-URI representation of the image, then I suggest to load the image in a <img> tag, paint it on a <canvas> then use the .toDataURL() method of the canvas.
Otherwise, you need to use XMLHttpRequest to get the image blob (set the responseType property on the XMLHttpRequest instance and get the blob from the .response property). Then, you can use the FileReader API as usual.
In both cases, the images have to be hosted on the same origin, or CORS must be enabled.
If your server does not support CORS, you can use a proxy that adds CORS headers. In the following example (using the second method), I'm using CORS Anywhere to get CORS headers on any image I want.
var x = new XMLHttpRequest();
x.open('GET', '//cors-anywhere.herokuapp.com/http://www.youtube.com/favicon.ico');
x.responseType = 'blob';
x.onload = function() {
var blob = x.response;
var fr = new FileReader();
fr.onloadend = function() {
var dataUrl = fr.result;
// Paint image, as a proof of concept
var img = document.createElement('img');
img.src = dataUrl;
document.body.appendChild(img);
};
fr.readAsDataURL(blob);
};
x.send();
The previous code can be copy-pasted to the console, and you will see a small image with YouTube's favicon at the bottom of the page. Link to demo: http://jsfiddle.net/4Y7VP/
Alternative download with fetch:
fetch('http://cors-anywhere.herokuapp.com/https://lorempixel.com/640/480/?
60789', {
headers: {},
}).then((response) => {
return response.blob();
}).then((blob) => {
console.log(blob);
var fr = new FileReader();
fr.onloadend = function() {
var dataUrl = fr.result;
// Paint image, as a proof of concept
var img = document.createElement('img');
img.src = dataUrl;
document.body.appendChild(img);
};
fr.readAsDataURL(blob);
}).catch((e) => console.log(e));

Categories

Resources