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
94
95
96
97
98
99
100
|
private class JavaCamera2Frame(private val image: Image) {
fun gray(): Mat {
val planes = image.planes
val w = image.width
val h = image.height
assert(planes[0].pixelStride == 1)
val y_plane = planes[0].buffer
val y_plane_step = planes[0].rowStride.toLong()
mGray = Mat(h, w, CvType.CV_8UC1, y_plane, y_plane_step)
return mGray
}
fun rgba(): Mat {
val planes = image.planes
val w = image.width
val h = image.height
val chromaPixelStride = planes[1].pixelStride
return if (chromaPixelStride == 2) { // Chroma channels are interleaved
assert(planes[0].pixelStride == 1)
assert(planes[2].pixelStride == 2)
val y_plane = planes[0].buffer
val y_plane_step = planes[0].rowStride.toLong()
val uv_plane1 = planes[1].buffer
val uv_plane1_step = planes[1].rowStride.toLong()
val uv_plane2 = planes[2].buffer
val uv_plane2_step = planes[2].rowStride.toLong()
val y_mat = Mat(h, w, CvType.CV_8UC1, y_plane, y_plane_step)
val uv_mat1 = Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane1, uv_plane1_step)
val uv_mat2 = Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane2, uv_plane2_step)
val addr_diff = uv_mat2.dataAddr() - uv_mat1.dataAddr()
if (addr_diff > 0) {
assert(addr_diff == 1L)
CvHelper.cvtColorTwoPlane(y_mat, uv_mat1, mRgba, Imgproc.COLOR_YUV2RGBA_NV12)
} else {
assert(addr_diff == -1L)
CvHelper.cvtColorTwoPlane(y_mat, uv_mat2, mRgba, Imgproc.COLOR_YUV2RGBA_NV21)
}
mRgba
} else { // Chroma channels are not interleaved
val yuv_bytes = ByteArray(w * (h + h / 2))
val y_plane = planes[0].buffer
val u_plane = planes[1].buffer
val v_plane = planes[2].buffer
var yuv_bytes_offset = 0
val y_plane_step = planes[0].rowStride
if (y_plane_step == w) {
y_plane[yuv_bytes, 0, w * h]
yuv_bytes_offset = w * h
} else {
val padding = y_plane_step - w
for (i in 0 until h) {
y_plane[yuv_bytes, yuv_bytes_offset, w]
yuv_bytes_offset += w
if (i < h - 1) {
y_plane.position(y_plane.position() + padding)
}
}
assert(yuv_bytes_offset == w * h)
}
val chromaRowStride = planes[1].rowStride
val chromaRowPadding = chromaRowStride - w / 2
if (chromaRowPadding == 0) {
// When the row stride of the chroma channels equals their width, we can copy
// the entire channels in one go
u_plane[yuv_bytes, yuv_bytes_offset, w * h / 4]
yuv_bytes_offset += w * h / 4
v_plane[yuv_bytes, yuv_bytes_offset, w * h / 4]
} else {
// When not equal, we need to copy the channels row by row
for (i in 0 until h / 2) {
u_plane[yuv_bytes, yuv_bytes_offset, w / 2]
yuv_bytes_offset += w / 2
if (i < h / 2 - 1) {
u_plane.position(u_plane.position() + chromaRowPadding)
}
}
for (i in 0 until h / 2) {
v_plane[yuv_bytes, yuv_bytes_offset, w / 2]
yuv_bytes_offset += w / 2
if (i < h / 2 - 1) {
v_plane.position(v_plane.position() + chromaRowPadding)
}
}
}
val yuv_mat = Mat(h + h / 2, w, CvType.CV_8UC1)
yuv_mat.put(0, 0, yuv_bytes)
CvHelper.cvtColor(yuv_mat, mRgba, Imgproc.COLOR_YUV2RGBA_I420, 4)
mRgba
}
}
fun release() {
mRgba.release()
mGray.release()
}
private val mRgba = Mat()
private var mGray = Mat()
}
|