You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libyuv将YUV420P转RGB24时输出图像整体偏蓝,是什么原因如何解决

问题原因
  • 输出写入逻辑错误:RGB24格式每个像素占3字节,单帧总大小为width * height * 3。你的代码中错误将size_dest定义为4字节每像素的总大小,且fwrite时写入了该错误长度,导致大量无效内存数据被写入输出RGB文件,直接引发颜色异常。
  • U/V通道顺序错误:如果输入的YUV文件实际为YV12格式(存储顺序为Y层->V层->U层),而非你默认的I420格式(Y层->U层->V层),你传入的U、V通道指针顺序完全颠倒,会导致红蓝通道错位,最常见的表现就是图像整体偏蓝。
  • 色域转换矩阵不匹配:720P及以上分辨率的YUV资源通常采用BT.709高清色域标准,而libyuv的基础I420ToRGB24函数默认使用BT.601标清色域转换矩阵,也会导致颜色出现偏差。
修复方法
  1. 修正输出参数:将size_dest修改为width * height * 3,fwrite时也按照该长度写入有效数据,同时取消目标文件fclose操作的注释,避免资源泄漏。
  2. 调整U/V传参顺序:如果确认输入YUV为YV12格式,直接交换U、V通道的传入指针即可。
  3. 匹配色域矩阵:如果调整U/V顺序后仍有偏色,可替换为libyuv中支持指定BT.709色域的转换函数。
修正后参考代码
const int width = 1280, height = 720;
FILE *src_file = fopen("1280x720.yuv", "rb");
FILE *dst_file = fopen("1280x720.rgb", "wb");

int size_src = width * height * 3 / 2;
// 修正输出大小为RGB24对应长度
int size_dest = width * height * 3;
char *buffer_src = (char *)malloc(size_src);
char *buffer_dest = (char *)malloc(size_dest);

uint64_t start_time = os_gettime_ns();
while (1)
{
    if (fread(buffer_src, 1, size_src, src_file) != size_src)
    {
        break;
    }
    // 如果确认输入是YV12,交换下面U和V的指针即可
    libyuv::I420ToRGB24((const uint8*)buffer_src, width,
        (const uint8*)(buffer_src + width * height), width / 2,
        (const uint8*)(buffer_src + width * height * 5 / 4), width / 2,
        (uint8*)buffer_dest, width * 3,
        width, height);
    // 修正写入长度为正确的RGB24单帧大小
    fwrite(buffer_dest, 1, size_dest, dst_file);
    fflush(dst_file);
}
uint64_t stop_time = os_gettime_ns();
printf("------ %ld \n", stop_time - start_time);

free(buffer_src);
free(buffer_dest);
// 取消注释,正常关闭目标文件
fclose(dst_file);
fclose(src_file);
return 0;

内容的提问来源于stack exchange,提问作者doublezhou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 04:54:03