I'm saving pictures in my application using the camera feature of Phonegap. When I try to get the file through its saved file_URI (that I got from the camera), the image doesn't load.
function toBase64(url) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = url;
if ( img.height != 0 ) {
var height = img.height, width = img.width;
canvas.height = height;
canvas.width = width;
ctx.drawImage(img, 0, 0, width, height);
try {
var dataURL = canvas.toDataURL("image/jpg");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
catch (err) { console.log("ERROR " + err);}
}
else {
alert("Wrong path!");
}
}
The images are saved in the cache folder of the application (/data/data/my.app/cache)
Any ideas of where the problem could be from ?
I fixed this issue and had to use the FileReader object of Phonegap.
var base64;
function toBase64(filename) {
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, function(fileSystem) {
// Filesystem's root is the cache folder of the application: /storage/emulated/0/Android/data/com.yourcompany.whatever
fileSystem.root.getFile(filename, null, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log(evt.target.result);
// Firing callback
base64 = evt.target.result;
};
reader.readAsDataURL(file);
}, fail);
}, fail);
}, fail);
// We wait until the reader was fully loaded and then we return the base64 encrypted data !
while ( base64 == "" ) {}
base64 = base64.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
return base64;
}
Don't think that the "while(base64 == "" ) {}" is a good practice though...
EDIT: I used the do_when method of this gentleman instead of the empty loop !
Related
I used a lot time, trying to get a successful decode image in base64, but I get a black image. I don't know what is wrong.
I am using jcrop
I need yo two thing.
Get a successful image when decode it base64 and I can rotate image before to crop. Appreciate your help or recommendations.
I am using this example is not mine in jisfidle
var cropCoords,
file,
uploadSize = 360,
previewSize = 500;
$("input[type=file]").on("change", function(){
file = this.files[0];
readFile(file, {
width: previewSize,
height: previewSize
}).done(function(imgDataUrl, origImage) {
$("input, img, button").toggle();
initJCrop(imgDataUrl);
}).fail(function(msg) {
alert(msg);
});
});
$("button[type=submit]").on("click", function(){
$(this).text("Uploading...").prop("disabled", true);
readFile(file, {
width: uploadSize,
height: uploadSize,
crop: cropCoords
}).done(function(imgDataURI) {
var data = new FormData();
var blobFile = dataURItoBlob(imgDataURI);
data.append('file', blobFile);
$.ajax({
url: "/upload",
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function() {
alert("Yay!");
},
error: function(xhr) {
alert("Well, obviously we can't upload the file here."+
"This is what the data looks like: " +
imgDataURI.substr(0,128)+"...");
console.log(imgDataURI);
}
});
});
});
/*****************************
show local image and init JCrop
*****************************/
var initJCrop = function(imgDataUrl){
var img = $("img.crop").attr("src", imgDataUrl);
var storeCoords = function(c) {
cropCoords = c;
};
var w = img.width();
var h = img.height();
var s = uploadSize;
img.Jcrop({
onChange: storeCoords,
onSelect: storeCoords,
aspectRatio: 1,
setSelect: [(w - s) / 2, (h - s) / 2, (w - s) / 2 + s, (h - s) / 2 + s]
});
};
/*****************************
Read the File Object
*****************************/
var readFile = function(file, options) {
var dfd = new $.Deferred();
var allowedTypes = ["image/gif", "image/jpeg", "image/pjpeg", "image/png", "image/bmp"];
if ($.inArray(file.type, allowedTypes) !== -1) {
//define FileReader object
var reader = new FileReader();
var that = this;
//init reader onload event handlers
reader.onload = function(e) {
var image = $('<img/>')
.load(function() {
//when image is fully loaded
var newimageurl = getCanvasImage(this, options);
dfd.resolve(newimageurl, this);
})
.attr('src', e.target.result);
};
reader.onerror = function(e) {
dfd.reject("Couldn't read file " + file.name);
};
//begin reader read operation
reader.readAsDataURL(file);
} else {
//some message for wrong file format
dfd.reject("Selected file format (" + file.type + ") not supported!");
}
return dfd.promise();
};
/*****************************
Get New Canvas Image URL
*****************************/
var getCanvasImage = function(image, options) {
//define canvas
var canvas = document.createElement("canvas"),
ratio = {
x: 1,
y: 1
};
if (options) {
if (image.height > image.width) {
ratio.x = image.width / image.height;
} else {
ratio.y = image.height / image.width;
}
}
canvas.height = options.crop ? Math.min(image.height, options.height) : Math.min(image.height, Math.floor(options.height * ratio.y));
canvas.width = options.crop ? Math.min(image.height, options.width) : Math.min(image.width, Math.floor(options.width * ratio.x));
var ctx = canvas.getContext("2d");
if (options.crop) {
//get resized width and height
var c = options.crop;
var f = image.width / options.previewWidth;
var t = function(a) {
return Math.round(a * f);
};
ctx.drawImage(image, t(c.x), t(c.y), t(c.w), t(c.h), 0, 0, canvas.width, canvas.height);
} else {
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
}
//convert canvas to jpeg url
return canvas.toDataURL("image/jpeg");
};
/*****************************
convert dataURI to blob
*****************************/
var dataURItoBlob = function(dataURI) {
var blob = window.Blob || window.WebKitBlob || window.MozBlob;
//skip if browser doesn't support Blob object
if (typeof blob === "undefined") {
alert("Oops! There are some problems with your browser! <br/>New image produced from canvas can\'t be upload to the server...");
return dataURI;
}
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
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 an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new blob([ab], {
type: mimeString
});
};
html
<input type="file" />
<img class="crop" style="display:none" />
<button type="submit" style="display:none">Upload</button>
I get a black image when decode it in base64
Example image
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCABLAEsDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD8qqKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/2Q==
I have already made a simple log system where i get the Base64 Code from a text string:
var myString = 'Hello everyone, my name is Dennis';
var b64 = btoa(myString);
var unicode = atob(b64);
console.log(b64);
console.log(unicode);
The output is a Base64 Code like i said, but what i am trying to is to convert an uploaded image to Base64. Here is what i got so far, the output what i get from this is the whole webpage in base64 code. i hope someone could help me out.
function toDataUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.send();
}
//use
var captcha = document.getElementById('logo').src;
toDataUrl(captcha, function(base64Img) {
log(captcha);
});
Thanks in advance!
There I made you a working example if the duplicate doens't help you:
(And be aware of CORS if your image is not heberged on the same domain of the request)
function toDataUrl(src, callback) {
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function() {
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL();
callback(dataURL);
};
img.src = src;
}
toDataUrl("http://i.imgur.com/rx3kylA.png", function(base64Img) {
console.log(base64Img);
});
I'm looking for the solution to my problem with image upload. I have one script that is kind of compressing my files with Javascript. Then it creates an Array with results in base64 which I want to add to my page as an <input type="hidden">. I have just one problem. It takes a bit to compress these images and .change() event on file input is not enough. Because it begins before the compression is done.
I was thinking about adding something like event listener for the statement, something like:
if(result_base64.length != input.files.length){
listen
} else {
do the function
}
Is it possible to achieve that without setting the interval function?
The compression script:
var result_base64 = [];
var images = document.getElementById('images');
var max_width = images.getAttribute('data-maxwidth');
var max_height = images.getAttribute('data-maxheight');
images.onchange = function(){
if ( !( window.File && window.FileReader && window.FileList && window.Blob ) ) {
alert('The File APIs are not fully supported in this browser.');
return false;
}
readfiles(images.files);
}
function readfiles(files) {
for (var i = 0; i < files.length; i++) {
processfile(files[i]);
}
images.value = "";
}
function processfile(file) {
if( !( /image/i ).test( file.type ) ){
alert( "File "+ file.name +" is not an image." );
return false;
}
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (event) {
var blob = new Blob([event.target.result]);
window.URL = window.URL || window.webkitURL;
var blobURL = window.URL.createObjectURL(blob);
var image = new Image();
image.src = blobURL;
image.onload = function() {
result_base64.push(resizeMe(image));
}
};
}
function resizeMe(img) {
var canvas = document.createElement('canvas');
var width = img.width;
var height = img.height;
if (width > height) {
if (width > max_width) {
height = Math.round(height *= max_width / width);
width = max_width;
}
} else {
if (height > max_height) {
width = Math.round(width *= max_height / height);
height = max_height;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
return canvas.toDataURL("image/jpeg",0.7);
}
Then it creates an Array with results in base64
In processFile() you can fire an event like
function processfile(file) {
if( !( /image/i ).test( file.type ) ){
alert( "File "+ file.name +" is not an image." );
return false;
}
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (event) {
var blob = new Blob([event.target.result]);
window.URL = window.URL || window.webkitURL;
var blobURL = window.URL.createObjectURL(blob);
var image = new Image();
image.src = blobURL;
image.onload = function() {
result_base64.push(resizeMe(image));
$(window).trigger('filesCompressed', result_base64); // This is the addition
}
};
}
Where you need these files, you can listen for this event like
$(window).on('filesCompressed', function(e, files) {
// Do something with files
})
Catch: The listening code must execute before the event is triggered.
I would like to ask you here about some problem.
I am using Phonegap to build an application that can take photo and then show the picture in a canvas.After drawimage in the canvas, I use a method to convert canvas to image file. But I have a problem related to writing file as image file to SD Card in Android,i.e, I cannot read the image file that was created in SD Card (image is invalid).
Here is my code:
var picture = "";
function takePhoto() {
navigator.camera.getPicture(onCameraSuccess,
onCameraError,{
quality : 50,
destinationType : Camera.DestinationType.FILE_URI
//saveToPhotoAlbum: true
});
}
function onCameraSuccess(imageURL) {
var canvas = document.getElementById('myCanvas');
var ctx=canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0,220,180);
};
imageObj.src=imageURL;
picture = imageURL;
}
function onCameraError(e) {
console.log(e);
navigator.notification.alert("onCameraError: " + e +" (" + e.code + ")");
}
function storePhoto() {
movePic(pictures);
}
function movePic(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fileSystem.root.getFile("test.PNG", {create: true, exclusive: false}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.createWriter(gotFileWriter, fail);
}
function gotFileWriter(writer) {
var c = document.getElementById('myCanvas');
var img_from_canvas=c.toDataURL("image/png"); // base64 encoded
var pic = img_from_canvas.split("base64,");
var pictures =window.atob(pic[1]); // decode base64
writer.write(pictures);
alert("Your picture was successfully stored !")
}
function fail(error) {
console.log(error.code);
}
I am appreciated for your helps and suggestion.
are you doing any kind of editing on image after capturing by canvas ?
if not then you can try this code to move file to root folder
var fs;
function movePic(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fs = fileSystem;
window.resolveLocalFileSystemURI(picture, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.moveTo( fs.root,fileEntry.name, success, fail);
}
function fail(error) {
console.log(error.code);
}
You have problem with writer.write(pictures);
Try this instead
var buffer = new ArrayBuffer(pictures.length);
var array = new Uint8Array(buffer);
for (var i = 0; i < pictures.length; i++) {
array[i] = pictures.charCodeAt(i);
}
writer.write(buffer);
It work for me.
I have an file input that i used to get a file and turn it into a blob. Is there anyway I can get an external image url and turn that into a blob? Here is the code I am using to do it with just a file from a <input type="file" />:
//Process the file and resize it.
function processfile(file) {
if (!(/image/i).test(file.type)) {
alert("File " + file.name + " is not an image.");
return false;
}
// read the files
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (event) {
// blob stuff
var blob = new Blob([event.target.result]); // create blob...
window.URL = window.URL || window.webkitURL;
var blobURL = window.URL.createObjectURL(blob); // and get it's URL
// helper Image object
var image = new Image();
image.src = blobURL;
image.onload = function () {
for (var x = 0; x < self.ThumbSizes.length; x++) {
// have to wait till it's loaded
var resized = resizeMe(image, self.ThumbSizes[x]); // send it to canvas
var resized_blob = dataURItoBlob(resized);
uploadFile(resized_blob, self.ThumbSizes[x].Name);
}
}
};
Instead of passing a file through I wanted to be able to structure this code to pass a image url and convert it into a blob.
I hope it helps you. (I didn't run it.)
function processfile(imageURL) {
var image = new Image();
var 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);
canvas.toBlob(function(blob) {
// do stuff with blob
});
};
image.onload = onload;
image.src = imageURL;
}