在 C 中将 yuv420p 转换为 rgb888
Convert yuv420p to rgb888 in C
我正在尝试将平面 YUV (yuv420p) 转换为 C 中的 RGB24。
我没有控制输入,并将 YUV 数据作为 3 个单独的缓冲区,一个用于 Y,一个用于 U和一个 V.
我想从这 3 个输入缓冲区创建一个输出 RGB 缓冲区。
我在 wiki 上遵循了以下模式,但我的代码有问题,因为输出图像的颜色有误。
这是我的功能(请原谅丑...)
static uint8_t* yuv420p_to_rgb2(const uint8_t* y, const uint8_t* u, const uint8_t* v, const size_t width, const size_t height)
{
const size_t size = width * height;
uint8_t* rgb = (uint8_t*)calloc((size * 3), sizeof(uint8_t));
int uv_index = 0, pass = 0;
int b,g,r;
uint8_t* ptr = rgb;
for (size_t i = 0; i < size; i += 6)
{
if (pass == 2)
{
pass = 0;
uv_index += 3;
}
int y1 = y[i];
int y2 = y[i+1];
int y3 = y[i+2];
int y4 = y[i+3];
int y5 = y[i+4];
int y6 = y[i+5];
int u1 = u[uv_index];
int u2 = u[uv_index+1];
int u3 = u[uv_index+2];
int v1 = v[uv_index];
int v2 = v[uv_index+1];
int v3 = v[uv_index+2];
//1
r = 1.164 * (y1 - 16) + 1.596 * (v1 - 128);
g = 1.164 * (y1 - 16) - 0.813 * (v1 - 128) - 0.391 * (u1 - 128);
b = 1.164 * (y1 - 16) + 2.018 * (u1 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//2
r = 1.164 * (y2 - 16) + 1.596 * (v1 - 128);
g = 1.164 * (y2 - 16) - 0.813 * (v1 - 128) - 0.391 * (u1 - 128);
b = 1.164 * (y2 - 16) + 2.018 * (u1 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//3
r = 1.164 * (y3 - 16) + 1.596 * (v2 - 128);
g = 1.164 * (y3 - 16) - 0.813 * (v2 - 128) - 0.391 * (u2 - 128);
b = 1.164 * (y3 - 16) + 2.018 * (u2 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//4
r = 1.164 * (y4 - 16) + 1.596 * (v2 - 128);
g = 1.164 * (y4 - 16) - 0.813 * (v2 - 128) - 0.391 * (u2 - 128);
b = 1.164 * (y4 - 16) + 2.018 * (u2 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//5
r = 1.164 * (y5 - 16) + 1.596 * (v3 - 128);
g = 1.164 * (y5 - 16) - 0.813 * (v3 - 128) - 0.391 * (u3 - 128);
b = 1.164 * (y5 - 16) + 2.018 * (u3 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//6
r = 1.164 * (y6 - 16) + 1.596 * (v3 - 128);
g = 1.164 * (y6 - 16) - 0.813 * (v3 - 128) - 0.391 * (u3 - 128);
b = 1.164 * (y6 - 16) + 2.018 * (u3 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
pass++;
}
return rgb;
}
结果(上图是我的结果,下图是应该的):
感谢您的帮助。
您获取的 U 值和 V 值不正确。
像素(i
、j
)的 U 值和 V 值是:
u[((j / 2) * (width / 2)) + (i / 2)];
v[((j / 2) * (width / 2)) + (i / 2)];
所以,试试这样的循环:
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int yy = y[(j * width) + i];
int uu = u[((j / 2) * (width / 2)) + (i / 2)];
int vv = v[((j / 2) * (width / 2)) + (i / 2)];
r = 1.164 * (yy - 16) + 1.596 * (vv - 128);
g = 1.164 * (yy - 16) - 0.813 * (vv - 128) - 0.391 * (uu - 128);
b = 1.164 * (yy - 16) + 2.018 * (uu - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
}
}
我正在尝试将平面 YUV (yuv420p) 转换为 C 中的 RGB24。
我没有控制输入,并将 YUV 数据作为 3 个单独的缓冲区,一个用于 Y,一个用于 U和一个 V.
我想从这 3 个输入缓冲区创建一个输出 RGB 缓冲区。
我在 wiki 上遵循了以下模式,但我的代码有问题,因为输出图像的颜色有误。
这是我的功能(请原谅丑...)
static uint8_t* yuv420p_to_rgb2(const uint8_t* y, const uint8_t* u, const uint8_t* v, const size_t width, const size_t height)
{
const size_t size = width * height;
uint8_t* rgb = (uint8_t*)calloc((size * 3), sizeof(uint8_t));
int uv_index = 0, pass = 0;
int b,g,r;
uint8_t* ptr = rgb;
for (size_t i = 0; i < size; i += 6)
{
if (pass == 2)
{
pass = 0;
uv_index += 3;
}
int y1 = y[i];
int y2 = y[i+1];
int y3 = y[i+2];
int y4 = y[i+3];
int y5 = y[i+4];
int y6 = y[i+5];
int u1 = u[uv_index];
int u2 = u[uv_index+1];
int u3 = u[uv_index+2];
int v1 = v[uv_index];
int v2 = v[uv_index+1];
int v3 = v[uv_index+2];
//1
r = 1.164 * (y1 - 16) + 1.596 * (v1 - 128);
g = 1.164 * (y1 - 16) - 0.813 * (v1 - 128) - 0.391 * (u1 - 128);
b = 1.164 * (y1 - 16) + 2.018 * (u1 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//2
r = 1.164 * (y2 - 16) + 1.596 * (v1 - 128);
g = 1.164 * (y2 - 16) - 0.813 * (v1 - 128) - 0.391 * (u1 - 128);
b = 1.164 * (y2 - 16) + 2.018 * (u1 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//3
r = 1.164 * (y3 - 16) + 1.596 * (v2 - 128);
g = 1.164 * (y3 - 16) - 0.813 * (v2 - 128) - 0.391 * (u2 - 128);
b = 1.164 * (y3 - 16) + 2.018 * (u2 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//4
r = 1.164 * (y4 - 16) + 1.596 * (v2 - 128);
g = 1.164 * (y4 - 16) - 0.813 * (v2 - 128) - 0.391 * (u2 - 128);
b = 1.164 * (y4 - 16) + 2.018 * (u2 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//5
r = 1.164 * (y5 - 16) + 1.596 * (v3 - 128);
g = 1.164 * (y5 - 16) - 0.813 * (v3 - 128) - 0.391 * (u3 - 128);
b = 1.164 * (y5 - 16) + 2.018 * (u3 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
//6
r = 1.164 * (y6 - 16) + 1.596 * (v3 - 128);
g = 1.164 * (y6 - 16) - 0.813 * (v3 - 128) - 0.391 * (u3 - 128);
b = 1.164 * (y6 - 16) + 2.018 * (u3 - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
pass++;
}
return rgb;
}
结果(上图是我的结果,下图是应该的):
感谢您的帮助。
您获取的 U 值和 V 值不正确。
像素(i
、j
)的 U 值和 V 值是:
u[((j / 2) * (width / 2)) + (i / 2)];
v[((j / 2) * (width / 2)) + (i / 2)];
所以,试试这样的循环:
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int yy = y[(j * width) + i];
int uu = u[((j / 2) * (width / 2)) + (i / 2)];
int vv = v[((j / 2) * (width / 2)) + (i / 2)];
r = 1.164 * (yy - 16) + 1.596 * (vv - 128);
g = 1.164 * (yy - 16) - 0.813 * (vv - 128) - 0.391 * (uu - 128);
b = 1.164 * (yy - 16) + 2.018 * (uu - 128);
*ptr++ = CLAMP(r);
*ptr++ = CLAMP(g);
*ptr++ = CLAMP(b);
}
}