图像格式互转

一:灰度图转YUV

由于工作需要,经常接触12bit灰度数据,因此在这里将数据的处理记录下来。

经常接触的是sensor输出的12bit灰度数据,按照需求经常会将这份数据转换成其他格式,如16bit灰度数据(高4bit为0),YUV数据等,其中在转成YUV之前需要先把每个piel的12bit数据变成8bit,即将低4bit舍弃,然后补齐UV数据。

以下代码为将16bit的灰度数据转成YUV格式,由于UV数据都置为128,因此对于YUV420的各种格式的处理也都是相同的了。

#include <stdio.h>

unsigned short grayraw[640*480];	//输入的16bit 灰度数据
unsigned char gray_8bit[640*480];	//输出的8bit 灰度数据
unsigned char gray_yuv[640*480*3/2];//输出的YUV数据,NV12或者NV21等

int main()
{

	int i = 0;
	unsigned short pixel;
	unsigned short temp;
	
	char gray_file[256];
	sprintf(gray_file, "gray_raw");
	FILE *file_grayraw = fopen(gray_file, "rb");
	fread(grayraw, 1, 640 * 480 * 2 , file_grayraw);
	fclose(file_grayraw);
	
	for(i = 0; i < 640*480; i++)
	{
		pixel = grayraw[i];
		temp = (pixel << 4) >> 8;
		gray_8bit[i] = (unsigned char)temp;
		gray_yuv[i] = (unsigned char)temp;
	}
	
	//to 8bit
	char gray_out[256];
	sprintf(gray_out, "grayout.raw");
	FILE *grayout_file = fopen(gray_out, "wb+");
	fwrite((void*)gray_8bit, 1, 640*480, grayout_file);
	fclose(grayout_file);
	
	//to yuv
	memset(gray_yuv+640*480, 128, 640*480/2);
	char gray_yuv_out[256];
	sprintf(gray_yuv_out, "640_480.yuv");
	FILE *grayyuv_file = fopen(gray_yuv_out, "wb+");
	fwrite((void*)gray_yuv, 1, 640*480*3/2, grayyuv_file);
	fclose(grayyuv_file);
			
	return 0;
}

二:NV12转YUV422(UYVY)

NV12格式属于YUV420  即 YYYYYYYYYYYYYYY.....UVUVUVUVUVUV

下面的代码用于将1920*1080的NV12数据转换成UYVY的YUV422格式

原理是将YUV420的由上下两行相邻的共4个Y共享一个U转变为YUV422每行相邻的两个Y共享一个U,具体方式为将YUV420的第一行的Y对应的U(第二行Y也对应着这个U)复制一行,也就是两行的U,其中一行对应YUV422第一行的Y,另一行对应YUV422第二行的Y,如此类推,那么YUV420的第3,4行的Y对应的960个U也是复制成为1920个,分别用于对应YUV422的3,4行的Y。同理,V也是如此。

#include <stdio.h>

char image_buffer[460800];
char image_big_buffer[3110400];
char image_yuv422_buffer[4147200];

static void NV12_to_UYVY(char* src, char* dst, int width, int height)  
{
	char *yuv420_y = src;
	char *yuv420_u = src + width * height;
	char *yuv420_v = src + width * height + 1;
	char *yuv422   = dst;
	
	int i = 0;
	int j = 0;
	
	char u_buf[518400];
	char v_buf[518400];
	memset((void*)u_buf, 0, 518400);
	memset((void*)v_buf, 0, 518400);

	for(i = 0, j = 0; i < 518400; i++)
	{
		u_buf[i] = *(yuv420_u + j);
		j+=2;
	}

	for(i = 0, j = 0; i < 518400; i++)
	{
		v_buf[i] = *(yuv420_v + j);
		j+=2;
	}

	char uu_buf[1036800];
	char vv_buf[1036800];
	memset((void*)uu_buf, 0, 1036800);
	memset((void*)vv_buf, 0, 1036800);

	int uWidth = width / 2;
	int uHeight = height / 2;

	for(i = 0; i < uHeight; i++)
	{
		memcpy((void*)uu_buf + i * 2 * uWidth, u_buf + i * uWidth, uWidth);
		memcpy((void*)uu_buf + i * 2 * uWidth + uWidth, u_buf + i * uWidth, uWidth);
	}

	for(i = 0; i < uHeight; i++)
	{
		memcpy((void*)vv_buf + i * 2 * uWidth, v_buf + i * uWidth, uWidth);
		memcpy((void*)vv_buf + i * 2 * uWidth + uWidth, v_buf + i * uWidth, uWidth);
	}
	
	for(i = 1; i < width * height * 2;)
	{
		*(yuv422 + i) = *yuv420_y++;
		i += 2;
	}

	for(i = 0, j = 0; i < width * height * 2;)
	{
		*(yuv422 + i) = uu_buf[j];
		i += 4;
		j++;
	}

	for(i = 0, j = 0; i < width * height * 2;)
	{
		*(yuv422 + i + 2) = vv_buf[j];
		i += 4;
		j++;
	}
}
 
int main()
{
	char *originimage = "yuv420_19201080.bin";
	FILE *imagefile = fopen(originimage,"a+");
	if(NULL == imagefile)
	{
		printf("open file[%s] failed!\n", originimage);
		return -1;
	}
	memset((void*)image_big_buffer,0,3110400);
	fread((void*)image_big_buffer, 1, 3110400, imagefile);
	fclose(imagefile);
	
	memset((void*)image_yuv422_buffer,128,4147200);
	NV12_to_UYVY(image_big_buffer, image_yuv422_buffer, 1920, 1080);
	char *big422image = "big422.yuv";
	FILE *fp_422big = fopen(big422image,"a+");
	if(NULL == fp_422big)
	{
		printf("open file[%s] failed!\n", big422image);
		return -1;
	}
	
	fwrite((void*)image_yuv422_buffer, 1, 4147200, fp_422big);
	fclose(fp_422big);	
}

三:YUV444(YUVYUVYUV)转NV12

void YUV444ToNV12(unsigned char *yuv, unsigned char *nv12, int width, int height)
{
	int i = 0;
	int j = 0;
	int k = 0;

	/* copy y data */
	for(i = 0; i < height; i++)
	{
		for(j = 0; j < width; j++)
		{
			*(nv12 + i * width + j) = *(yuv + 3 * k);
			k++;
		}
	}

	unsigned char * ptr_u = nv12 + width * height;
	unsigned char * ptr_v = ptr_u + 1;

	int uv_height = height /2;

	for(i = 0; i < uv_height; i++)
	{
		k = 0;
		for(j = 0; j < width;)
		{
			*(ptr_u + i * width + j) = *(yuv + i * width * 3 * 2 + k * 6 + 1);
			*(ptr_v + i * width + j) = *(yuv + i * width * 3 * 2 + k * 6 + 2);
			j+=2;
			k++;
		}
	}

}

四:BGR888转YUV444(YUVYUVYUV)

void BGR888ToYUV444(unsigned char *yuv, unsigned char *bgr, int pixel_num)
{
    int i = 0;

    for (i = 0; i < pixel_num; ++i) {
        unsigned char b = bgr[i * 3];
        unsigned char g = bgr[i * 3 + 1];
        unsigned char r = bgr[i * 3 + 2];

        // 1. Multiply transform matrix (Y′: unsigned, U/V: signed)
        unsigned short y_tmp = 76 * r + 150 * g + 29 * b;
        unsigned short u_tmp = -43 * r - 84 * g + 127 * b;
        unsigned short v_tmp = 127 * r - 106 * g - 21 * b;

        // 2. Scale down (">>8") to 8-bit values with rounding ("+128") (Y′: unsigned, U/V: signed)
        y_tmp = (y_tmp + 128) >> 8;
        u_tmp = (u_tmp + 128) >> 8;
        v_tmp = (v_tmp + 128) >> 8;

        // 3. Add an offset to the values to eliminate any negative values (all results are 8-bit unsigned)
        yuv[i * 3] = (unsigned char) y_tmp;
        yuv[i * 3 + 1] = (unsigned char) (u_tmp + 128);
        yuv[i * 3 + 2] = (unsigned char) (v_tmp + 128);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值