首页 > 解决方案 > 从 Javascript Uint8ClampedArray 获取位

问题描述

我有一个节点服务器正在运行,在服务器中我生成并存储到 Redis 中的一堆代表画布上颜色的位。存储位的每四位代表一种 4 位颜色。(例如,如果我存储 001001101011111,那么我感兴趣的颜色是 0010、0110、1011 和 1111)。

var byteArr = new ArrayBuffer(360000);
redis_client.set("board", byteArr);
redis_client.setbit("board", 360000, 0);

// There is some garbage at the beginning of the stored value, so zeroing them out.
for(var i = 0; i < 160; i++){
    redis_client.setbit("board", i, 0);
}

当客户端连接到服务器时,我从 Redis 获取这个字符串,并通过 Websocket 发送它:

wss.on('connection', function(ws) {
    redis_client.get("board", function (error, result) {
        var initial_send = {"initial_send":true, "board":result};
        ws.send(JSON.stringify(initial_send));
    });

在客户端,我是这样阅读董事会的:

socket.onmessage = function (event) {
    var o = JSON.parse(event.data);
    board = o["board"];                                        
    var clampedBoard = new Uint8ClampedArray(board.length); 

    for(var i = 0; i < board.length; i++){                     
        clampedBoard = board[i];                               
    }
}

此时,长度board为45000,我相信这是因为在Javascript中,最小的TypedArray构造函数只允许1个字节为单位。所以因为我最初的 ArrayBuffer 的大小是 360000,所以当我在客户端收到它时,它的大小是 360000/8。

这就是我遇到问题的地方。在这一点上,如果我得到clampedBoard[0],它应该给我前 8 位(我关心的前两种颜色),我可以这样做clampedBoard[0]>>4,并clampedBoard[0]&15得到这两种颜色,然后我可以在地图中查找它们键是 0000、0001 等。

但这不是正在发生的事情。

这是我尝试过的以及我所知道的:

  1. 在客户端打印值:console.log(clampedBoard[0])在 Chrome 的控制台上返回一个 [] 看起来为空/未定义的字符。

  2. 在服务器端,byteArr将前 160 个值初始化并清除为 0 时,我手动将前 8 位设置为 '00111111',即 ASCII 字符 '?' 的二进制表示。

当 console.loggingclampBoard[0]在客户端时,我得到相同的 [] null/undefined 字符,但是当 console.logging 时board[0],它打印出一个“?”。我不确定为什么会这样。

并且当尝试通过 do 在我的颜色图中查找时clampedBoard[0]>>4,它始终默认为字典中表示 0 的键,即使它应该是 0011。

如果我可以提供更多信息,请告诉我。

标签: javascriptbit

解决方案


首先,你可以这样做:

board = o["board"];                                        
var clampedBoard = new Uint8ClampedArray(board); 

所以你不需要值初始化循环。

此外,您将其传递给对象的方式,“字符串化”会将其转换为字符串而不是数组。为了获得一个数组,您需要从 ArrayBuffer 中创建一个 Node.js 的缓冲区,然后将其转换为本机数组,如下所示:

var view = Buffer.from(result); 
var initial_send = {"initial_send":true, "board":[...view]}; 

推荐阅读