webentwicklung-frage-antwort-db.com.de

Zeigen Sie das Bild aus dem Blob mit Javascript und Websockets an

Ich arbeite derzeit an einer WebSocket-Anwendung, die von einem C++ - Server gesendete Bilder anzeigt. Ich habe dort ein paar Themen gesehen, aber ich kann diesen Fehler in Firefox scheinbar nicht beseitigen:

Bild beschädigt oder abgeschnitten: data: image/png; base64, [einige Daten]

Hier ist der Javascript-Code, mit dem ich meinen Blob anzeige:

socket.onmessage = function(msg) {
    var blob = msg.data;

    var reader = new FileReader();
    reader.onloadend = function() {
        var string = reader.result;
        var buffer = Base64.encode(string);
        var data = "data:image/png;base64,"+buffer;

        var image = document.getElementById('image');
        image.src = data;
    };
    reader.readAsBinaryString(blob);
}

Ich verwende das Bild eines roten Punkts, das ich zu diesem Thema gefunden habe: https://stackoverflow.com/a/4478878/1464608 Und die Base64-Klasse ist von hier: https : //stackoverflow.com/a/246813/1464608

Aber das Base64-Ergebnis, das ich erhalte, stimmt nicht überein und Firefox meldet mir einen Fehler, dass das Image beschädigt ist.

Ich weiß, dass dies nicht viele Informationen sind, aber ich habe keine Ahnung, wo ich suchen soll:/Jede Hilfe ist mehr als willkommen !!

26
guitio2002

Ich denke, die sauberste Lösung wäre, den Base64-Encoder so zu ändern, dass er direkt auf einem Uint8Array anstelle eines Strings funktioniert.

Wichtig: Dazu müssen Sie den binaryType des Web-Sockets auf "arraybuffer" setzen.

Die onmessage-Methode sollte folgendermaßen aussehen:

socket.onmessage = function(msg) {
    var arrayBuffer = msg.data;
    var bytes = new Uint8Array(arrayBuffer);

    var image = document.getElementById('image');
    image.src = 'data:image/png;base64,'+encode(bytes);
};

Der konvertierte Encoder sollte dann folgendermaßen aussehen (basierend auf https://stackoverflow.com/a/246813/1464608 ):

// public method for encoding an Uint8Array to base64
function encode (input) {
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
        chr1 = input[i++];
        chr2 = i < input.length ? input[i++] : Number.NaN; // Not sure if the index 
        chr3 = i < input.length ? input[i++] : Number.NaN; // checks are needed here

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }
        output += keyStr.charAt(enc1) + keyStr.charAt(enc2) +
                  keyStr.charAt(enc3) + keyStr.charAt(enc4);
    }
    return output;
}
26
Stefan Haustein

Danke, es funktioniert super !!

Also denke ich, ich würde meinen endgültigen Javascript-Code teilen:

var socket = new WebSocket('ws://'+Host+':'+port, protocol);
socket.binaryType = 'arraybuffer';

try {
    socket.onopen = function() {
        document.getElementById('status').style.backgroundColor = '#40ff40';
        document.getElementById('status').textContent = 'Connection opened';
    }

    socket.onmessage = function(msg) {
        var arrayBuffer = msg.data;
        var bytes = new Uint8Array(arrayBuffer);

        var image = document.getElementById('image');
        image.src = 'data:image/png;base64,'+encode(bytes);
    }

    socket.onclose = function(){
        document.getElementById('status').style.backgroundColor = '#ff4040';
        document.getElementById('status').textContent = 'Connection closed';
    }
} catch(exception) {
    alert('Error:'+exception);
}

ich verstehe nicht wirklich, warum die Blob-Version so trickreich ist, aber das hat es geschafft!

13
guitio2002

Sie können es viel einfacher schreiben:

socket.onmessage = function(msg) {
   var arrayBuffer = msg.data;
   var bytes = new Uint8Array(arrayBuffer);
   var blob        = new Blob([bytes.buffer]);

   var image = document.getElementById('image');

   var reader = new FileReader();
   reader.onload = function(e) {
       image.src = e.target.result;
   };
   reader.readAsDataURL(blob);
};
13

Eine andere Alternative

let urlObject;

socket.onmessage = function(msg) {
    const arrayBuffer = msg.data;
    const image = document.getElementById('image');

    if (urlObject) {
        URL.revokeObjectURL(urlObject) // only required if you do that multiple times
    }
    urlObject = URL.createObjectURL(new Blob([arrayBuffer]));

    image.src = urlObject;

};
2
Walle Cyril

Dank der anderen Antworten konnte ich ein JPEG-Bild per Websocket empfangen und in einem neuen Fenster anzeigen:

socket.binaryType = "arraybuffer";                 
socket.onmessage = function (msg) 
               {    var bytes = new Uint8Array(msg.data);
                    var blob = new Blob([bytes.buffer]);
                    window.open(URL.createObjectURL(blob),'Name','resizable=1');
                };
2
J.Jacobs-VP