[图像] RGB和YUV图像的数据是如何存储的

参考:

视音频数据处理入门:RGB、YUV像素数据处理_雷霄骅(leixiaohua1020)的专栏-CSDN博客_rgb yuvicon-default.png?t=L9C2https://blog.csdn.net/leixiaohua1020/article/details/50534150

图像处理基础(像素、RGB、YUV )_u014583317的博客-CSDN博客YUV与像素的关系:YUV是利用一个亮度(Y)、两个色差(U,V)来代替传统的RGB三原色来压缩图像。传统的RGB三原色使用红绿蓝三原色表示一个像素,每种原色占用一个字节(8bit),因此一个像素用RGB表示则需要8*3=24bit。如果使用YUV表示这个像素,假设YUV的采样率为:4:2:0,即每一个像素对于亮度Y的采样频率为1,对于色差U和V,则是每相邻的两个像素各取一个U和V。对于单个的像素来说,色差U和V的采样频率为亮度的一半。(解析不清楚,看下面图解)如有三个相邻的像素,如果用RGB三原色表https://blog.csdn.net/u014583317/article/details/119834974

前言:

图像都以像素为单位,但是不同数据格式图像(不是指图像文件格式)在存储数据(字节)时数据结构是不一样的。

注:下面内容中,每一个长方形的格子代表一个字节的数据不是代表一个像素。

RGB:

内存模型(1):

数据是连续存储的,每个像素都由3个字节组成,因此对于 w*h 像素的 rgb 图像,则需要 3*w*h 个字节来表示

内存模型(2):

注:模型1和模型2都能表示图像,模型2更贴近图像的表示方式,模型1更贴近实际内存分布。二者是一样的。

代码表示:

/**
 * Split R, G, B planes in RGB24 file.
 * @param url  Location of Input RGB file.
 * @param w    Width of Input RGB file.
 * @param h    Height of Input RGB file.
 * @param num  Number of frames to process.
 *
 */
int simplest_rgb24_split(char *url, int w, int h,int num){
	FILE *fp=fopen(url,"rb+");
	FILE *fp1=fopen("output_r.y","wb+");
	FILE *fp2=fopen("output_g.y","wb+");
	FILE *fp3=fopen("output_b.y","wb+");
 
	unsigned char *pic=(unsigned char *)malloc(w*h*3);
 
	for(int i=0;i<num;i++){
 
		fread(pic,1,w*h*3,fp);
 
		for(int j=0;j<w*h*3;j=j+3){
			//R
			fwrite(pic+j,1,1,fp1);
			//G
			fwrite(pic+j+1,1,1,fp2);
			//B
			fwrite(pic+j+2,1,1,fp3);
		}
	}
 
	free(pic);
	fclose(fp);
	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
 
	return 0;
}

YUV420:

内存模型:

w*h个像素的yuv图像占用的内存空间为 1.5*w*h 。

Y 数据量 = w*h 个字节

U 数据量 = 0.25 * w*h 个字节 

V  数据量 = 0.25 * w*h 个字节 

YUV420的存放是先存放所有 Y 数据,接着是 U 数据,最后是 V数据,我们在解析的时候可以以此为标准进行数据拆分。

代码表示:

/**
 * Split Y, U, V planes in YUV420P file.
 * @param url  Location of Input YUV file.
 * @param w    Width of Input YUV file.
 * @param h    Height of Input YUV file.
 * @param num  Number of frames to process.
 *
 */
int simplest_yuv420_split(char *url, int w, int h,int num){
	FILE *fp=fopen(url,"rb+");
	FILE *fp1=fopen("output_420_y.y","wb+");
	FILE *fp2=fopen("output_420_u.y","wb+");
	FILE *fp3=fopen("output_420_v.y","wb+");
 
	unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
 
	for(int i=0;i<num;i++){
 
		fread(pic,1,w*h*3/2,fp);
		//Y
		fwrite(pic,1,w*h,fp1);
		//U
		fwrite(pic+w*h,1,w*h/4,fp2);
		//V
		fwrite(pic+w*h*5/4,1,w*h/4,fp3);
	}
 
	free(pic);
	fclose(fp);
	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
 
	return 0;
}

YUV444:

内存模型:

w*h个像素的yuv图像占用的内存空间为 3*w*h 。

Y 数据量 = w*h 个字节

U 数据量 = w*h 个字节 

V  数据量 = w*h 个字节 

和YUV420的区别在于U和V的字节数不同。YUV444和RGB占用同样的内存空间。

代码表示:

/**
 * Split Y, U, V planes in YUV444P file.
 * @param url  Location of YUV file.
 * @param w    Width of Input YUV file.
 * @param h    Height of Input YUV file.
 * @param num  Number of frames to process.
 *
 */
int simplest_yuv444_split(char *url, int w, int h,int num){
	FILE *fp=fopen(url,"rb+");
	FILE *fp1=fopen("output_444_y.y","wb+");
	FILE *fp2=fopen("output_444_u.y","wb+");
	FILE *fp3=fopen("output_444_v.y","wb+");
	unsigned char *pic=(unsigned char *)malloc(w*h*3);
 
	for(int i=0;i<num;i++){
		fread(pic,1,w*h*3,fp);
		//Y
		fwrite(pic,1,w*h,fp1);
		//U
		fwrite(pic+w*h,1,w*h,fp2);
		//V
		fwrite(pic+w*h*2,1,w*h,fp3);
	}
 
	free(pic);
	fclose(fp);
	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
 
	return 0;
}

理解采样:

下图中每个方块代表当前像素的Y分量,每个圆代表U和V分量。

YUV444:每一个像素都采集 Y U V三个分量

在这里插入图片描述

YUV422:所有行策略一致,每两个像素中采集一个U和一个V,每个像素都采集Y

在这里插入图片描述

YUV420:每四个像素采集一个U和一个V,没个像素都采集Y,这里需要注意这里示意图的表示方法中对于 U和V 的采集并没有落到实际的像素上,这只是一种表示方法,实际采样的时候会落到具体的像素点上,或者考虑使用4个点U和V的平均值作为采样值。

 在这里插入图片描述

 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值