小白一个,开始研究YUV,记录一下心得,如果有什么说得不对的地方,请及时纠正
最近实现了一个yuv裁剪的功能,现在做一些整理:
宽和高分别为w和h的yuv420图像的大小为w*h*3/2,对于NV21和NV12来说,前w*h Byte存储Y分量,后w*h/2 Byte存储UV分量,NV12和NV21不同就是UV分量的位置不同,具体自行百度。
具体实现如下:
void cutYuv(int yuvType, unsigned char *tarYuv, unsigned char *srcYuv, int startW,
int startH, int cutW, int cutH, int srcW, int srcH)
{
int i;
int j = 0;
int k = 0;
//分配一段内存,用于存储裁剪后的Y分量
unsigned char *tmpY = (unsigned char *)malloc(cutW*cutH);
//分配一段内存,用于存储裁剪后的UV分量
unsigned char *tmpUV = (unsigned char *)malloc(cutW*cutH/2);
switch (yuvType) {
case NV21OR21:
for(i=startH; i<cutH+startH; i++) {
// 逐行拷贝Y分量,共拷贝cutW*cutH
memcpy(tmpY+j*cutW, srcYuv+startW+i*srcW, cutW);
j++;
}
for(i=startH/2; i<(cutH+startH)/2; i++) {
//逐行拷贝UV分量,共拷贝cutW*cutH/2
memcpy(tmpUV+k*cutW, srcYuv+startW+srcW*srcH+i*srcW, cutW);
k++;
}
//将拷贝好的Y,UV分量拷贝到目标内存中
memcpy(tarYuv, tmpY, cutW*cutH);
memcpy(tarYuv+cutW*cutH, tmpUV, cutW*cutH/2);
free(tmpY);
free(tmpUV);
break;
case YUV420SP:
//Not FInished
break;
}
}
参数的含义:yuvType -------------------------- yuv类型,目前只支持NV12和NV21
tarYuv -------------------------- 存储裁剪结果的内存
srcYuv -------------------------- 原始YUV数据,通过fread获取
startW,startH -------------------------- 开始裁剪的坐标位置
cutW,cutH -------------------------- 裁剪过后的分辨率
srcW,srcH -------------------------- 原始YUV数据的分辨率
从代码看出,分别拷贝Y分量和UV分量即可。具体测试结果如下:
裁剪前,分辨率1144*789(不要问为什么这么奇葩,QQ截图随便截的)
在裁剪坐标20,50 裁剪大小500,500之后,结果如下