从图像中读取二进制数据并用 JavaScript 保存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21501413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Read binary data from an image and save it with JavaScript
提问by Benny Neugebauer
I want to read the binary data of an image and then save it again to my local disk with JavaScript.
我想读取图像的二进制数据,然后使用 JavaScript 将其再次保存到我的本地磁盘。
I wrote a small demo that shows this use-case. To read the file I use readAsBinaryStringfrom the File Reader API(HTML5) to get the binary data.
我写了一个小演示来展示这个用例。读书,我使用的文件readAsBinaryString从文件读取API(HTML5)来获取二进制数据。
I write the binary string into a textfield from which I then read the data again to write it to a file. If I save the file my images (I tested several JPEGs) are broken so you cannot see anything useful.
我将二进制字符串写入一个文本字段,然后再次读取数据以将其写入文件。如果我保存文件,我的图像(我测试了几个 JPEG)会损坏,所以你看不到任何有用的东西。
Can it be that "readAsBinaryString" makes a conversion which makes the binary data incorrect?
难道“readAsBinaryString”进行了转换,使二进制数据不正确?
To have a look at my demo application I made a fiddle. The main part starts here:
为了看看我的演示应用程序,我做了一个fiddle。主要部分从这里开始:
reader.readAsBinaryString(file);
回答by dbermudez
I have tested this code on your fiddle and it has 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'm not an expert on the new HTML5 APIs, but I will try to explain a bit what I have done.
我不是 new 的专家HTML5 APIs,但我会试着解释一下我所做的。
1) I have saved a PNGto disk. (photo.png)
1)我已将一个保存PNG到磁盘。(照片.png)
2) If you have Linux, you can see the contents of the file in hexadecimal format with this command od -cx photo.png. If not you need some hexadecimal editor.
2)如果你有Linux,你可以用这个命令以十六进制格式查看文件的内容od -cx photo.png。如果没有,您需要一些十六进制编辑器。
The first lines of photo.png in hexadecimal show something like this:
十六进制 photo.png 的第一行显示如下:
211 P N G \r \n 032 \n ##代码## ##代码## ##代码## \r I H D R
5089 474e 0a0d 0a1a 0000 0d00 4849 5244
Each pair of numbers in the second line represent the hexadecimal codification of the symbol above: 5089 is the codification of 211 P, 50 is the hex value for P and 89 for 211 (little endian codification, the first two bytes encodes the second symbol, the last two encodes the first symbol)
第二行中的每一对数字代表上述符号的十六进制编码:5089是211 P的编码,50是P的十六进制值,89是211(小端编码,前两个字节编码第二个符号,最后两个编码第一个符号)
3) Instead of read the file as a binaryString, I read it as an ArrayBuffer(it doesn't make encoding conversions).
3)binaryString我没有将文件读作,而是将其读作ArrayBuffer(它不进行编码转换)。
4) When the file is read, I transform the ArrayBufferinto a Uint16Array, and store each value in an array to show its decimal value on your text area. It shows the values as a list of decimal numbers, comma separated.
The first decimal number will in this case will be 20617, which is the decimal equivalent for the 5089 hexadecimal.
4) 读取文件时,我将 转换ArrayBuffer为Uint16Array,并将每个值存储在一个数组中,以在文本区域显示其十进制值。它将值显示为十进制数字列表,逗号分隔。在这种情况下,第一个十进制数将是 20617,它是 5089 十六进制的十进制等效值。
5) Prior to saving the file, some simple code splits the decimal values and add them to a new Uint16Array.
5) 在保存文件之前,一些简单的代码会拆分十进制值并将它们添加到一个新的Uint16Array.
It worked for me... It's a bit confusing and probably someone will get a better & more efficient approach using the APIs in another way.
它对我有用......这有点令人困惑,可能有人会以另一种方式使用 API 获得更好、更有效的方法。

