Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript将YUV转换为RGB_Javascript_Html_Canvas_Rgb_Yuv - Fatal编程技术网

Javascript将YUV转换为RGB

Javascript将YUV转换为RGB,javascript,html,canvas,rgb,yuv,Javascript,Html,Canvas,Rgb,Yuv,我有js中的YUV图像字节数组(UINtArray),是否可以将其转换为rgb?或者如何在画布上绘制 这里是使用webGL画布的链接,通过填充纹理/但我需要使用2D上下文画布。我知道可能会慢一些,但无论如何。 更新:图像YUV字节也是我看到的I420格式 UpDea2:我在C++中发现了一个例子,我认为它会起作用,但是你能帮我把它转换成JS? static int getR(int y, int u, int v) { return clamp(y + (int) (1.402f *

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

这里是使用webGL画布的链接,通过填充纹理/但我需要使用2D上下文画布。我知道可能会慢一些,但无论如何。

更新:图像YUV字节也是我看到的I420格式

UpDea2:我在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;
        }
    }
}
静态整数getR(整数y,整数u,整数v)
{
回程钳(y+(int)(1.402f*(v-128));
}
静态整数getG(整数y、整数u、整数v)
{
回程钳(y-(int)(0.344f*(u-128)+0.714f*(v-128));
}
静态整数getB(整数y,整数u,整数v)
{
回位夹(y+(int)(1.772f*(u-128));
}
静态int getY(int r,int g,int b)
{
返回值(整数)(0.299f*r+0.587f*g+0.114f*b);
}
静态整数getU(整数r,整数g,整数b)
{
返回值(整数)(-0.169f*r-0.331f*g+0.499f*b+128);
}
静态整数getV(整数r、整数g、整数b)
{
返回(整数)(0.499f*r-0.418f*g-0.0813f*b+128);
}
静态整数钳位(整数值)
{
返回数学::Min(数学::Max(值,0),255);
}
静态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;
intui=0;
int vi=0;
int rgbi=0;
对于(intypos=0;yposiPicHeight;ypos++)
{
对于(intxpos=0;xposiPicWidth;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);
intb=getB(y,u,v);
if(位转换器::IsLittleEndian)
{
rgbData[rgbi++]=(无符号字符)b;
rgbData[rgbi++]=(无符号字符)g;
rgbData[rgbi++]=(无符号字符)r;
}
其他的
{
rgbData[rgbi++]=(无符号字符)r;
rgbData[rgbi++]=(无符号字符)g;
rgbData[rgbi++]=(无符号字符)b;
}
易++;
如果(xpos%2==1)
{
ui++;
vi++;
}
}
yi+=yp;
如果(YPO%2==0)
{
ui-=(yuvImage->iPicWidth/2);
vi-=(yuvImage->iPicWidth/2);
}
其他的
{
ui+=向上添加;
vi+=vpn;
}
}
}

我对您的主题了解不多,稍后我会尝试了解更多,但我发现两个有用的链接可能会有所帮助

应该告诉您如何将YUV图像转换为RGB(这是用Java编写的,稍后我将尝试转换):

应该告诉您如何绘制RGB图像:

以下是将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);}
}
函数yuv2rgb(y,u,v){ y=parseInt(y); u=parseInt(u); v=parseInt(v); r=夹具(数学地板(y+1.4075*(v-128)),0255); g=夹具(数学地板(y-0.3455*(u-128)-(0.7169*(v-128))),0255); b=夹具(数学地板(y+1.7790*(u-128)),0255); 返回({r:r,g:g,b:b}); } 功能夹(n、低、高){ if(nhigh){return(high);} } 您可以使用var imgData=ctx.createImageData(canvas.width,canvas.height)创建一个“从头开始”的像素数组,您可以将rgb值输入其中


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

假设您的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);
///迭代缓冲区
对于(;i
我们不需要钳制这些值,因为画布的缓冲区默认为
uint8clampedaray
,因此浏览器将为我们执行钳制操作,并为我们节省一些CPU周期。只要加上0.5就可以了

如果您的YUV缓冲区是原始的4:2:0格式,那么它就有点乏味,因为您必须考虑交织等。但是对于YUV分量值本身,可以使用上面的转换方法来获得RGB


希望这能有所帮助。

感谢@CubanAzcuy的回复。是的,我尝试了一些转换的例子,但必须运气画出来,也许我错过了一些东西。绘制rgb字节不是问题,因为我还可以将其转换为base64并绘制为图像。希望您在convert方面取得成功。在JS中实现此功能时,您面临的具体问题是什么?你们能发布你们到目前为止的任何尝试吗?这是我尝试过的所有转换函数,我得到的全部,或者是空画布,或者是图片,若我将其转换为base并在图片中设置src,那个么就不绘制了。谢谢,我得到了白色帆布anyway@TomWhitete YUV缓冲区的格式是什么?它是“标准化”为8:8:8还是原始数据为4:2:0?有关如何处理420个原始缓冲区的更多详细信息,请参阅本文:对于他们发送给我的编码数据,他们使用抱歉,但这也不起作用:(我认为,因为我不需要简单的YUV,但IYUVYou忘记了钳制“b”字段。
/// 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);