繁体   English   中英

Javascript将YUV转换为RGB

[英]Javascript convert YUV to RGB

我在js中有YUV图像字节数组(UINtArray),是否可以将其转换为rgb? 或如何在画布上绘制?

这是使用webGL画布填充纹理的链接,但我需要使用2D上下文画布来做到这一点。 我知道它可能会比较慢,但是无论如何。 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)创建“从头开始”的像素数组,您可以将rgb值输入到其中。

建立像素阵列后,您可以使用ctx.putImageData(imgData)将其绘制到画布上

我对您的主题不太了解,稍后将尝试找出更多信息,但是我发现了两个有用的链接可能会有所帮助。

应该告诉您如何将YUV图像转换为RGB(这是Java语言,我稍后会尝试将其转换): http : //www.41post.com/3470/programming/android-retrieving-the-camera-preview-as-一个像素阵列

应该告诉您如何绘制RGB图像: HTML Canvas中的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格式,那么它就有些繁琐,因为您必须考虑交织等。 但是对于YUV分量值本身,您可以使用上面的转换方法来获得RGB。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM