Save the blob url image from using viewer.screenshot() to server/database - javascript

I used forge viewer api. Viewer.screenshot() to get the image of a component. It returns a blob url as the image. E.g “blob:localhost:3000/afdijhejsbjdjd”. But I need to save this image to my local server, how can I achieve this? Using Nodejs.
How can I change this blob url to a transferable image url?

We can convert the image Blob URL to a based64 encoded string like the below, and then
function getScreenShotImageBase64(viewer, width, height) {
return new Promise((resolve) => {
viewer.getScreenShot(width, height, blobURL => {
let img = new Image();
let tmpCanvas = document.createElement('canvas');
let ctx = tmpCanvas.getContext('2d');
tmpCanvas.width = width;
tmpCanvas.height = height;
img.onload = function() {
// draw viewer image on canvas
ctx.drawImage(img, 0, 0, width, height);
resolve(tmpCanvas.toDataURL('image/png'));
};
img.src = blobURL;
});
});
}
let imageBase64 = await getScreenShotImageBase64(viewer, viewer.container.offsetWidth, viewer.container.offsetHeight);
Here is the preview of the result:
Afterward, send the base64 string to your backend server, and then you can either save the image base64 string to your database,
Or resave the base64 string to file. For example in nodejs.
fs.writeFileSync(path.join(uploadPath, fileName), new Buffer(base64, 'base64'))
ref: How to upload image using Base64 string in NodeJs

Related

How to encode an <input type="file> as a base64 string?

I am trying to send an image to my express backend. I have tried adding the image directly to my post request body.
var imgValue = document.getElementById("image").value;
In my post request
body : JSON.stringify({
image:imgValue
})
Accessing the image on the backend only gives me the name of the file. Is there any way I can encode the image as a base64 string in the frontend itself?
You need to load the image into a temporary img element and then you can convert it to base64 when the temporary element has loaded the image.
Use the image as img.src = (YourImageSource)
From the onload function you can then retrieve the base64 value.
var imgEl = document.createElement('img');
imgEl.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);
const d = canvas.toDataURL('image/jpeg');
console.log('base64',d);
};
imgEl.src = img;
Run below code, if you already upload your file then the console will show the base64 of the file
The example is for only first file.
If you need upload more than one files. You can loop to make it.
document.getElementById("image").files;
Using files array to get each file's base64.
var file = document.getElementById("image").files[0];
var reader = new FileReader();
reader.onload = function (r) {
var fileInfo = new Object();
fileInfo.name = file.name;
fileInfo.size = file.size;
fileInfo.extension = file.name.split(".")[file.name.split(".").length - 1];
console.log(r.target.result.split("base64,")[1]);
};
reader.onerror = function (ex) {
console.error(ex);
};
reader.readAsDataURL(file);

How to send a resized user uploaded image to the server (Rails)?

I know there are tons of posts about image resizing and I read a lot of them. I was able to resize an image uploaded by a user. But I genuinely don't understand how to post the form with this new and resized image.
I implemented the resizing method from this post, but I don't understand the part where the blob is appended to the formData.
const input = this.$refs.input;
const file = input.files[0];
// Load the image
var reader = new FileReader();
reader.onload = function (readerEvent) {
var image = new Image();
image.onload = function (imageEvent) {
// Resize the image
var canvas = document.createElement('canvas');
const width = 200;
const height = 300;
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
var dataUrl = canvas.toDataURL('image/jpeg');
var resizedImage = dataURLToBlob(dataUrl);
// I don't understand that part
// $.event.trigger({
// type: 'imageResized',
// blob: resizedImage,
// url: dataUrl,
// });
// I understand that an image input value can not be changed programatically
// const url = URL.createObjectURL(resizedImage);
// input.value = url;
};
image.src = readerEvent.target.result;
};
reader.readAsDataURL(file);
To be clear, this is a Rails project and the form (that includes many other fields than just the image) is built with simple_form.
Should I actually place the file input out of the form? Should I intercept the form submit call to manually construct the formData, including the resized image? Should I maybe do the resizing on the server side?
My understanding is probably wrong, so I would greatly appreciate any help!
you probably want to do the image resizing on the server any way cuz the browser dose a bad job at compressing it.
( see how to compress a base64 image to custom size )
fyi, it's possible to update a FileList programatically in a round about way...
Is it possible to update FileList?
About the part of where you want to append the file to a formdata
you have to use canvas.toBlob to get it as a file instead of a base64 string.
async function showDemo (blob) {
const file = blob // simulated getting a file from input
// Load the image
const bitmap = await createImageBitmap(blob)
// Resize the image
var canvas = document.createElement('canvas')
const width = 200
const height = 300
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(bitmap, 0, 0, width, height);
canvas.toBlob(function (resizedImage) {
const fd = new FormData()
const img = new Image()
fd.append('upload', file, 'image.jpg')
img.src = URL.createObjectURL(resizedImage)
document.body.append(img)
// upload
// fetch(url, { method: 'post', body: fd })
}, 'image/jpeg', 1);
}
// just to get a dummy image:
fetch('https://dummyimage.com/600x400/000/fff').then(res =>res.blob()).then(showDemo)

Convert Link from Image URL from s3 into File Object using JavaScript

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

HTML5 load a png buffer into a canvas (for streaming purpose)

Through a websocket, I retrieve a binary buffer of an image in a PNG format (something like that).
I want to load this PNG buffer into a canvas, and then read the different pixels to read the uncompressed data.
I managed to do it but it is stupid:
function onBinaryMessage(/*ArrayBuffer*/ input) {
input = new Uint8Array(input);
var str = '';
for (var i = 0; i < input.byteLength; i++)
str = str + String.fromCharCode(input[i]);
var image = document.getElementById("image");
image.src = 'data:image/png;base64,' + btoa(str);
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.drawImage(image, 0, 0);
var imgData = ctx.getImageData(0, 0, image.width, image.height);
console.log(imgData);
}
I have to convert my binary into a string to encode64 this string, and than I affect my image src to this newly created encoded64 string...
The browser have to re-convert this encoded64 data into the original PNG buffer I got...
Is there any way to directement set the canvas buffer?
Or is there any method to better handle streaming?
I think I could use the File API to write the buffer into a temporary file but it would cost a lot to create a file :(
Any suggestion?
You can convert your input buffer to a Blob instead, obtain an URL for it and use that to draw onto the canvas instead:
function onBinaryMessage(input) {
var blob = new Blob([input], {type: 'image/png'});
var url = URL.createObjectURL(blob);
var img = new Image;
img.onload = function() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.drawImage(this, 0, 0);
URL.revokeObjectURL(url);
}
img.src = url;
}
Just note that this will be asynchronous and you would need to provide a callback-mechanism inside the onload handler (in any case you really need to do that in your own example as well). But you won't have to convert to base64 etc. which is a relative costly operation.
Also note that URL.createObjectURL is currently experimental.

How can I get Image data or the path of cache of Image on WebPage in chrome or firefox?

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.

Categories