在浏览器中显示 rgb8 像素数据
Displaying rgb8 pixel data in-browser
我在 SO 上发现了与我类似的问题,但还没有找到这个问题的答案。我有一个 rgb8 编码图像,我试图在浏览器中显示在 img
或 canvas
元素中。我不确定如何将此像素数据正确转换为图像,并且正在寻找任何见解。
对于上下文,此 rgb8 数据的来源来自类型为 sensor_msgs/Image
的 ROS 主题。使用 roslibjs
订阅此主题时,我得到以下对象:
{
data: “MT4+CR…”, (of length 1228800)
encoding: "rgb8",
header: {
frame_id: “camera_color_optical_frame”,
seq: 1455,
stamp: ...timestamp info
},
height: 480,
is_bigendian: 0,
step: 1920,
width: 640
}
对于 data
字符串,我曾尝试在 canvas 上显示它,将其转换为 base64 等,但未能成功。我知道 ROS 中的 web_video_server
有助于通过端口发送这些图像,但不幸的是,这对我来说不是一个选项 - 我需要直接使用 data
.
有什么方法可以在浏览器中显示此 rgb8 数据?根据 here 上的文档,data
应表示为 uint8[]
(如果有帮助的话)。
非常感谢!
先创建一个大小正确的canvas,得到一个CanvasRenderingContext2D
// Assuming that imgMes is the image message as linked in question
const can = document.createElement("canvas");
can.width = imgMes.width;
can.height = imgMes.height;
const ctx = can.getcontext("2d");
然后创建一个image buffer来保存像素
const imgData = ctx.createImageData(0, 0, imgMes.width, imgMes.height);
const data = imgData.data;
const inData = imgMes.data;
然后从图像消息中读取数据。确保使用标志 is_bigendian
中定义的正确顺序
var i = 0, j, y = 0, x;
while (y < imgMes.height) {
j = y * imgMes.step;
for (x = 0; x < imgMes.width; x ++) {
if (imgMes.is_bigendian) {
data[i] = inData[j]; // red
data[i + 1] = inData[j + 1]; // green
data[i + 2] = inData[j + 2]; // blue
} else {
data[i + 2] = inData[j]; // blue
data[i + 1] = inData[j + 1]; // green
data[i] = inData[j + 2]; // red
}
data[i + 3] = 255; // alpha
i += 4;
j += 3;
}
y++;
}
把put the pixel data改成canvas;
ctx.putImageData(imgData, 0, 0);
并将 canvas 添加到您的 HTML
document.body.appendChild(can);
大功告成。
请注意,我可能 is_bigendian 走错了路。如果是这样,只需将行 if (imgMes.is_bigendian) {
更改为 if (!imgMes.is_bigendian) {
更新
通过有关数据格式的更多信息,我能够提取图像。
我用atob解码了Base64字符串。这 returns 另一个字符串。然后我迭代字符串中的每个字符,获取要添加到每个像素的字符代码。
尚不清楚字节序在哪里。我的猜测是它在解码后的字符串中,因此代码会为每个字符代码交换字节,因为在 3 个字节的倍数上具有字节序是没有意义的
const can = document.createElement("canvas");
can.width = imgMes.width;
can.height = imgMes.height;
const ctx = can.getContext("2d");
const imgData = ctx.createImageData(imgMes.width, imgMes.height);
const data = imgData.data;
const inData = atob(imgMes.data);
var j = 0; i = 4; // j data in , i data out
while( j < inData.length) {
const w1 = inData.charCodeAt(j++); // read 3 16 bit words represent 1 pixel
const w2 = inData.charCodeAt(j++);
const w3 = inData.charCodeAt(j++);
if (!imgMes.is_bigendian) {
data[i++] = w1; // red
data[i++] = w2; // green
data[i++] = w3; // blue
} else {
data[i++] = (w1 >> 8) + ((w1 & 0xFF) << 8);
data[i++] = (w2 >> 8) + ((w2 & 0xFF) << 8);
data[i++] = (w3 >> 8) + ((w3 & 0xFF) << 8);
}
data[i++] = 255; // alpha
}
ctx.putImageData(imgData, 0, 0);
document.body.appendChild(can);
从示例数据中,我得到了道路附近铺路的图像。
我在 SO 上发现了与我类似的问题,但还没有找到这个问题的答案。我有一个 rgb8 编码图像,我试图在浏览器中显示在 img
或 canvas
元素中。我不确定如何将此像素数据正确转换为图像,并且正在寻找任何见解。
对于上下文,此 rgb8 数据的来源来自类型为 sensor_msgs/Image
的 ROS 主题。使用 roslibjs
订阅此主题时,我得到以下对象:
{
data: “MT4+CR…”, (of length 1228800)
encoding: "rgb8",
header: {
frame_id: “camera_color_optical_frame”,
seq: 1455,
stamp: ...timestamp info
},
height: 480,
is_bigendian: 0,
step: 1920,
width: 640
}
对于 data
字符串,我曾尝试在 canvas 上显示它,将其转换为 base64 等,但未能成功。我知道 ROS 中的 web_video_server
有助于通过端口发送这些图像,但不幸的是,这对我来说不是一个选项 - 我需要直接使用 data
.
有什么方法可以在浏览器中显示此 rgb8 数据?根据 here 上的文档,data
应表示为 uint8[]
(如果有帮助的话)。
非常感谢!
先创建一个大小正确的canvas,得到一个CanvasRenderingContext2D
// Assuming that imgMes is the image message as linked in question
const can = document.createElement("canvas");
can.width = imgMes.width;
can.height = imgMes.height;
const ctx = can.getcontext("2d");
然后创建一个image buffer来保存像素
const imgData = ctx.createImageData(0, 0, imgMes.width, imgMes.height);
const data = imgData.data;
const inData = imgMes.data;
然后从图像消息中读取数据。确保使用标志 is_bigendian
var i = 0, j, y = 0, x;
while (y < imgMes.height) {
j = y * imgMes.step;
for (x = 0; x < imgMes.width; x ++) {
if (imgMes.is_bigendian) {
data[i] = inData[j]; // red
data[i + 1] = inData[j + 1]; // green
data[i + 2] = inData[j + 2]; // blue
} else {
data[i + 2] = inData[j]; // blue
data[i + 1] = inData[j + 1]; // green
data[i] = inData[j + 2]; // red
}
data[i + 3] = 255; // alpha
i += 4;
j += 3;
}
y++;
}
把put the pixel data改成canvas;
ctx.putImageData(imgData, 0, 0);
并将 canvas 添加到您的 HTML
document.body.appendChild(can);
大功告成。
请注意,我可能 is_bigendian 走错了路。如果是这样,只需将行 if (imgMes.is_bigendian) {
更改为 if (!imgMes.is_bigendian) {
更新
通过有关数据格式的更多信息,我能够提取图像。
我用atob解码了Base64字符串。这 returns 另一个字符串。然后我迭代字符串中的每个字符,获取要添加到每个像素的字符代码。
尚不清楚字节序在哪里。我的猜测是它在解码后的字符串中,因此代码会为每个字符代码交换字节,因为在 3 个字节的倍数上具有字节序是没有意义的
const can = document.createElement("canvas");
can.width = imgMes.width;
can.height = imgMes.height;
const ctx = can.getContext("2d");
const imgData = ctx.createImageData(imgMes.width, imgMes.height);
const data = imgData.data;
const inData = atob(imgMes.data);
var j = 0; i = 4; // j data in , i data out
while( j < inData.length) {
const w1 = inData.charCodeAt(j++); // read 3 16 bit words represent 1 pixel
const w2 = inData.charCodeAt(j++);
const w3 = inData.charCodeAt(j++);
if (!imgMes.is_bigendian) {
data[i++] = w1; // red
data[i++] = w2; // green
data[i++] = w3; // blue
} else {
data[i++] = (w1 >> 8) + ((w1 & 0xFF) << 8);
data[i++] = (w2 >> 8) + ((w2 & 0xFF) << 8);
data[i++] = (w3 >> 8) + ((w3 & 0xFF) << 8);
}
data[i++] = 255; // alpha
}
ctx.putImageData(imgData, 0, 0);
document.body.appendChild(can);
从示例数据中,我得到了道路附近铺路的图像。