NV21是YUV格式的,比例是411。Y对应每个像素,这个好办。每个U、V对应4个像素,这个怎么复制?试着改了代码,内容出来了,颜色基本都错了。
网上搜索了半天,都是缩放方面的。也不知道有没有测试过?能不能跑?结果对不对?
反复搜索了几次,终于找到了一个剪切的代码,是JAVA的,而且写法跟吾差别很大。可是没有别的参考,有这个也很好了。于是自己研究了代码,发现原理、流程是一样的(那是肯定的)。有一个步骤代码有些差异,做了修改,直接崩溃。仔细看了,对照自己代码,再修改,这次有不少的画面正确,也有错误(自己的代码,之前也出现过类似情况)。
这是怎么回事呢?同样的代码,怎么有的图片对,有的不对?吾使出以前用过的办法,将每个图片的剪切区域打印出来,进行分析。果然发现了规律:相对于源图片的TOP、LEFT必须都是偶数,图片就正确。那就好说了,咱玩这个多熟练啊。这里把正确的代码开放出来,希望对于为此苦恼的朋友有帮助。
int clipNv21ToNv21(const char* pNv21Source, const int nWidth, const int nHeight, char* pNv21Dest, const int nClipLeft, const int nClipTop, const int nClipWidth, const int nClipHeight) { const char* pNv21Source0 = pNv21Source; int i = 0; //关键二之一。 //取整。估计不同平台要求取整范围有差异。 //这样计算的结果,有可能差一个像素。宽高最好对应调整。 int clipLeft = (int)(nClipLeft+1) / 2 * 2; int clipTop = (int)(nClipTop +1) / 2 * 2; //移动到指定位置 pNv21Source0 += clipTop * nWidth + clipLeft; //复制Y for (i=0; i<nClipHeight; i++) { memcpy(pNv21Dest, pNv21Source0, nClipWidth); pNv21Source0 += nWidth; pNv21Dest += nClipWidth; } //复制U/V pNv21Source0 = pNv21Source + nWidth*nHeight; pNv21Source0 += (clipTop * nWidth/2 + clipLeft); //关键二之二: for (i=0; i<nClipHeight/2; i++) { memcpy(pNv21Dest, pNv21Source0, nClipWidth); pNv21Source0 += nWidth; pNv21Dest += nClipWidth; } return 0; }