从图像中读取二进制数据并用 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 PNG
to 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 ArrayBuffer
into 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 获得更好、更有效的方法。