I am trying to get an image from a URL by using Ajax and want to convert this into data URL.
so far I have done following things("ALL DOES NOT WORK :(")
sforce.connection.remoteFunction({
url : newURL,
mimeType: 'text/plain',
requestHeaders: {"responseType": "arraybuffer"},
onSuccess:function(response){
console.log(newURL);
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById(imageID);
output.src = dataURL;
};
var blob = new Blob([response], {type: "image/png"});
console.log(blob);
reader.readAsDataURL(blob);
}
This above code return data url but that does not display any image(corrupted).
I have done below thing also :
First converted response binary string into array like below
var bytes = new Uint8Array(response.length);
for (var i=0; i<response.length; i++)
bytes[i] = response.charCodeAt(i);
Now I converted above array into base64 like below
function Uint8ToString(u8a){
var CHUNK_SZ = 0x8000;
var c = [];
for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
}
return c.join("");
}
// Usage
var u8 = bytes;
var b64encoded = btoa(Uint8ToString(u8));
make data URI with above base64 like below
var dataurl = 'data:image/png;base64,'+b64encoded;
But nothing is working.
Below is the end point url to get image from
http://featherfiles.aviary.com/2014-10-24/f93707f9c1472f8a/7892b73db1d947adb7bc536d5d03e5c0.png
Please help me as I am not able to understand how to solve this :(
Are you able to get the blob of image correctly? i.e. it's size is that of the image right?
If yes , then you might be just missing this line (the creation of blobUrl from blob)
var blob = new Blob([response], {type: "image/png"});
var blobUrl= URL.createObjectURL(blob); //create blobUrl from blob
console.log(blob);
console.log(blobUrl)
reader.readAsDataURL(blobUrl);
Related
Python PIL rejects to read an image you have resized with Javascript canvas
I resize an image on the client-side with Javascript:
var reader = new FileReader();
reader.onload = function (e) {
el('image-picked').src = e.target.result;
el('image-picked').className = '';
var image = new Image();
//compress Image
image.onload=function(){
el("image-picked").src=image.src;
var canvas=document.createElement("canvas");
var context=canvas.getContext("2d");
new_size = get_sizes(image.width,image.height,max_side_px)
[canvas.width,canvas.height] = new_size;
context.drawImage(image,
0,
0,
image.width,
image.height,
0,
0,
canvas.width,
canvas.height
);
console.log("Converted");
//el('image-picked').className = 'no-display'
//el('image-picked').src=""
el('upload-Preview').className = ''
el('upload-Preview').src = canvas.toDataURL("image/png", quality);
The result seems ok, less size, seemingly ok:
There are only minor differences on the files with identify:
(base) ➜ Desktop file before.png after.png
before.png: PNG image data, 4048 x 3036, 8-bit/color RGB, non-interlaced
after.png: PNG image data, 500 x 375, 8-bit/color RGBA, non-interlaced
Then I send the file via POST:
var xhr = new XMLHttpRequest();
var loc = window.location
xhr.open('POST', `${loc.protocol}//${loc.hostname}:${loc.port}/analyze`, true);
xhr.onerror = function() {alert (xhr.responseText);}
xhr.onload = function(e) {
if (this.readyState === 4) {
var response = JSON.parse(e.target.responseText);
el('result-label').innerHTML = `Result = ${response['result']}`;
}
}
var fileData = new FormData();
var file = new File([el('upload-Preview').src],
"image.png", { type: "image/png",
lastModified : new Date()});
fileData.append('file', uploadFiles[0]);
xhr.send(fileData);
And then I read on the server with python open_image(BytesIO(img_bytes)) :
#app.route('/analyze', methods=['POST'])
async def analyze(request):
data = await request.form()
img_bytes = await (data['file'].read())
img = open_image(BytesIO(img_bytes))
The above works without problems with any normal image, but it fails with any image that is the result of the resize with js, and the error is
File "/Users/brunosan/anaconda3/envs/fastai/lib/python3.7/site-packages/PIL/Image.py", line 2705, in open
% (filename if filename else fp))
OSError: cannot identify image file <_io.BytesIO object at 0x124ce6360>```
I've tried canvas.toDataURL("image/jpeg", quality) on the JS side, and reading directly with PIL (not fastai, which calls PIL). It's the same error :frowning_face:
Found the answer here.
I was injecting the image as a a DataURL, when the POST expected a binary. I could see the difference using the "Network" tab:
To convert a DataURL into the binary we need to make a Blob, and then put it into a File:
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
blob=dataURItoBlob(el('upload-Preview').src)
var file = new File([blob],
"image.png", { type: "image/png",
lastModified : new Date()});
var fileData = new FormData();
fileData.append('file', file);
I am trying to parse blob object into base64 string in javascript. Please help. my code is
var reader = new FileReader();
reader.addEventListener("loadend", function () {
// reader.result contains the contents of blob as a typed array
var buffer = reader.result;
var view = new Uint8Array(buffer);
var binary = String.fromCharCode.apply(window, view);
var base64 = btoa(binary);
cb(base64);
console.log(base64);
});
reader.readAsArrayBuffer(data.blob);
You may try this-
var blob = //your blob data;
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
var base64data = reader.result;
console.log(base64data);
return;
}
Refer- Convert blob to base64
From server I am getting the pdf response as string format, Now on client side, I want to convert it into ArrayBuffer, So that we can change again in pdf.
I am converting it into pdf, like following, but is not pdf is getting corrupted.
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint8Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Above function I got from stackover flow, I change Uint16Array to Uint8Array, pdfkit uses utf-8 uncode formate..
service.getAddress(reqData).then(function(response){
if(response.data.error ===1){
toastr.error(response.data.message ,"Unsuccessful");
}else{
var uintStr = str2ab(response.data);
var file = new Blob([uintStr], {
type : 'application/pdf'
});
//trick to download store a file having its URL
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = envelopeObj.customer_name+'_'+ 'envId_'+envelopeObj.envelope_id+'.pdf';
document.body.appendChild(a);
a.click();
}
});
To using pdf kit to convert it into string format.
add_str = render_to_string(address_template_path , {"address_dict": address_dict})
pdfkit.from_string(add_str, file_location)
address_pdf = open(file_location)
response = HttpResponse(address_pdf.read(), content_type='application/pdf') # Generates the response as pdf response.
response['Content-Disposition'] = 'inline;filename= %s' % envelope_id
I used a jquery plugin to crop images. The plugin will crop the image and give it to me as a base64 encoded string. In order to upload it to S3, I need to convert this into a file and pass the file into the upload function. How can I do this? I tried a lot of things including decoding the string using atob. None worked.
Here's the code of the cropping plugin ('croppie') which gives me the encoded string :
imageCropper.croppie('result', {
type: 'canvas',
size: 'viewport',
format: 'jpeg'
}).then(function (resp) {
updateAvatar(resp);
});
I pass it to a function called updateAvatar. Here's the updateAvatar function :
updateAvatar({Meteor, Slingshot}, avatar) {
const uploader = new Slingshot.Upload('userAvatarUpload');
uploader.send(avatar, function (error, downloadUrl) {
if (error) {
// Log service detailed response.
console.error('Error uploading', uploader.xhr.response);
console.log(error);
}
else {
console.log('uploaded', downloadUrl);
}
});
}
The uploader.send function expects a file or a url. It won't accept my encoded string.
The plugin which I use to upload files to S3 : https://github.com/CulturalMe/meteor-slingshot
It seems like the missing 'brick' in your code is a function that would take a base64-encoded image and convert it to a Blob.
So, I'm going to focus on that part exclusively with a short comment for each step.
The following function expects a string such as:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICA...
function base64ImageToBlob(str) {
// extract content type and base64 payload from original string
var pos = str.indexOf(';base64,');
var type = str.substring(5, pos);
var b64 = str.substr(pos + 8);
// decode base64
var imageContent = atob(b64);
// create an ArrayBuffer and a view (as unsigned 8-bit)
var buffer = new ArrayBuffer(imageContent.length);
var view = new Uint8Array(buffer);
// fill the view, using the decoded base64
for(var n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
// convert ArrayBuffer to Blob
var blob = new Blob([buffer], { type: type });
return blob;
}
Convert the base64 string to blob, to be used in upload to S3. There are tidier ways of doing this of course! :)
Original SO Answer here: https://stackoverflow.com/a/16245768/1350913
imageCropper.croppie('result', {
type: 'canvas',
size: 'viewport',
format: 'jpeg'
}).then(function(resp) {
var contentType = 'image/png';
var s3Blob = b64toBlob(resp, contentType);
updateAvatar(s3Blob);
});
updateAvatar({
Meteor,
Slingshot
}, avatar) {
const uploader = new Slingshot.Upload('userAvatarUpload');
uploader.send(avatar, function(error, downloadUrl) {
if (error) {
// Log service detailed response.
console.error('Error uploading', uploader.xhr.response);
console.log(error);
} else {
console.log('uploaded', downloadUrl);
}
});
}
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var b64DataString = b64Data.substr(b64Data.indexOf(',') + 1);
var byteCharacters = atob(b64DataString);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {
type: contentType
});
return blob;
}
The base64ToFile function (.ts) converts the base64 string into a File. The codeUnits and charCodes part make sure you can read Unicode text as ASCII by converting the string such that each 16-bit unit occupies only one byte.
Finally the download function (.ts) downloads the converted file from your browser to your local machine.
function base64ToFile(base64data: string, myFileNameWithdotExtention: string,
fileType: string): File {
let content = decodeURIComponent(escape(window.atob(base64data)));
let fileName = myFileNameWithdotExtention;
const codeUnits = Uint16Array.from(
{ length: content.length },
( _, index) => content.charCodeAt(index)
);
const charCodes = new Uint8Array(codeUnits.buffer);
const type = fileType; // 'text/csv' for instance
const blob = new Blob([charCodes], { type });
return new File([blob], fileName, { lastModified: new Date().getTime(), type });
}
download(){
let res: string = getMyDataFromSomewhere(); // base64 string
let data = base64ToFile(res);
let element = document.createElement('a');
window.URL = window.URL || window.webkitURL;
element.setAttribute('href', window.URL.createObjectURL(data));
element.setAttribute('download', data.name);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
blob has null prepended at the start eg : blob:null/72438-4637-23673-34721. But when I use the same as a src to the , it shows up the correct image.
I am using URL.createObjectURL call. I also tried using webkitURL. Both return a blob with null appended at the start. Also the blob value returned by URL and webkitURL are not the same.
Here is the code snippet
var dataUrl = canvas.toDataURL();
// The last piece of the data URL after the comma
var byteString = atob(dataUrl.split(',')[1]);
// Populate an array buffer
var arrayBuffer = new ArrayBuffer(byteString.length);
var uint8Array = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteString.length; i++) {
uint8Array[i] = byteString.charCodeAt(i);
}
var blob = new Blob([uint8Array], { type: "image/png" });
var blobVal = URL.createObjectURL(blob);
Here the blobVal has "blob:null/1234-5678-9012- ..."
That's the origin, file system and sandboxed iframes(maybe others) have null as their origin. If you set up a local sever it should say http%3A//localhost, that's http://localhost url encoded
var arrayBuffer = new ArrayBuffer(100);
var uint8Array = new Uint8Array(arrayBuffer);
for (var i = 0; i < 100; i++) {
uint8Array[i] = i;
}
var blob = new Blob([uint8Array], { type: "image/png" });
var blobVal = URL.createObjectURL(blob);
$('div').html(blobVal);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
This one sais http%3A//fiddle.jshell.net
http://jsfiddle.net/thsn3ayp/