关于NV21格式数据不了解的同学可自行搜索,网上资料很多,这里不做过多阐述。
NV21数据剪裁
/**
* nv21数据剪裁
*
* @param src 原始nv21数据
* @param srcWidth 原始nv21数据的宽
* @param srcHeight 原始nv21数据的高
* @param clipWidth 剪裁的宽度
* @param clipHeight 剪裁的高度
* @param left 剪裁的开始的左边位置,坐标相对于nv21原始数据
* @param top 剪裁的开始的上边位置,坐标相对于nv21原始数据
* @return 剪裁异常时返回null,成功时返回剪裁的nv21数据
*/
@Nullable
public static byte[] cropNV21(@NonNull byte[] src, int srcWidth, int srcHeight, int clipWidth, int clipHeight, int left, int top) {
if (src.length != srcWidth * srcHeight * 3 / 2) {
return null;
}
if (clipWidth + left > srcWidth || clipHeight + top > srcHeight) {
return null;
}
if (clipWidth == srcWidth && clipHeight == srcHeight && left == 0 && top == 0) {
return src;
}
//确保为偶数
clipWidth &= ~1;
clipHeight &= ~1;
left &= ~1;
top &= ~1;
byte[] cropBytes = new byte[clipWidth * clipHeight * 3 / 2];
int bottom = top + clipHeight;
//先复制Y数据
for (int i = top; i < bottom; i++) {
System.arraycopy(src, left + i * srcWidth, cropBytes, (i - top) * clipWidth, clipWidth);
}
//复制UV数据
int startH = srcHeight + top / 2;
int endH = srcHeight + bottom / 2;
for (int i = startH; i < endH; i++) {
System.arraycopy(src,
left + i * srcWidth,
cropBytes,
(i - startH + clipHeight) * clipWidth,
clipWidth);
}
return cropBytes;
}
复制代码
NV21数据叠图
/**
* 叠图
* 调用完成后改方法后,直接使用传入的nv21 数据即可。
*
* @param nv21 叠图最下面的图的nv21数据,大小要比被叠图的nv21数据大
* @param width 最下面叠图的nv21数据的宽
* @param height 最下面叠图的nv21数据的高
* @param left 叠图起始左边位置
* @param top 叠图起始的上边位置
* @param overlayNv21 小图的nv21数据
* @param overlayWidth 小图的宽
* @param overlayHeight 小图的高
*/
public static void overlayNV21(byte[] nv21, int width, int height, int left, int top, byte[] overlayNv21, int overlayWidth, int overlayHeight) {
if (nv21.length != width * height * 3 / 2) {
return;
}
if (overlayNv21.length != overlayWidth * overlayHeight * 3 / 2) {
return;
}
int originalOverlayWidth = overlayWidth;
int originalOverlayHeight = overlayHeight;
if (overlayWidth + left > width) {
//不符合要求,进行二次剪裁
overlayWidth = width - left;
}
if (overlayHeight + top > height) {
//不符合要求,进行二次剪裁
overlayHeight = height - top;
}
//裁剪
overlayNv21 = cropNV21(overlayNv21, originalOverlayWidth, originalOverlayHeight, overlayWidth, overlayHeight, 0, 0);
if (overlayNv21 == null) {
return;
}
//确保为偶数
left &= ~1;
top &= ~1;
overlayWidth &= ~1;
overlayHeight &= ~1;
//先复制Y数据
for (int i = 0; i < overlayHeight; i++) {
System.arraycopy(overlayNv21, i * overlayWidth, nv21, left + (top + i) * width, overlayWidth);
}
//复制UV数据
int startH = overlayHeight;
int endH = overlayHeight + (overlayWidth * overlayHeight / 2) / overlayWidth;
int basic = height + top / 2;
for (int i = startH; i < endH; i++) {
System.arraycopy(overlayNv21,
i * overlayWidth,
nv21,
left + (basic + (i - startH)) * width,
overlayWidth);
}
}
复制代码
如有错误或建议,欢迎指正!