Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

encode/decode image with base64 breaks image

I am trying to encode and decode an image. I am using the FileReader's readAsDataURL method to convert the image to base64. Then to convert it back I have tried using readAsBinaryString() and atob() with no luck. Is there another way to persist images without base64 encoding them?

readAsBinaryString()

Starts reading the contents of the specified Blob, which may be a File. When the read operation is finished, the readyState will become DONE, and the onloadend callback, if any, will be called. At that time, the result attribute contains the raw binary data from the file.

Any idea what I'm doing wrong here?

Sample Code http://jsfiddle.net/qL86Z/3/

$("#base64Button").on("click", function () {
    var file = $("#base64File")[0].files[0]
    var reader = new FileReader();

    // callback for readAsDataURL
    reader.onload = function (encodedFile) {
        console.log("reader.onload");
        var base64Image = encodedFile.srcElement.result.split("data:image/jpeg;base64,")[1];
        var blob = new Blob([base64Image],{type:"image/jpeg"});
        var reader2 = new FileReader();

        // callback for readAsBinaryString
        reader2.onloadend = function(decoded) {
            console.log("reader2.onloadend");
            console.log(decoded); // this should contain binary format of the image

            // console.log(URL.createObjectURL(decoded.binary)); // Doesn't work
        };
        reader2.readAsBinaryString(blob);

        // console.log(URL.createObjectURL(atob(base64Image))); // Doesn't work

    };
    reader.readAsDataURL(file);
    console.log(URL.createObjectURL(file)); // Works
});

Thanks!

like image 898
sissonb Avatar asked Feb 19 '13 21:02

sissonb


2 Answers

After some more research I found the answer from here I basically needed to wrap the raw binary in an arraybuffer and convert the binary chars to Unicode.

This is the code that was missing,

    var binaryImg = atob(base64Image);
    var length = binaryImg.length;
    var ab = new ArrayBuffer(length);
    var ua = new Uint8Array(ab);
    for (var i = 0; i < length; i++) {
        ua[i] = binaryImg.charCodeAt(i);
    }

The full sample code is here

like image 57
sissonb Avatar answered Nov 07 '22 22:11

sissonb


URL.createObjectURL expects a Blob (which can be a File) as its argument. Not a string. That's why URL.createObjectURL(file) works.

Instead, you are creating a FileReader reader that reads file as a data url, then you use that data url to create another Blob (with the same contents). And then you even create a reader2 to get a binary string from the just constructed blob. However, neither the base64Image url string part (even if btoa-decoded to a larger string) nor the decoded.binary string are vaild arguments to URL.createObjectURL!

like image 1
Bergi Avatar answered Nov 07 '22 22:11

Bergi