2016-07-12 41 views
3

Für ein kleines Projekt möchte ich ein Bild in eine binäre Darstellung (Nullen und Einsen) konvertieren. Da ich dies auf einer Maschine verwenden möchte, die nicht für PHP, .NET, ... konfiguriert ist, möchte ich das in JavaScript machen.Wie erstelle ich eine textuelle Binärdarstellung eines Bildes in JavaScript?

Im Moment konnte ich die Datei mit der FileReader lesen, die mir eine ArrayBuffer gibt.

Aber ich bin ratlos, wie diese ArrayBuffer in eine Bit-Darstellung konvertieren.

Meine aktuelle Version finden Sie auf dieser jsfiddle.

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

Ihre Hilfe wird sehr geschätzt!

Antwort

2

Verwenden Sie ein 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; 
} 

Dataview s können Sie lesen/numerische Daten schreiben; getInt8 wandelt die Daten von der Byteposition - hier ist 0 der übergebene Wert - in ArrayBuffer in eine 8-Bit-Integer-Ganzzahldarstellung um und toString(2) wandelt das 8-Bit-Ganzzahl- in Binärdarstellungsformat um (d. H. Eine Folge von Einsen und Nullen). Der "magische" Offset-Wert wird erhalten, indem man feststellt, dass wir Dateien, die als Bytes gespeichert sind, d. H. Als 8-Bit-Ganzzahlen aufnehmen und sie in einer 8-Bit-Ganzzahldarstellung lesen. Wenn wir versuchen würden, unsere bytegespeicherten (d. H. 8 Bits) Dateien in 32-Bit-Ganzzahlen zu lesen, würden wir bemerken, dass 32/8 = 4 die Anzahl der Bytespeicher ist, was unser Byte-Offset-Wert ist.


Dies, zusätzlich Arrays eingegeben, ist die recommended way/Schreibvorgang von einem ArrayBuffer zur:

Das Arraybuffer-Objekt eines generischen, mit fester Länge rohen binären Datenpuffer darzustellen verwendet wird. Sie können den Inhalt eines ArrayBuffers nicht direkt bearbeiten. Stattdessen erstellen Sie eines der typisierten Array-Objekte oder ein DataView-Objekt, das den Puffer in einem bestimmten Format darstellt, und verwenden Sie diesen, um den Inhalt des Puffers zu lesen und zu schreiben.

Zusätzlich zu signierten 8-Bit-Darstellung, Sie können auch eine Vielzahl von Darstellungen (wie float64 oder sogar int32) erhalten. Die Wahl der Darstellung sollte nicht wichtig sein, da toString(2) es sowieso im Binärformat anzeigt (obwohl sich die Länge Ihrer binären Zeichenfolge aus offensichtlichen Gründen sicherlich ändert!).

Beachten Sie, dass ich in diesem Beispiel gewählt habe, um die gesamte Datei als eine Reihe von 8-Bit-Ganzzahlen darzustellen, d. H. Byteweise zu lesen. Im Allgemeinen jedoch DataView s erleichtern das Mischen homogene Typen - Sie können die ersten 12 Bytes als 32-Bit-Ganzzahlen lesen, und die restlichen als 64-Bit, zum Beispiel. DataView s werden normalerweise bei der Verarbeitung von Dateien bevorzugt, da auf diese Weise unterschiedliche Dateiformate verarbeitet werden können und DataView auch die Endianität von Dateien unterschiedlicher Architekturen verarbeitet.

Eine Aufgabe, wie dieser kann in @ die le_m Antwort von typisierten Arrays, wie behandelt werden, oder durch DataView s - allerdings DataView s sowohl endianness umgehen kann und ein unterschiedliche Datei (wenn Dateien über das Netzwerk aus verschiedenen CPUs übertragen werden) Formate (zPDF-Dateien, die einige Byte-Header vor dem Hauptinhalt haben).

+0

Vielen Dank für Ihre Antwort. Ich denke, in deinem Beispiel ist immer noch etwas falsch. Das 'dataView.getInt32 (0) .toString (2)' gibt mir als Ergebnis '1000111010010010100011000111000' für ein Bild. Scheint ein bisschen kurz ... – Jules

+0

@Jules Ich habe meine Antwort mit etwas besser überarbeitet und aktualisiert. –

+0

@AkshatMahajan Ich habe in letzter Zeit in dasselbe Problem wie OP geraten, und ich folge Ihnen Antwort und Erklärung. es ist gut und so detailliert für einen Anfänger wie mich. Dann schreibe ich eine vollständige Demo, um binäre/hex Daten auf dem Bildschirm zu drucken. Aber ich bin wirklich neu in diesem binären Bereich. Ich kann das Ergebnis ** bekommen, aber ich bin mir nicht sicher, ob ich es richtig verstanden habe. Kannst du es vielleicht nachsehen, was es gibt, was ich verbessern kann? [Geige hier] (https://jsfiddle.net/69c5wcmL/1/) ** – Lien

1

Sie müssen den Inhalt des Array-Puffers durchlaufen. Sie könnten ein DataView für dieses oder ein typisiertes Array verwenden.

Da wir einzelne Bytes lesen wollen, brauchen wir nicht über große oder kleine endianness unseres Systems zu kümmern und kann sicher eine Uint8Array benutzen, die uns erlaubt Array.reduce() zu verwenden, um alle Elemente zu einem einzigen binären zu kombinieren Zeichenfolge.

Um ein Byte in binäre umzuwandeln, können wir die Number.toString(base) Methode verwenden.

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>