2012-02-15 89 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