【问题标题】:Read binary data from an image and save it with JavaScript从图像中读取二进制数据并使用 JavaScript 保存
【发布时间】:2014-02-01 17:49:20
【问题描述】:

我想读取图像的二进制数据,然后使用 JavaScript 将其再次保存到我的本地磁盘。

我写了一个小演示来展示这个用例。为了读取文件,我使用 File Reader API (HTML5) 中的readAsBinaryString 来获取二进制数据。

我将二进制字符串写入文本字段,然后再次从中读取数据以将其写入文件。如果我保存文件,我的图像(我测试了几个 JPEG)会损坏,所以你看不到任何有用的东西。

会不会是“readAsBinaryString”进行了转换,导致二进制数据不正确?

为了查看我的演示应用程序,我创建了一个fiddle。主要部分从这里开始:

reader.readAsBinaryString(file);

【问题讨论】:

    标签: javascript html image filereader binary-data


    【解决方案1】:

    我已经在你的小提琴上测试了这段代码,它就像一个魅力:

      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);
      }
    

    我不是新HTML5 APIs 方面的专家,但我会尝试解释一下我做了什么。

    1) 我已将PNG 保存到磁盘。 (照片.png)

    2) 如果你有Linux,你可以用这个命令od -cx photo.png查看十六进制格式的文件内容。如果没有,您需要一些十六进制编辑器。

    photo.png 的第一行十六进制显示如下:

           211   P   N   G  \r  \n 032  \n  \0  \0  \0  \r   I   H   D   R
    
           5089    474e    0a0d    0a1a    0000    0d00    4849    5244
    

    第二行每一对数字代表上面符号的十六进制编码:5089是211 P的编码,50是P的十六进制值,89是211的编码(小端编码,前两个字节编码第二个符号,后两个编码第一个符号)

    3) 我没有将文件读取为binaryString,而是将其读取为ArrayBuffer(它不会进行编码转换)。

    4) 读取文件时,我将ArrayBuffer 转换为Uint16Array,并将每个值存储在一个数组中以在您的文本区域显示其十进制值。它将值显示为十进制数字列表,逗号分隔。 在这种情况下,第一个十进制数将是 20617,它是 5089 十六进制的十进制等效值。

    5) 在保存文件之前,一些简单的代码会拆分十进制值并将它们添加到新的Uint16Array

    它对我有用...这有点令人困惑,可能有人会以另一种方式使用 API 获得更好、更有效的方法。

    【讨论】:

    • 非常感谢这个伟大而详细的答案!我刚刚在 Windows 8 上使用十六进制编辑器跟踪了所有内容。效果很好!甚至可以读取和写入 JPEG 文件。我已经修改了我的小提琴,以便大家可以看到解决方案:jsfiddle.net/qz498/1 - 非常感谢!
    • 那个小提琴在保存时损坏了我的图像。这仍然对您有用吗?
    • 对不起,克里斯蒂安,直到几天前我才看到你的问题。如果您查看 Benny 的小提琴,您会发现它的 js 代码与我提出的不同。如果你使用这个小提琴jsfiddle.net/ocqu253m/1我希望你会发现它可以正常工作。抱歉有点晚了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    相关资源
    最近更新 更多