FabricJS canvas to image issue - javascript

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

PWA appearing black when using blob

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.

IE11 hangs when downloading large base64 file

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.

AJAX convert image into ByteArray

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/

How can I save a JPEG from a URL to a file in angularjs(ionic)?

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.

converting ByteArray into blob using javascript

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

Categories

Resources