I have used Fabricjs on my project. If I draw some thing to canvas it works fine at the time of convert them to dataurl. But when I draw any image and convert them to dataurl its not working properly.
Can anyone help on this.
Here is my code:
Load canvas from json:
CANVASOBJ.canvas.loadFromJSON(CANVASOBJ.canJson.items[k].data, CANVASOBJ.canvas.renderAll.bind(CANVASOBJ.canvas), function(o, object) {
});
Function to convert to blob:
var blob =CANVASOBJ.toBlob(imageFileType,CANVASOBJ.canvas);
toBlob : function (type,canvas) {
var dataN = canvas.toDataURL({
width: canvas.getWidth(),
height: canvas.getHeight(),
multiplier: ''
});
console.log(canvas.toDataURL("image/png"));
var data = dataN.replace("data:image/png;base64,", "");
return CANVASOBJ.b64toBlob(data, 'image/png');
},
b64toBlob:function (b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
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);
}
console.log(byteArrays);
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
Related
I'm making an offline PWA installer using Blob, but when I share and add to home screen on IOS, the PWA appears completely black. Here is my code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function install(){
var autodate, enapp, data;
// Getting current PWA
$("#autodate").load("https://mysite.github.io/pwa/app1.html");
autodate = document.getElementById('autodate');
setTimeout(() => {
// Encode
encapp = btoa(autodate.innerHTML);
// Blob
blobt('text/html', 'data:text/html;base64,'+encapp)
}, 300);
};
function blobt(type, data){
const base64data = data;
const contentType = type;
const byteCharacters = atob(base64data.substr(`data:${contentType};base64,`.length));
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 1024) {
const slice = byteCharacters.slice(offset, offset + 1024);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
}
</script>
I don't see what would make it not work. It does everything perfectly in-browser, but once you install it to home screen, it just blacks out. Am I doing something wrong? Is there a solution to this?
Thanks in advance.
For IE11 in this code base64 file is converted to Blob, and then a download link is created. But with a large base64 file (~ >5Mb), the browser hangs at the moment when Blob is created:
new Blob(byteArrays, {type: contentType});
How is it possible to solve this problem?
var fullFileName = 'example.test';
var b64file = '';
var contentType = 'application/octet-stream';
b64toBlob(b64file, contentType, 512, function(blob){
if (typeof MouseEvent != "function") { //for IE
$('#ie_download').off('click').on('click', function(){
window.navigator.msSaveBlob(blob, fullFileName);
})
.show();
success();
return;
}
//other browsers
var blobUrl = URL.createObjectURL(blob);
var jqLink = $('<a style="display: none" target="_blank">Save</a>');
$('#download')
.attr('download', fullFileName)
.attr('href', blobUrl)
.show();
success();
});
function success () {
$('#waiting').hide();
}
function b64toBlob(b64Data, contentType, sliceSize, resultCb) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
var offset = 0;
setTimeout(function generateByteArrays () {
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);
offset += sliceSize;
if (offset < byteCharacters.length) {
setTimeout(generateByteArrays, 0);
}
else {
resultCb(new Blob(byteArrays, {type: contentType}));
}
}, 0);
}
#download, #ie_download {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='waiting'>waiting...</div>
<a id='download'>Save</a>
<a id='ie_download'>IE Save</a>
Update
I just noticed that the segment size is 512 bytes. This is extremely small and will with a 5 mb file create 10,240 array slices which IE seem to do a very slow operation with (ie. create buffer, copy content, check next slice, create new buffer of old size and next slice's size, copy old buffer + new content etc.).
You should be able to use at least 1000x larger slice size (0.5 mb) and with that not block IE11.
Demo using original code with a larger slice size:
setTimeout(test, 10);
function test() {
// Generate a big base-64 string, chop off data-uri
// NOTE: Initial creation will take a couple of seconds...
var c = document.createElement("canvas"); c.width = c.height = 6000;
var ctx = c.getContext("2d"); // create some lines to degrade compression ratio...
for(var i = 0, r = Math.random.bind(Math), w = c.width, h = c.height; i < 500; i++) {
ctx.moveTo(r()*w, r()*h);ctx.lineTo(r()*w, r()*h);
}
ctx.stroke();
var base64 = c.toDataURL();
base64 = base64.substr(base64.indexOf(",")+1);
// OK, now we have a raw base64 string we can use to test
document.querySelector("out").innerHTML = "Converting...";
// Increase sliceSize by x1024
b64toBlob(base64, "application/octet-stream", 512<<10, function(blob) {
document.querySelector("out").innerHTML = "Blob size: " + blob.size;
});
function b64toBlob(b64Data, contentType, sliceSize, resultCb) {
contentType = contentType || '';
sliceSize = sliceSize || (512<<10);
var byteCharacters = atob(b64Data);
var byteArrays = [];
var offset = 0;
setTimeout(function generateByteArrays () {
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);
offset += sliceSize;
if (offset < byteCharacters.length) {
setTimeout(generateByteArrays, 5);
}
else {
resultCb(new Blob(byteArrays, {type: contentType}));
}
}, 5);
}
}
<out>Creating test data...</out>
Due to a bug in IE11 one cannot use XMLHttpRequest() with a data-uri and response type "blob", otherwise you could have used that to do all these operations for you.
var c = document.createElement("canvas"); c.width = c.height = 4000;
var ctx = c.getContext("2d"); // create some lines to degrade compression ratio...
for(var i = 0, r = Math.random.bind(Math), w = c.width, h = c.height; i < 200; i++) {
ctx.moveTo(r()*w, r()*h);ctx.lineTo(r()*w, r()*h);
}
ctx.stroke();
var base64 = c.toDataURL();
base64 = base64.substr(base64.indexOf(",")+1);
b64toBlob(base64, "application/octet-stream", function(blob) {
console.log(blob)
})
// Using XMLHttpRequest to do the work (won't work in IE11...)
function b64toBlob(base64, mimeType, callback) {
var xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.onload = function() {
callback(this.response)
};
xhr.open("GET", "data:" + mimeType + ";base64," + base64);
xhr.send();
}
Old answer (still applicable/recommended)
Increase the timeout to something like 7-10ms and see if that unblock the loop (or use even higher value if still blocking).
A timeout of 0 is in effect beating the purpose of this asynchronous segmentation approach.
I need to create a method to convert a image with AJAX to a ByteArray and send via AJAX to My API PHP.
Someone can help me?!
Thanks
Solution 1:
This is the sample code which is returning Bytes
Javascript :
<script type="text/javascript">
$(document).ready(function () {
$('#cmdUpload').click(function () {
uploadFile();
});
});
function uploadFile() {
var input = document.getElementById('objFile');
// var file = $("#objFile")[0].files[0];
var file = input.files[0];
fr = new FileReader();
fr.onload = receivedText;
//fr.readAsText(file);
fr.readAsDataURL(file);
}
function receivedText() {
var b64Data = fr.result.split(',');
var contentType = 'image/jpeg';
//document.getElementById('editor').appendChild(document.createTextNode(fr.result))
var byteCharacters = atob(b64Data[1]);
var byteNumbers = Array.prototype.map.call(byteCharacters,
charCodeFromCharacter);
var uint8Data = new Uint8Array(byteNumbers);
var blob = b64toBlob(b64Data[1], contentType);
var blobUrl = URL.createObjectURL(blob);
}
function charCodeFromCharacter(c) {
return c.charCodeAt(0);
}
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 1024;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = Array.prototype.map.call(slice, charCodeFromCharacter);
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
for (var i = 0; i < byteArray.length; i++) {
alert(byteArray[i]);
}
}
</script>
HTML :
<div>
<input type="file" id="objFile" size="50" /><br />
<br />
<input type="button" id="cmdUpload" value="Upload" />
<div id="editor"></div>
</div>
Note: require Jquery library.
Hope it will help you.
Solution 2:
Reference link:
http://www.macaalay.com/2014/09/26/rendering-images-from-byte-arrays-and-converting-images-to-byte-arrays-using-angularjs/
I have got base64data from ng-src, but I can't make a jpeg file with this base64data. I have ever been trying as follow:
First I have removed the data:image/jpeg:base64, chunk from data:image/jpeg:base64,/9/DEefesdfae453/sdDFEYEUdfdief8fe ... and write this data with test.jpg file by use of $cordovaFile. Here is my code:
var base64Image = angular.element(document.querySelectorAll('#my-photo')).attr('src');
var writeData = base64Image.replace(/data:image\/jpeg;base64,/g, '');
alert(writeData);
// Writing filtered image -----------------------------------------------------------------
$cordovaFile.writeFile(ROOT_DIR + PM_DATA_DIR_NAME + '/', $scope.photo.name, writeData, true)
.then(function (success) {
// success
$ionicLoading.hide();
$ionicPopup.alert({
template : "Updated Photo!!"
});
}, function (error) {
// error
$ionicLoading.hide();
$ionicPopup.alert({
template : "Failed to update Photo!!"
});
});
But I can't show the file as image file. It is showing only black screen. (original file size : 19K ---> result file size : 66K)
What's wrong?
Please help me.
Thank you everybody to help.
FileWriter’s write method does not take a base64 string. According to the docs (http://docs.phonegap.com/en/edge/cordova_file_file.md.html#FileWriter) text will be encoded as UTF-8 before being written. So your base64 string is being encoded before writing to the file so it’s not valid image data. You have to pass your image data as a Blob or an ArrayBuffer. Note this only works on iOS and Android. Have a look at Jeremy Banks’ b64toBlob function in this answer: https://stackoverflow.com/a/16245768
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
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;
}
You can pass the resulting blob into the write method.
I'm using flash to capture audio, encode it to mp3, then send it to javascript as ByteArray.
Now I want the javascript to save it as MP3 on my computer (not flash saves it to my computer). I am using Blob and then getDataURL, but the file isn't playing when saved. I used to do the same exact method to save WAV files and it worked perfectly fine.
Here's the JS code:
var getDataFromSWF = function (bytes) {
var myBlob = new Blob([bytes], { type: "audio/mpeg3" });
var url = (window.URL || window.webkitURL).createObjectURL(myBlob);
var link = window.document.createElement('a');
link.href = url;
// $("label").text(url);
link.download = 'output.mp3';
var click = document.createEvent("Event");
click.initEvent("click", true, true);
link.dispatchEvent(click);
// console.log(bytes);
}
I'm pretty much sure that the byteArray is fine because if I let the SWF save the file it works OK too. But I want to know what's wrong with the JS code. (note: i'm new to BLOB)
Try this to get the Blob
function base64toBlob(base64Data, contentType) {
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0 ; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}