我在js中具有yuv image byte数组(uintarray),是否可以将其转换为RGB?或如何在画布上绘制它?
这是链接,它通过填充纹理/需要使用2D上下文画布来使用WebGL画布。我知道它可能会慢,但是无论如何。https://github.com/mbebenita/broadway/blob/master/player/canvas.js
var lumaSize = width * height,
chromaSize = lumaSize >> 2;
webGLCanvas.YTexture.fill(buffer.subarray(0, lumaSize));
webGLCanvas.UTexture.fill(buffer.subarray(lumaSize, lumaSize + chromaSize));
webGLCanvas.VTexture.fill(buffer.subarray(lumaSize + chromaSize, lumaSize + 2 * chromaSize));
webGLCanvas.drawScene();
更新:图像YUV字节也是I420格式,如我所见
update2:我在C 中找到了我认为可以起作用的示例,但是您能帮我转换为JS吗?
static int getR(int y, int u, int v)
{
return clamp(y + (int) (1.402f * (v - 128)));
}
static int getG(int y, int u, int v)
{
return clamp(y - (int) (0.344f * (u - 128) + 0.714f * (v - 128)));
}
static int getB(int y, int u, int v)
{
return clamp(y + (int) (1.772f * (u - 128)));
}
static int getY(int r, int g, int b)
{
return (int) (0.299f * r + 0.587f * g + 0.114f * b);
}
static int getU(int r, int g, int b)
{
return (int) (-0.169f * r - 0.331f * g + 0.499f * b + 128);
}
static int getV(int r, int g, int b)
{
return (int) (0.499f * r - 0.418f * g - 0.0813f * b + 128);
}
static int clamp(int value)
{
return Math::Min(Math::Max(value, 0), 255);
}
static void ConvertI420ToRGB24(SSourcePicture *yuvImage, unsigned char *rgbData)
{
int yPadding = yuvImage->iStride[0] - yuvImage->iPicWidth;
int uPadding = yuvImage->iStride[1] - (yuvImage->iPicWidth / 2);
int vPadding = yuvImage->iStride[2] - (yuvImage->iPicWidth / 2);
int yi = 0;
int ui = 0;
int vi = 0;
int rgbi = 0;
for (int ypos = 0; ypos < yuvImage->iPicHeight; ypos++)
{
for (int xpos = 0; xpos < yuvImage->iPicWidth; xpos++)
{
int y = yuvImage->pData[0][yi] & 0xFF;
int u = yuvImage->pData[1][ui] & 0xFF;
int v = yuvImage->pData[2][vi] & 0xFF;
int r = getR(y, u, v);
int g = getG(y, u, v);
int b = getB(y, u, v);
if (BitConverter::IsLittleEndian)
{
rgbData[rgbi++] = (unsigned char) b;
rgbData[rgbi++] = (unsigned char) g;
rgbData[rgbi++] = (unsigned char) r;
}
else
{
rgbData[rgbi++] = (unsigned char) r;
rgbData[rgbi++] = (unsigned char) g;
rgbData[rgbi++] = (unsigned char) b;
}
yi++;
if (xpos % 2 == 1)
{
ui++;
vi++;
}
}
yi += yPadding;
if (ypos % 2 == 0)
{
ui -= (yuvImage->iPicWidth / 2);
vi -= (yuvImage->iPicWidth / 2);
}
else
{
ui += uPadding;
vi += vPadding;
}
}
}
以下是将YUV转换为RGB的JS代码。
function yuv2rgb(y,u,v){
y=parseInt(y);
u=parseInt(u);
v=parseInt(v);
r=clamp(Math.floor(y+1.4075*(v-128)),0,255);
g=clamp(Math.floor(y-0.3455*(u-128)-(0.7169*(v-128))),0,255);
b=clamp(Math.floor(y+1.7790*(u-128)),0,255);
return({r:r,g:g,b:b});
}
function clamp(n,low,high){
if(n<low){return(low);}
if(n>high){return(high);}
}
您可以使用var imgdata = ctx.createimagedata(canvas.width,canvas.height)来创建一个" scratch"像素阵列,您可以将RGB值馈入。
构建像素数组后,您可以使用CTX.putimagedata(imgdata)
我对您的话题不了解,我稍后会尝试更多,但是我找到了两个用户链接可能会有所帮助的。
应该告诉您如何将YUV映像转换为RGB(这是在Java中,我将稍后尝试转换):http://www.41post.com/3470/programming/android-retrieving-the-camera-preview-as-a-apixel-array
应该告诉您如何绘制RGB图像:来自HTML帆布的GetPixel?
假设您的Yuv数组为每个像素3个字节,您可以将缓冲区复制并转换为这样的画布:
var width = 800, /// the dimension of the YUV buffer
height = 600,
canvas = document.getElementById('myCanvasId'),
ctx = canvas.getContext('2d'),
idata, /// image data for canvas
buffer, /// the buffer itself
len, /// cached length of buffer
yuvBuffer = ... /// your YUV buffer here
i = 0, /// counter for canvas buffer
p = 0, /// counter for YUV buffer
y, u, v; /// cache the YUV bytes
/// make sure canvas is of same size as YUV image:
canvas.width = width;
canvas.height = height;
/// create an image buffer for canvas to copy to
idata = ctx.createImageData(width, height);
buffer = idata.data;
len = buffer.length;
现在,我们可以迭代缓冲区并随着我们进行转换:
/// iterate buffers
for(; i < len; i += 4, p += 3) {
/// get YUV bytes
y = yuvBuffer[p];
u = yuvBuffer[p + 1] - 128;
v = yuvBuffer[p + 2] - 128;
/// convert to RGB and copy to canvas buffer
buffer[i] = y + v * 1.402 + 0.5;
buffer[i + 1] = y - u * 0.344 - v * 0.714 + 0.5;
buffer[i + 2] = y + u * 1.772 + 0.5;
}
/// update canvas with converted buffer
ctx.putImageData(idata, 0, 0);
我们不需要将值夹住,因为默认情况下的画布的缓冲区是Uint8ClampedArray
,因此浏览器将为我们进行夹紧并节省我们的几个CPU周期。只需添加0.5用于舍入即可。
如果您的YUV缓冲区是原始的4:2:0格式,则考虑到Interleave等,它会更加乏味。但是对于YUV组件值本身,您可以使用上面的转换方法获取RGB。
希望这会有所帮助。