Reading binary data from an image and saving it using JavaScript

I want to read binary image data and then save it to my local disk again using JavaScript.

I wrote a short demo showing this use case. To read a file, I use readAsBinaryString from the file reader API (HTML5) to get binary data.

I am writing a binary string to a text field from which I am reading data again in order to write it to a file. If I save the file, my images (I tested several JPEG files) are broken, so you will not see anything useful.

Could it be that "readAsBinaryString" makes a conversion that makes binary data invalid?

To see my demo application, I made a script . The main part starts here:

reader.readAsBinaryString(file); 
+7
javascript html5 binary-data image filereader
source share
1 answer

I tested this code on your violin and it worked like a charm:

  var contentType = ''; window.saveImage = function() { var textToWrite = document.getElementById("inputTextToSave").value; var splittedTextToWrite = textToWrite.split(","); var u16 = new Uint16Array(splittedTextToWrite.length); for(i=0; i<splittedTextToWrite.length; i++){ u16[i]=splittedTextToWrite[i]; } var textFileAsBlob = new Blob([u16], {type: contentType}); var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value; var downloadLink = document.createElement("a"); downloadLink.download = fileNameToSaveAs; downloadLink.innerHTML = "Download File"; if (window.webkitURL !== null) { // Chrome allows the link to be clicked // without actually adding it to the DOM. downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob); } else { // Firefox requires the link to be added to the DOM // before it can be clicked. downloadLink.href = window.URL.createObjectURL(textFileAsBlob); downloadLink.onclick = destroyClickedElement; downloadLink.style.display = "none"; document.body.appendChild(downloadLink); } downloadLink.click(); } function destroyClickedElement(event) { document.body.removeChild(event.target); } window.loadImage = function() { var file = document.getElementById("fileToLoad").files[0]; var reader = new FileReader(); reader.onload = function(event) { var data = event.target.result; var data16 = new Uint16Array(data); var text = []; for(i = 0; i<data16.length; i++){ text.push(data16[i]); } document.getElementById("inputTextToSave").value = text; var imagePreview = document.getElementById("imagePreview"); imagePreview.innerHTML = ''; var dataURLReader = new FileReader(); dataURLReader.onload = function(event) { // Parse image properties var dataURL = event.target.result; contentType = dataURL.split(",")[0].split(":")[1].split(";")[0]; var image = new Image(); image.src = dataURL; image.onload = function() { console.log("Image type: " + contentType); console.log("Image width: " + this.width); console.log("Image height: " + this.height); imagePreview.appendChild(this); }; }; dataURLReader.readAsDataURL(file); }; //reader.readAsBinaryString(file); reader.readAsArrayBuffer(file); } 

I am not an expert in the new HTML5 APIs , but I will try to explain a bit what I did.

1) I saved the PNG to disk. (Photo.png)

2) If you have Linux, you can see the contents of the file in hexadecimal using this command od -cx photo.png . If not, you need some kind of hex editor.

The first lines of photos.png in hexadecimal form show something like the following:

  211 PNG \r \n 032 \n \0 \0 \0 \r IHDR 5089 474e 0a0d 0a1a 0000 0d00 4849 5244 

Each pair of numbers in the second line represents the hexadecimal character encoding of the character above: 5089 is the 211 P encoding, 50 is the hexadecimal value for P and 89 for 211 (small end encoding, the first two bytes encode the second character, the last two encode the first character)

3) Instead of reading the file as binaryString , I read it as ArrayBuffer (it does not do encoding conversion).

4) When the file is being read, I convert the ArrayBuffer to Uint16Array and save each value in an array to show its decimal value in your text area. It shows the values ​​as a comma-separated list of decimal numbers. The first decimal number in this case will be 20617, which is the decimal equivalent for the hexadecimal number 5089.

5) Before saving the file, some simple code breaks the decimal values ​​and adds them to the new Uint16Array .

This worked for me ... This is a bit confusing, and probably someone will get a more efficient and effective approach using the API in a different way.

+9
source share

All Articles