首先需要大家对yuv数据格式有一定的了解,不了解的可以先看下YUV格式说明这篇文章,主要是看懂这两张图:
上面的链接文章已经介绍的很清楚了,这里就不在赘述。
代码如下:
/**
* @param src 原图
* @param w 原图宽
* @param h 原图高
* @param dstRect 要截取的块
* @return 截取后的图
*/
public static byte[] nv21Clip(byte[] src, int w, int h, Rect dstRect) {
//要截取的部分不能超出原图
if (dstRect.left > w || dstRect.right > w || dstRect.top > h || dstRect.bottom > h || dstRect.left>dstRect.right || dstRect.top>dstRect.bottom) {
return null;
}
//边界处理,此处需理解yuv三个通道的对应关系
if (dstRect.left % 2 != 0) {
dstRect.left -= 1;
}
if (dstRect.right % 2 != 0) {
dstRect.right -= 1;
}
if (dstRect.top % 2 != 0) {
dstRect.top -= 1;
}
if (dstRect.bottom % 2 != 0) {
dstRect.bottom -= 1;
}
int dstW = dstRect.right - dstRect.left;
int dstH = dstRect.bottom - dstRect.top;
//目标图(dst)相对于原图(src)的偏移量
int offsetX = dstRect.left;
int offsetY = dstRect.top;
int dstSize = dstW * dstH * 3 / 2;
byte[] dst = new byte[dstSize];
//拷贝y
for (int i = 0; i < dstH; i++) {
for (int j = 0; j < dstW; j++) {
int dstIndex = i * dstW + j;
int srcIndex = (i + offsetY) * w + offsetX + j;
dst[dstIndex] = src[srcIndex];
}
}
//拷贝uv,一行行的查找像素并复制
for (int m = 0; m < dstH / 2; m++) {
for (int n = 0; n < dstW; n++) {
int dstIndex = dstW * dstH + m * dstW + n;
int srcIndex = w * h + (offsetY/2+m) * w + offsetX + n;
dst[dstIndex] = src[srcIndex];
}
}
return dst;
}
实现还是比较简单的,无非就是将需要截取部分的yuv分量复制出来,其他NV12、I420、YV12等格式也类似。