THREE js - Load texture from string data - javascript

I am uploading a bunch of png files to AWS, and fetching them as I need them. When uploading, I stream the data read through fs, and when downloading I pipe the data from AWS as a response.
Anyhow, when I get hold of the data on the client, it is returned as a string with the following structure:
�PNG
IHDR�x�� IDATx���_��[�����1���s�?��9u����h�...
How do I load this into a texture? I have tried with this (also recommended by mrdoob here)
But it results in the Image throwing an uninformative error, and onload is never called.
let image = new Image();
let texture = new THREE.Texture();
image.onerror = function(e) {
//enters here
}
image.onload = function(e) {
//never here
texture.image = texture_image;
texture.needsUpdate = true;
}
image.src = myFetchedPNGData;
What is the correct way to create a THREE.Texture out of this data?
EDIT:
Here is the request for fetching the data:
let requestt = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/json');
request.addEventListener('load', (event) => {
// Here myFetchedPNGData recides in event.target.response
}, false);
request.addEventListener('error', (event) => {
//do error handling
}, false);
onProgress && request.addEventListener('progress', (event) => {
//Handle request
}, false);
request.send(...);

Related

How correctly store .js files to Localstorage of a browser

Can you please tell me how can I correctly store some js file to localstorage and then run it.
So I have found some code that stores an image, but can I store a js file?
Here is the code:
https://gist.github.com/robnyman/1875344
// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
rhino = document.getElementById("rhino");
if (rhinoStorage) {
// Reuse existing Data URL from localStorage
rhino.setAttribute("src", rhinoStorage);
}
else {
// Create XHR and FileReader objects
var xhr = new XMLHttpRequest(),
fileReader = new FileReader();
xhr.open("GET", "rhino.png", true);
// Set the responseType to blob
xhr.responseType = "blob";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
rhino.setAttribute("src", result);
// Store Data URL in localStorage
try {
localStorage.setItem("rhino", result);
}
catch (e) {
console.log("Storage failed: " + e);
}
};
// Load blob as Data URL
fileReader.readAsDataURL(xhr.response);
}
}, false);
// Send XHR
xhr.send();
}

Why can't my filereader read this data url from a xmlhttprequest

let MY_URL = "*"
let DataURL;
// basic JS way of getting the info from S3
let request = new XMLHttpRequest();
request.open('GET', MY_URL, true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
DataURL = e.target.result;
};
};
request.send();
listenGetImageLoad(DataURL);
Here I am getting the Data URL of a file I am getting from the web. Next I want to Read it into a fileReader, but I keep getting the bug:
Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.
My code for the fileReader is as follows::
const listenGetImageLoad = (DataURL) => {
const imageArray = Object.keys(images)
let async = imageArray.length
for (let image in images) {
const reader = new FileReader()
reader.addEventListener("load", () => {
const imageObject = new Image()
imageObject.addEventListener("load", (event) => {...})
reader.readAsDataURL(DataURL)
}
}
This function seems to be failing at reader.readAsDataURL(DataURL). I have no idea as to why this is the case. I am so sure that I have inputted a data URL into the FileReader function too.
You have two problems
You are calling listenGetImageLoad at the wrong time. XMLHttpRequest is async. So you need to call that inside your onload event.
Even when you correct the async issue you are passing the wrong thing to readAsDataURL(). It expects a blob or file object to be passed to it, not a string which is what a data url is.
Call listenGetImageLoad inside the load event passing in the response from the request to fix your issue.
request.onload = function() {
listenGetImageLoad(request.response);
};
Note you do not need to use readAsDataURL to show an image from a blob. Just call URL.createObjectURL() passing in the blob/file to get a url the browser will be able to load. Then set the src of the image with that url.
request.onload = function() {
var url = URL.createObjectURL(request.response);
yourImage.src = url;
};

How to post image to server from web camera canvas using toDataURL() ? javascript

I want to send image from capture by web camera then send to server for store that image.
function captureAndSendToServer() {
const player = document.getElementById('player')
const canvas = document.getElementById('canvas')
const context = canvas.getContext('2d')
context.drawImage(player, 0, 0, canvas.width, canvas.height)
var image = canvas.toDataURL("image/png")
// var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
axios
.post('http://localhost:3000/sendImageToCloudinary', image)
.then(response => {
console.log(response)
})
}
I using Cloudinary to store Image, the server code:
exports.sendImageToCloudinary = (req, res) => {
console.log(req.body)
cloudinary.v2.uploader.upload(req.body,
function (error, result) {
if (err) throw error
console.log(result)
res.json(result)
})
}
The error is
PayloadTooLargeError: request entity too large
And i've tried to console.log(image) and that output hundreds of thousands words.
So, what is the correct way to do that, thank you,
You can try something like the following-
var file = <your_file>;
var formdata = new FormData();
formdata.append('file', file);
formdata.append('cloud_name', '<cloud_name>');
formdata.append('resource_type', 'image');
formdata.append('upload_preset', '<upload_preset>');
var xhr = new XMLHttpRequest();
xhr.open('POST', "https://api.cloudinary.com/v1_1/<cloud_name>/image/upload",true);
xhr.onload = function () {
// do something to response
//console.log(this.responseText);
};
xhr.send(formdata);

Can't get EXIF info using loadImage.parseMetaData

I am using JavaScript LoadImage.parseMetaData (https://github.com/blueimp/JavaScript-Load-Image) to try and get Orientation of an image on the web, so I can rotate it.
If I hardcode the orientation (see "orientation: 3" in my second loadImage call), I can rotate it... but I am trying to use loadImage.parseMetaData to get the Orientation.
I have used web based EXIF parsers and the orientation info is there in the image.
When I call loadImage.parseMetaData "data.exif" seems to be null. See this fiddle: http://jsfiddle.net/aginsburg/GgrTM/13/
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.filepicker.io/api/file/U0D9Nb9gThy0fFbkrLJP', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
// Note: .response instead of .responseText
console.log ("got image");
var blob = new Blob([this.response], {type: 'image/png'});
console.log("about to parse blob:" + _.pairs(this.response));
loadImage.parseMetaData(blob, function (data) {
console.log("EXIF:" + _.pairs(data))
var ori ="initial";
if (data.exif) {
ori = data.exif.get('Orientation');
}
console.log("ori is:" + ori);
});
var loadingImage = loadImage(
blob,
function (img) {
console.log("in loadingImage");
document.body.appendChild(img);
},
{maxWidth: 600,
orientation: 3,
canvas: true,
crossOrigin:'anonymous'
}
);
if (!loadingImage) {
// Alternative code ...
}
}
};
xhr.send();
Any ideas or alternative approaches to correctly orientating images welcome.
Your call to loadImage needs to be inside the callback from the call to parseMetaData.
The reason: as is, your code contains a race condition. The call the loadImage is very likely to be made BEFORE the call the parseMetaData completes and stuffs the orientation due to the fact they are both asynchronous calls.
Why are you making a new blob whereas you asked for a Blob? The metadata are then lost, this is why you are losing it and exif is null.
Just replace :
var blob = new Blob([this.response], {type: 'image/png'});
By:
var blob = this.response;
Should do the trick.
Had the same problem, I changed the reponse type for 'arrayBuffer' and then create the blob from the response
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
if (this.status == 200) {
var arrayBufferView = new Uint8Array(this.response);
var blob = new Blob([arrayBufferView], { type: "image/jpeg" });
...

How to create a Blob from a local file in phonegap on android

I am trying to upload a file to amazon S3 from a phonegap app on android. I already have the code working for iOS. But I've got a trouble making it work on android. The problem is that I do not know how to create the Blob object properly. On iOS I just do this:
blob = new Blob([evt.target.result], {type: "image/png"});
It is uploaded just fine. On android one can not use the Blob constructor (see here), but I could not manage to get the file data correctly into the Blob object using WebKitBlobBuilder.
Here is how I retrieve the file data, there are two approaches and both pass without errors, but the resulting file on the S3 is empty:
window.resolveLocalFileSystemURI(url, function(e){
e.file(function(f){
var reader = new FileReader();
reader.onloadend = function(evt) {
// This way also did not work:
// var builder = new WebKitBlobBuilder();
// builder.append(evt.target.result);
// blob = builder.getBlob("image/png");
var blob = null;
var builder = new WebKitBlobBuilder();
for(var i = 0; i < evt.target.result.length; i++){
builder.append(evt.target.result[i]);
}
blob = builder.getBlob("image/png");
uploadToS3(filename, s3url, blob);
};
reader.readAsArrayBuffer(f);
});
}, function(e){
console.log("error getting file");
error();
});
also, here is the uploadToS3 function:
var uploadToS3 = function(filename, s3url, fileData) {
var xhr = createCORSRequest('PUT', s3url);
if(!xhr) {
console.log('CORS not supported');
error();
return;
}
xhr.onload = function () {
if(xhr.status == 200) {
console.log('100% - Upload completed.');
callback(filename); //callback defined in outer context
}
else {
console.log('0% - Upload error: ' + xhr.status);
console.log(xhr.responseText);
error();
}
};
xhr.onerror = function () {
console.log(0, 'XHR error.');
error();
};
xhr.upload.onprogress = function (e) {
if(e.lengthComputable) {
var percentLoaded = Math.round((e.loaded / e.total) * 100);
var label = (percentLoaded == 100) ? 'Finalizing.' : 'Uploading.';
console.log(percentLoaded + "% - " + label);
}
};
xhr.setRequestHeader('Content-Type', "image/png");
//xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.send(fileData);
};
EDIT:
I checked the filesize by logging evt.target.result.byteLength and it was ok, so evt.target.result contains image data. Still there is a problem with the upload - I checked the s3 storage and file size is 0, so I am not constructing the Blob correctly.
So this is an android bug after all, which was not fixed since at least Nov 2012.
Here is an article I found which is directly related to my problem: https://ghinda.net/article/jpeg-blob-ajax-android/
It also provides a workaround for the bug, which is to send ArrayBuffer directly, without creating a Blob. In my case I had to send evt.target.result directly.

Categories