How do I encode and decode a geoTiff file from a base64string? - javascript

I have a geotiff file that is being converted to a base64string upon being selected. The encoded file is then uploaded to an ASP.NET web service and then decoded and saved with a .tiff extension. The problem is that the metadata within the file is significantly altered from the original file.
JavaScript
var fr = new FileReader();
fr.onloadend = function () {
var base64string = fr.result;
var imgStr = base64string.split("base64,")[1];
App.instance.client.area.uploadMap(imgStr);
};
fr.readAsDataURL(value.rawFile);
C#/ASP.NET Web API:
byte[] imageBytes = Convert.FromBase64String(mapImage);
MemoryStream ms = new MemoryStream(imageBytes);
Image img = Image.FromStream(ms);
I'm then extrating the metadata uploaded image with the GDAL library. The image looks fine, but the metadata contained within the file is completely different. The corner coordinates are no longer accurate and there is color table information in the new file, which wasn't present in the original.
Is there any way to handle this conversion so that the bytes aren't altered?

Related

Downloading image in Javascript creates corrupted file

I'm trying to download an image and write it to the disk in Javascript. The image will be delivered base64 encoded by the server. I'm then trying to decode the image, create a blob with that data and create a new URL object. The download itself works, but the output file will be corrupted and unusable. My code looks as follows:
jsonObject = JSON.parse(requestObject.getReturnData());
decoded = atob(jsonObject['DownloadFile']);
url = window.URL.createObjectURL(new Blob([decoded], { type: "image/png" }));
aElement = document.createElement('a');
aElement.style.display = 'none';
aElement.href = url;
aElement.download = 'download.' + jsonObject['DownloadType'];
document.body.appendChild(aElement);
aElement.click();
window.URL.revokeObjectURL(url);
I verified that jsonObject['DownloadFile'] contains the correct base64 representation of the image. However, it seems that there's an error when creating the blob, since its size is too big when looking at the debug console.

How to read large video files in JavaScript using FileReader?

I want the user of my website to be able to upload a potentially large video file to it using HTML‘s file input. The video should than be processed and played locally in the user‘s browser.
let fileInput = document.createElement("INPUT");
fileInput.setAttribute("type", "file");
fileInput.onChange = onFileSelected;
To read the video file uploaded by the user, I wanted to use a File Reader like this:
function onFileSelected(e) {
// The file uploaded by the user:
let file = e.target.files[0];
// Create a file reader:
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
video.src = e.target.result;
}
}
However, when I uploaded really large video files (≈300 MB), e.target.result was not a URI to the video file, like I expected, but an empty string.
How can I read very large video files using File Reader in JavaScript?
The FileReader class in JavaScript contains multiple methods to read files:
readAsText(): This reads a file and returns its content as text. Suitable for small text files.
readAsBinaryString(): This reads a file and returns its content as a binary string. Suitable for small files of any type.
readAsDataURL(): This reads a file and returns a Data URL referencing it. This is inefficient for large files as the file is loaded into memory as a whole before being processed.
readAsArrayBuffer(): This reads a file and returns an ArrayBuffer containing the input file 'chopped up in smaller pieces'. This works for very large files, too.
In the question, the readAsDataURL() method is used as it is usually most convenient. However, for very large video files (and very large files in general) it does not work for the reason described above leading to an empty result. Instead, you should use readAsArrayBuffer():
let reader = new FileReader();
reader.readAsArrayBuffer(file);
Now, the file reader returns an ArrayBuffer after loading the file. In order to be able to show the video in HTML, we have to convert this buffer to a blob, that can then give us a URL to the video file:
reader.onload = function(e) {
// The file reader gives us an ArrayBuffer:
let buffer = e.target.result;
// We have to convert the buffer to a blob:
let videoBlob = new Blob([new Uint8Array(buffer)], { type: 'video/mp4' });
// The blob gives us a URL to the video file:
let url = window.URL.createObjectURL(videoBlob);
video.src = url;
}

Converting File object to Image object in JavaScript

So I have a website (using AngularJS) that lets users upload files via tag
<input type="file" ng-model="image" id="trigger" onchange="angular.element(this).scope().setFile(this)" accept="image/*">
When I handle the upload in the controller the image gets stored as a File object. This is my method that saves the file and also sets variables to preview the image
$scope.setFile = function (element) {
$scope.image = element.files[0]; // This is my image as a File
var reader = new FileReader();
//This is for previewing the image
reader.onload = function (event) {
$scope.image_source = event.target.result;
$scope.$apply();
}
reader.readAsDataURL(element.files[0]);
}
Now I am trying to compress the image using J-I-C library found here: https://github.com/brunobar79/J-I-C/blob/master/src/JIC.js
But this library accepts an image object as its parameter and returns it as a compressed image object. I can't seem to find a way to convert my $scope.image File object into an Image object. How would I go about doing this?
I would also need to convert the compressed image object back into a File so I can upload it to my Azure storage.
You just need to create an Image instance, and set it's src to your data url. Then pass it to JIC:
var img = new Image();
img.src = $scope.image_source;
jic.compress(img,...)
It then just uses a canvas element to manipulate the image, generate a new data url, and creates a new Image instance, setting its src to the data url. So when you get the compressed image back just take the src and use atob to decode the base64 encoded data back into binary and create a Blob. You can use Blob in most places that you would use File, for instance like uploading through ajax.
var newImg = jic.compress(oldImg,...);
//replace 'image/png' with the proper image mime type
var base64data = newImg.src.replace("data:image/png;base64,","");
var bs = atob(base64data);
var buffer = new ArrayBuffer(bs.length);
var ba = new Uint8Array(buffer);
for (var i = 0; i < bs.length; i++) {
ba[i] = bs.charCodeAt(i);
}
var blob = new Blob([ba],{type:"image/png"});
//now use blob like you would any other File object

Unit8Array to base64 conversion and then displaying image in browser issue

I have a Unit8Array in a mongodb that represents a png image. I pull the array out and convert it to base64 using javascript (in meteor client side) so that I can display it in the browser. The code is as follows
var blob = new Uint8Array(Tester.findOne().image);
var base64String = btoa(String.fromCharCode.apply(null, blob));
var src = 'data:image/png;base64,' + base64String + '';
console.log(src);
Where Tester.findOne().image is my mongodb collection containing the Uint8Array.
I take the src once it is logged and I paste it into the browser. The generic broken image icon appears (see below). However when I click the broken image in the browser and say save to desktop, it downloads the file and when I open it the png image appears as expected.
After I Download the Image:
When I directly try to assign it to <img src = 'data'>:
Adding data as img source or by using document.findElementbyId("img") then changing img.src:

Decode base64 image and upload

I have a webapp that is saving images locally until they are ready to be sent to the server. When I save the images locally, I base64 encode them. Now I want to do a multipart file upload with these images.
So I need to convert the image back into binary form. I've tried using the FileReader to convert it back like this,
var fr = new FileReader();
fr.onloadend = function(binaryImage){
debugger;
binaryImage;
};
var base64Str = item.base64Image.substr(item.base64Image.indexOf("base64") + 7);
//var base64Str = item.base64Image;
fr.readAsBinaryString(base64Str);
but the onloadend event is never fired and there are no errors. Once I get the image I wont have trouble uploading it. Any ideas?
Thanks!
Not to familiar with FileReader, but I believe readAsBinaryString is expecting a Blob or File object. Passing it a string causes errors on my end. Try this:
var fr = new FileReader();
fr.onloadend = function(binaryImage){
debugger;
binaryImage;
};
var blob = new Blob([item.base64Image.
substr(item.base64Image.indexOf("base64") + 7)]);
fr.readAsBinaryString(blob);
I don't think this will give you want though. Check out this article for ways to encode/decode Base64: How can you encode to Base64 using Javascript?
Looks like you can use btoa() and atob() for web kit browsers.

Categories