数据压缩——rgb转yuv
RGB和YUV
- RGB 分别表示红(R)、绿(G)、蓝(B),也就是三原色,将它们以不同的比例叠加,可以产生不同的颜色。
一张 1920 * 1280 的图片,有 1920 * 1280 个像素点。采用 RGB 编码方式,每个像素点都有红、绿、蓝三个原色,每个原色占用 8 个字节,每个像素占用 24 个字节。 - YUV 编码采用了明亮度和色度表示每个像素的颜色。其中 Y 表示明亮度,也就是灰阶值。U、V 表示色度,描述的是色调和饱和度。
- YUV根据不同的采样格式,可以每个 Y 分量都对应自己的 UV 分量,也可以几个 Y 分量共用 UV 分量。相比 RGB,能够节约存储空间。
文章目录
- RGB和YUV
- RGB转YUV420思路
- 一、转换公式
- 二、代码
- 1.rgb转换为yuv的处理
- 2.截断处理部分
- 3. 调用函数rgb24_yuv420
- 结果
- 参考
RGB转YUV420思路
- 将rgb文件中的r,g,b像素读取
- 读取一组根据转换公式转换一组
- 判断y,u,v是否有溢出,若溢出则截断处理
一、转换公式
Y=0.299R+0.587G+0.114B+16 Cr=V=0.500R−0.419G−0.081B+128 Cb=U=−0.169R−0.331G+0.500B+128
二、代码
1.rgb转换为yuv的处理
代码如下:
bool RGB24_TO_YUV420(unsigned char* RgbBuf, int w, int h, unsigned char* yuvBuf)
{unsigned char* ptrY, * ptrU, * ptrV, * ptrRGB;memset(yuvBuf, 0, w * h * 3 / 2); //将yuvBuf初始化为0ptrY = yuvBuf; //420是planar format的储存格式先存放y,再u,再vptrU = yuvBuf + w * h;ptrV = ptrU + (w * h * 1 / 4);//RGB24是packed,RGB打包成一个像素。YUV420P是planar,先将整张图像的Y存完才开始存U,最后Vunsigned char y, u, v, r, g, b;for (int j = 0; j < h; j++) {ptrRGB = RgbBuf + w * j * 3; //rgb存储方式是packed打包存放,每包3个for (int i = 0; i < w; i++) {r = *(ptrRGB++);g = *(ptrRGB++);b = *(ptrRGB++);//rgb转yuv的公式y = 0.299 * r + 0.587 * g + 0.114 * b + 16;u = -0.1684 * r - 0.3316 * g + 0.5 * b + 128;v = 0.5 * r - 0.4187 * g - 0.0813 * b + 128;*(ptrY++) = clip_value(y, 0, 255); //判断y是否超出范围if (j % 2 == 0 && i % 2 == 0) {*(ptrU++) = clip_value(u, 0, 255);*(ptrV++) = clip_value(v, 0, 255);}//按照yuv420p的定义,一个2 * 2的矩形y对应一个u和v。即2 * 2的矩形计算出的u和v的值是一样的,都取第一个进行计算即可。这样改比较好理解。}}return true;
}
2.截断处理部分
代码如下:
//因YUV的范围是0~255因此在其范围外的数值都做截断处理
unsigned char clip_value(unsigned char x, unsigned char min_val, unsigned char max_val) {if (x > max_val) {return max_val; //大于max_val的值记作max_val}else if (x < min_val) {return min_val; //小于min_val的值记作min_val}else {return x; //在指定范围内,就保持不变}
}
3. 调用函数rgb24_yuv420
int rgb24_yuv420(const char* url_in, int w, int h, int num, const char* url_out) {FILE* fp = fopen(url_in, "rb+");FILE* fp1 = fopen(url_out, "wb+");//url_in是输入rgb的文件;//w为图像宽,h为图像高,num为图片数目//url_out为转换后的yuv文件unsigned char* pic_rgb24 = (unsigned char*)malloc(w * h * 3);unsigned char* pic_yuv420 = (unsigned char*)malloc(w * h * 3 / 2);for (int i = 0; i < num; i++) {fread(pic_rgb24, 1, w * h * 3, fp); //读rgb文件RGB24_TO_YUV420(pic_rgb24, w, h, pic_yuv420); //rgb到yuv文件转换fwrite(pic_yuv420, 1, w * h * 3 / 2, fp1); //转换后写入文件fp1}free(pic_rgb24);free(pic_yuv420);fclose(fp);fclose(fp1);return 0;
}
int main()
{rgb24_yuv420("F:\\大三下资料\\数据压缩\\shiyan3\\RGB_YUV\\test.rgb", 256, 256, 1, "F:\\大三下资料\\数据压缩\\shiyan3\\RGB_YUV\\output_test.yuv");
}
结果
缺点:该方法耗时较长
改进:可将浮点运算改为整数移位运算;或者添加查找表,以空间换取时间。
参考
- https://blog.csdn.net/leixiaohua1020/article/details/50534150
- https://blog.csdn.net/fanyun_01/article/details/100068351
- https://blog.csdn.net/liyuanbhu/article/details/68951683
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
