PreloadJS loaded image, but I cannot insert it to DOM - javascript

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>

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.

How to read remote image to a base64 data url

actually there are many answers for this question. But my problem is,
i want to generate pdf dynamically with 5 external(URL) images. Im using PDFmake node module.
it supports only two ways local and base64 format. But i don't want to store images locally.
so my requirement is one function which takes url as parameter and returns base64.
so that i can store in global variable and create pdfs
thanks in advance
function urlToBase(URL){
return base64;
}
var img = urlToBase('https://unsplash.com/photos/MVx3Y17umaE');
var dd = {
content: [
{
text: 'fjfajhal'
},
{
image: img,
}
]
};
var writeStream = fs.createWriteStream('myPdf.pdf');
var pdfDoc = printer.createPdfKitDocument(dd);
pdfDoc.pipe(writeStream);
pdfDoc.end();
im using PDFmake module from npm
The contents of the remote image can first be fetched with an HTTP request, for example using the ubiquitous request npm module. The image string contents can then be transformed to a buffer and finally converted to a base64 string. To complete the transformation, add the proper data-url prefix, for example, data:image/png,base64, to the beginning of the base64 string.
Here is a rough example for a PNG image:
const request = require('request-promise-native');
let jpgDataUrlPrefix = 'data:image/png;base64,';
let imageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
request({
url: imageUrl,
method: 'GET',
encoding: null // This is actually important, or the image string will be encoded to the default encoding
})
.then(result => {
let imageBuffer = Buffer.from(result);
let imageBase64 = imageBuffer.toString('base64');
let imageDataUrl = jpgDataUrlPrefix+imageBase64;
console.log(imageDataUrl);
});

Display image from ID3 image data using javascript

I've tried all of the methods I could find in stackoverflow. This two are some of the most complete posts:
Display image from blob using javascript and websockets
How can you encode a string to Base64 in JavaScript?
I'm using cloudinary and id3js. First I upload the mp3 file to
cloudinary, then I request the file with Ajax through id3js. This
gives me all of the ID3 tags.
openUploadModal() {
cloudinary.openUploadWidget(window.cloudinaryOptions,
(errors, track) => {
if(!values(errors).length) {
id3(track[0].secure_url, (errs, tags) => {
this.setState({
title: tags.title,
audio_url: track[0].secure_url,
artist: tags.artist,
uploaded: true,
cover_photo: this.getImage(tags.v2.image)
});
});
}
});
}
And the image converter:
getImage(image) {
var arrayBuffer = image.data;
var bytes = new Uint8Array(arrayBuffer);
return "data:image/png;base64,"+btoa(unescape(encodeURIComponent(bytes)));
}
This is what the tags object looks like:
I then use the return value of getImage in the background-image attribute of a div. There are no errors in the console (not a bad request) but when opening the data:image/jpg;base64,... link there's only a little white square on the page.
How can I get a working url from the image object in the ID3 tags?
If image.data is an ArrayBuffer, you can use FileReader. FileReader load event is asynchronous, you cannot return the result from the function without using Promise, though you can use FileReaderSync() at Worker.
See also createImageBitmap alternative on Safari.
var reader = new FileReader();
reader.onload = function() {
// do stuff with `data URI` of `image.data`
console.log(reader.result);
}
reader.readAsDataURL(new Blob([image.data], {type:image.mime}));

Blob URL to image

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]);
};

What's DataTransferItemList and what is DataTransferItemList.add doing?

So I'm trying to understand paste and copy API in Google Chrome. I don't understand either.
As of copy, you'll probably want to use javascript to add something in clipboard. I'm working with images (strings work well actually1):
//Get DataTransferItemList
var files = items.items;
if(files) {
console.log(files);
//Create blob from canvas
var blob = Blob.fromDataURL(_this.editor.selection.getSelectedImage().toDataURL("image/png"));
var file;
try {
//Try to create file from blob, which may fail
file = new File([blob], "image.png", {type:"image/png"});
}
catch(e) {
return false;
}
if(file) {
//I think this should clear previous data from clipboard
files.clear();
//Add a file as image/png
files.add(file, "image/png");
}
//console.log(files.add(file));
}
The problem is, that I don't really know how does that add method work. I found this "documentation" for DataTransferItemList which says:
add(any data, optional DOMString type)
What's any data? (how can anybody even write this in documentation?) While something is added to clipboard, I don't know what it is. I can't paste it anywhere - except Chrome. If I inspect paste event with my copied file, this is in DataTransferItemList:
It can be converted to File, but if I try to turn it back to <img>:
ImageEditorKeyboard.prototype.processFile = function(file) {
//File reader converts files to something else
var reader = new FileReader();
//Refference to this class
var _this = this;
//happens when the file is loaded
reader.onload = function(event) {
var img = new Image;
img.onload = function() {
_this.processImage(this);
};
img.src = event.target.result;
}; // data url!
//Read file
reader.readAsDataURL(file);
}
I get the error2:
If I log the value of event.target.result it turns out that the data was empty:
console.error("String '", event.target.result, "' ain't a valid URL!");
Q: What is the exact specification of DataTransferItemList, it's methods and properties, especially the .add method?
1: To add string to clipboard (during copy event of course!), call this: event.clipboardData.setData(data, "text/plain");. The second argument doesn't seem to have any functionality - using image/png will not do anything.
2: Funny thing is that this error can't be caught.

Categories

Resources