2012-02-15 144 views
10

我使用websockify將圖像從python服務器顯示到HTML5畫布。通過websocket接收圖像

我認爲我已經成功地從我的python服務器發送圖像,但我無法將圖像顯示在畫布上。

我認爲這個問題有,我想顯示在畫布上的字節數做,我相信我不是在等待接收到整個圖像,直到然後顯示圖像在畫布上。

到現在爲止我有:

on消息函數。當我發送的圖像,我得到12 MESSAGERECEIVED控制檯

ws.on('message', function() { 
    //console.log("MESSAGERECEIVED!") 
      msg(ws.rQshiftStr()); 
    }); 

味精功能,我接收字符串,我試圖將其顯示在畫布上。我爲每幅圖片調用方法12次。刺痛的格式是'xÙõKþ°pãüCY

function msg(str) { 
     //console.log(str); 
     console.log("RELOAD"); 

     var ctx = cv.getContext('2d'); 
     var img = new Image(); 
     //console.log(str); 
     img.src = "data:image/png;base64," + str; 
     img.onload = function() { 
      ctx.drawImage(img,0,0); 
     } 
    } 

關於如何解決此問題有什麼建議?

+0

除非客戶端不支持hybi草稿,否則不應該通過websockets將圖像作爲base64傳輸。 Base64將產生33%的開銷。因此發送二進制文件是最好的。 – einaros 2012-02-15 11:13:47

+0

我認爲'websockify'正在將通過它傳輸的所有內容轉換爲base64。 – glarkou 2012-02-15 11:15:49

+0

如果是這樣,那太糟糕了。尋找另一個websocket實現。 – einaros 2012-02-15 12:18:25

回答

11

websockify + websock.js的重點是能夠透明地支持流的二進制數據(低於更多)。您從接收隊列中獲得的數據已經被base64解碼。但是,數據URI方案期望使用base64編碼的字符串,因此您需要將圖像數據編碼爲base64。您可以使用內置的window.btoa()來使用Base64編碼的二進制編碼字符串:

img.src = "data:image/png;base64," + window.btoa(str); 

或者,更高的效率,你可以使用Base64編碼模塊從包括/ base64.js但你需要傳遞一個字節你的陣列將得到rQshiftBytes:

msg(ws.rQshiftBytes()); 

img.src = "data:image/png;base64," + Base64.encode(data); // str -> data 

關於websockify使用的base64的:

websockify使用的base64對數據進行編碼,支持不支持二進制數據可怕的瀏覽器ctly。除了諸如iOS Safari和桌面Safari之類的流行Hixie瀏覽器之外,一些瀏覽器版本還在使用HyBi,但缺少二進制支持。不幸的是,在Chrome的情況下,他們在同一時間也出現了WebIDL錯誤,這使得在進行連接之前無法檢測二進制支持。

此外,在Opera,firefox 3.6-5,IE 8和9上使用WebSockets的主要選項是web-socket-js。 web-socket-js支持HyBi,但沒有二進制支持,可能不會,因爲它所針對的大多數舊瀏覽器都不支持本機二進制類型(Blob和Typed Arrays)。

支持HyBi和二進制數據的瀏覽器市場份額目前相當低。然而,在未來,Websockify將檢測(或者通過對象檢測或瀏覽器版本檢測)瀏覽器是否支持二進制數據,並使用該直接支持,而不需要的base64編碼/解碼。

base64編碼/解碼的等待時間(和CPU)開銷非常低,通常無論如何都會被網絡等待時間所淘汰。 Base64編碼數據的帶寬開銷大約爲25%(即原始數據變大33%),但它確實給你的二進制數據在在野外基本上所有的瀏覽器的WebSockets(與網絡插座JS填充工具/墊片這是如果需要,可以通過websockify透明地使用)。

+0

再次感謝您的詳細結果。您能否提供一個例子,說明如何確定圖像是否完全傳輸?更具體地說,在Python中,我使用緩衝區大小爲1024的常規套接字發送數據。如果我有一個比緩衝區大的圖像,那麼它將以1024的部分發送。在瀏覽器中,這將觸發12次(如果我有12kb)websocket消息事件的圖像。如何將所有這些消息合併以重建圖像?再次感謝。 – glarkou 2012-02-15 15:52:02

+0

WebSocketServer.send_frames(bufs)獲取「緩衝區」列表。每個緩衝區將作爲單個消息(onmessage的一個消息)傳遞給客戶端(瀏覽器)。如果您將onmessage中的所有內容都從接收隊列中移走,那麼您將收到完整的消息。如果您使用較小的塊調用send_frames(或完全繞過send_frames),則需要向協議添加一些重構消息的機制(即在每個消息/圖像之前添加長度前綴)。但是這是複製WebSocket功能,所以我建議使用send_frames和整個消息/圖像。 – kanaka 2012-02-15 16:11:56

+0

不幸的是,我無法理解如何做到這一點。目前我有一臺在服務器1上發送圖像的python服務器,並且我在'服務器2'上運行'websockify'。當我收到消息時,我試圖做'var arr = ws.rQshiftBytes(ws.rQlen()),str =「」,chr; \t \t \t \t \t \t \t \t而(arr.length> 0){ \t \t \t \t \t CHR = arr.shift(); \t \t \t \t \t str + = String.fromCharCode(chr); \t \t \t \t \t} \t \t \t \t //console.log(str); msg(str);'不幸的是。 'ws.on('message',function()'爲從服務器發送的每個緩衝區調用,因此我無法確定圖片何時準備好以便在畫布上繪製。 – glarkou 2012-02-15 16:23:38