【问题标题】:How to create a textual binary representation of an image in JavaScript?如何在 JavaScript 中创建图像的文本二进制表示?
【发布时间】:2016-07-12 16:24:00
【问题描述】:

对于一个小项目,我想将图像转换为二进制表示(零和一)。由于我想在未配置为运行 PHP、.NET 的机器上使用它...我想在 JavaScript 中执行此操作。

目前我设法使用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;
  }

非常感谢您的帮助!

【问题讨论】:

    标签: javascript binary filereader bit arraybuffer


    【解决方案1】:

    使用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;
    }
    

    Dataviews 让你读/写数字数据; getInt8 将数据从字节位置 - 这里是 0,传入的值 - 在 ArrayBuffer 中转换为带符号的 8 位整数表示,toString(2) 将 8 位整数转换为二进制表示格式(即字符串1 和 0)。

    'magic' 偏移值是通过注意我们将文件存储为字节(即 8 位整数)并以 8 位整数表示形式读取它来获得的。如果我们尝试将字节保存(即 8 位)文件读取为 32 位整数,我们会注意到 32/8 = 4 是字节空间的数量,即我们的字节偏移值。


    除了类型化数组之外,这是从 ArrayBuffer 读取/写入的 recommended way

    ArrayBuffer 对象用于表示一个通用的、固定长度的原始二进制数据缓冲区。您不能直接操作 ArrayBuffer 的内容;相反,您可以创建一个类型化数组对象或 DataView 对象,它以特定格式表示缓冲区,并使用它来读取和写入缓冲区的内容。

    除了有符号的 8 位表示之外,您还可以获得各种表示(如float64 甚至int32)。表示的选择应该无关紧要,因为toString(2) 无论如何都会以二进制形式显示它(尽管您的二进制字符串的长度肯定会因为显而易见的原因而改变!)。

    请注意,在此示例中,我选择将整个文件表示为一系列 8 位整数,即逐字节读取。然而,一般来说,DataViews 促进了同类类型的混合——例如,您可以将前 12 个字节读取为 32 位整数,其余字节读取为 64 位。在处理文件时,DataViews 通常是首选,因为可以通过这种方式处理不同的文件格式,并且因为DataViews 还可以处理来自不同架构的文件的字节顺序。

    这样的任务可以由类型化数组处理,如@le_m 的回答,或DataViews - 但是,DataViews 可以处理两种字节序(如果文件通过网络从不同的 CPU 传输)问题和不同的文件格式(例如 PDF 文件,在主要内容之前有一些字节标题)。

    【讨论】:

    • 感谢您的回复。我认为你的例子仍然有问题。 dataView.getInt32(0).toString(2) 给了我一个结果 1000111010010010100011000111000 的图像。好像有点短……
    • @Jules 我已经用更好的东西修改并更新了我的答案。
    • @AkshatMahajan 我最近遇到了和 OP 一样的问题,我跟着你的回答和解释。对于像我这样的初学者来说,它很好而且很详细。然后我写了一个完整的演示来在屏幕上打印二进制/十六进制数据。但我对这个二进制句柄领域真的很陌生。我可以得到结果但我不确定我是否理解/做对了,你能检查一下有什么我可以改进的吗? fiddle here
    【解决方案2】:

    您需要遍历数组缓冲区的内容。您可以为此使用 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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多