ImageUtil.java
3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.sw.laryngoscope.glsurface;
import android.graphics.Rect;
public class ImageUtil {
/**
* 将Y:U:V == 4:2:2的数据转换为nv21
*
* @param y Y 数据
* @param u U 数据
* @param v V 数据
* @param nv21 生成的nv21,需要预先分配内存
* @param stride 步长
* @param height 图像高度
*/
public static void yuv422ToYuv420sp(byte[] y, byte[] u, byte[] v, byte[] nv21, int stride, int height) {
System.arraycopy(y, 0, nv21, 0, y.length);
int nv21UVIndex = stride * height;
int length = y.length + u.length / 2 + v.length / 2 - 2;
int uIndex = 0, vIndex = 0;
for (int i = nv21UVIndex; i < length; i += 2) {
vIndex += 2;
uIndex += 2;
nv21[i] = v[vIndex];
nv21[i + 1] = u[uIndex];
}
}
/**
* 裁剪NV21数据
*
* @param originNV21 原始的NV21数据
* @param cropNV21 裁剪结果NV21数据,需要预先分配内存
* @param width 原始数据的宽度
* @param height 原始数据的高度
* @param left 原始数据被裁剪的区域的左边界
* @param top 原始数据被裁剪的区域的上边界
* @param right 原始数据被裁剪的区域的右边界
* @param bottom 原始数据被裁剪的区域的下边界
*/
public static void cropNV21(byte[] originNV21, byte[] cropNV21, int width, int height, int left, int top, int right, int bottom) {
int halfWidth = width / 2;
int cropImageWidth = right - left;
int cropImageHeight = bottom - top;
//原数据Y左上
int originalYLineStart = top * width;
int targetYIndex = 0;
//原数据UV左上
int originalUVLineStart = width * height + top * halfWidth;
//目标数据的UV起始值
int targetUVIndex = cropImageWidth * cropImageHeight;
for (int i = top; i < bottom; i++) {
System.arraycopy(originNV21, originalYLineStart + left, cropNV21, targetYIndex, cropImageWidth);
originalYLineStart += width;
targetYIndex += cropImageWidth;
if ((i & 1) == 0) {
System.arraycopy(originNV21, originalUVLineStart + left, cropNV21, targetUVIndex, cropImageWidth);
originalUVLineStart += width;
targetUVIndex += cropImageWidth;
}
}
}
/**
* 裁剪NV21数据
*
* @param originNV21 原始的NV21数据
* @param cropNV21 裁剪结果NV21数据,需要预先分配内存
* @param width 原始数据的宽度
* @param height 原始数据的高度
* @param rect 原始数据被裁剪的区域
*/
public static void cropNV21(byte[] originNV21, byte[] cropNV21, int width, int height, Rect rect) {
if (originNV21.length != width * height * 3 / 2) {
throw new IllegalArgumentException("invalid origin squareNV21");
}
if (rect == null || rect.isEmpty()) {
throw new IllegalArgumentException("rect is null or empty");
}
if (cropNV21.length != rect.width() * rect.height() * 3 / 2) {
throw new IllegalArgumentException("cropNV21's size and rect size mismatch");
}
if (rect.left < 0 || rect.top < 0 || rect.right > width || rect.bottom > height) {
throw new IllegalArgumentException("rect is not inside image");
}
cropNV21(originNV21, cropNV21, width, height, rect.left, rect.top, rect.right, rect.bottom);
}
}