根据你想要提高的效率轴(带宽 vs CPU 效率),我会推荐几种方法。
选项1: 可以使用 canvas toDataURL 方法。这将返回一个 canvas 图像数据的 base64 编码图像。它将使用指定的图像格式进行压缩(或使用默认的 PNG 格式),并且会被预编码为 base64 以便通过 WebSocket 发送。
canvas = document.getElementById("mycanvas");
b64png = canvas.toDataURL();
ws.send(b64png);
选项2:如果您可以接受有损压缩,则可以使用toDataURL方法请求图像的base64编码JPEG格式:
canvas = document.getElementById("mycanvas")
b64jpeg = canvas.toDataURL("image/jpeg")
ws.send(b64jpeg)
选项 3:如果您正在使用支持二进制 WebSocket 数据的浏览器(Chrome、Firefox、IE 10),那么您可以直接通过 WebSocket 发送画布数组缓冲区。
canvas = document.getElementById("mycanvas");
ctx = canvas.getContext('2d');
imgdata = ctx.getImageData(0,0, width, height).data; // This is a Uint8ClampedArray
ws.send(imgdata.buffer); // Send the ArrayBuffer from the Uint8ClampedArray
选项3在带宽方面可能不太高效,但在客户端和服务器端的处理能力方面最高效,因为图像数据是原始的,几乎不需要预处理或后处理。
最节省带宽的选项可能是#2,但在将图像数据转换为JPEG格式时会损失一些图像质量。甚至可以进一步将数据解码为数组缓冲区或 blob,并通过二进制 WebSocket 发送,以避免33%的 base64 带宽开销,但这会增加更多的 CPU 开销。
如果您想要高效的带宽而不失去任何图像质量,则选项#2 是您最好的选择。
一些注意事项/警告:
toDataURL 将 base64 数据前缀命名为类似于此的内容:
"data:image/png;base64,iVBORw0KGgoAAAA..."
数据URL格式的一个好处是你可以将整个URL复制到浏览器地址栏中,浏览器就会渲染出图片。
查看MDN Canvas页面以获取更多关于toDataURL的信息。