使用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标清色域转换矩阵,也会导致颜色出现偏差。
修复方法
- 修正输出参数:将
size_dest修改为width * height * 3,fwrite时也按照该长度写入有效数据,同时取消目标文件fclose操作的注释,避免资源泄漏。 - 调整U/V传参顺序:如果确认输入YUV为YV12格式,直接交换U、V通道的传入指针即可。
- 匹配色域矩阵:如果调整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
相关产品推荐
相关产品推荐

