如何在JavaScript中创建图像的文本二进制表示?

4

我想将一张图片转换成二进制表示(0和1),并且希望使用JavaScript来完成,因为我的设备没有配置PHP、.NET等。目前,我已经成功使用FileReader读取了文件,得到了一个ArrayBuffer

但是,我不知道如何将这个ArrayBuffer转换成位表示。

你可以在这个jsfiddle链接中查看我的当前版本。

function ArrayBufferToBit(buffer) {
    // How to convert my array buffer to a textual bit-representation? 0 1 1 0 0 0...
    return buffer;
  }

非常感谢您的帮助!

2个回答

2
使用DataView对象:
function ArrayBufferToBit(buffer) {
    var dataView = new DataView(buffer);
    var response = "", offset = (8/8); 
    // I assume we will read the entire file as a series of 8-bit integers, 
    // i.e. as a byte, hence my choice of offset.
    for(var i = 0; i < dataView.byteLength; i += offset) {
        response += dataView.getInt8(i).toString(2); 
        // toString is the secret sauce here.
    }
    return response;
}
可以读写数字数据,getInt8方法将ArrayBuffer中从字节位置(这里是0,即传入的值)开始的数据转换为有符号8位整数表示,toString(2)方法将8位整数转换为二进制表示格式(即由1和0组成的字符串)。请注意保留HTML标签。

“魔术”偏移值是通过注意到我们正在读取以字节形式存储的文件(即作为8位整数)并以8位整数表示形式读取它来获得的。如果我们试图将以字节保存(即8位)的文件读取为32位整数,则应该注意到32/8 = 4是字节偏移值。

此外,结合使用DataViewtyped array是从ArrayBuffer中读写的推荐方法。您不能直接操作ArrayBuffer的内容;相反,您需要创建一个特定格式的typed array对象或DataView对象来代表缓冲区,并使用它们来读取和写入缓冲区的内容。

除了带符号8位表示,还可以获得各种表示(如float64int32)。选择表示形式不应该有影响,因为toString(2)将以二进制的方式显示它(尽管出于明显的原因,您的二进制字符串长度肯定会改变!)。

请注意,在此示例中,我选择将整个文件表示为一系列8位整数,即逐字节读取。然而,DataView便于混合同一类型 - 您可以将前12个字节读取为32位整数,其余部分为64位整数,例如。通常情况下,由于可以处理不同的文件格式,并且DataView还可以处理来自不同体系结构的文件的字节序问题,因此在处理文件时通常更喜欢使用DataView

像这样的任务可以通过typed arrayDataView来处理 - 但是,DataView可以处理字节序(如果从不同CPU的网络传输文件)问题和不同的文件格式(例如PDF文件,在主要内容之前有一些字节头)。

谢谢您的回复。我认为您的示例仍然有些问题。dataView.getInt32(0).toString(2) 对于一张图片给出了结果 1000111010010010100011000111000。看起来有点短... - Jules
@Jules,我已经修订并更新了我的答案,提供了更好的内容。 - Akshat Mahajan
@AkshatMahajan,最近我也遇到了与OP相同的问题,我按照你的答案和解释进行操作。对于像我这样的初学者来说,它非常好而且详细。然后我编写了一个完整的演示程序,在屏幕上打印二进制/十六进制数据。但是我在这个二进制处理领域真的很新。我可以得到结果,但我不确定我是否理解/做得正确,您能否检查一下,看看有什么可以改进的地方吗?fiddle here - Lien

1
你需要遍历数组缓冲区的内容。你可以使用 DataView 或者一个类型化数组来实现。
由于我们将要读取单个字节,我们不需要担心系统的大小端问题,可以安全地使用 Uint8Array,这使我们能够使用 Array.reduce() 将所有元素组合成一个二进制字符串。
要将一个字节转换为二进制,我们可以使用 Number.toString(base) 方法。

function arrayBufferToBinary(buffer) {
  var uint8 = new Uint8Array(buffer);
  return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}

function fileToBinary(file, callback) {  
  var reader = new FileReader();
  reader.onload = (event) => callback(arrayBufferToBinary(reader.result));
  reader.readAsArrayBuffer(file);
}

var input = document.getElementById("file");
var output = document.getElementById("binary");

input.addEventListener("change", function(event) {
  var file = input.files[0];
  if (file) fileToBinary(file, (binary) => output.textContent = binary);
});
#binary {
  word-wrap: break-word;
}
<input id="file" type="file">
<div id="binary"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接