Commit 00861b66 authored by vdgussem's avatar vdgussem

Changed the way Images are converted into rgba Mats so that JavaCamera2View also…

Changed the way Images are converted into rgba Mats so that JavaCamera2View also shows correct colors when the Image contains I420 or YV12 data
parent c9a76ede
...@@ -181,17 +181,7 @@ public class JavaCamera2View extends CameraBridgeViewBase { ...@@ -181,17 +181,7 @@ public class JavaCamera2View extends CameraBridgeViewBase {
assert (planes.length == 3); assert (planes.length == 3);
assert (image.getFormat() == mPreviewFormat); assert (image.getFormat() == mPreviewFormat);
// see also https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888 JavaCamera2Frame tempFrame = new JavaCamera2Frame(image);
// Y plane (0) non-interleaved => stride == 1; U/V plane interleaved => stride == 2
assert (planes[0].getPixelStride() == 1);
assert (planes[1].getPixelStride() == 2);
assert (planes[2].getPixelStride() == 2);
ByteBuffer y_plane = planes[0].getBuffer();
ByteBuffer uv_plane = planes[1].getBuffer();
Mat y_mat = new Mat(h, w, CvType.CV_8UC1, y_plane);
Mat uv_mat = new Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane);
JavaCamera2Frame tempFrame = new JavaCamera2Frame(y_mat, uv_mat, w, h);
deliverAndDrawFrame(tempFrame); deliverAndDrawFrame(tempFrame);
tempFrame.release(); tempFrame.release();
image.close(); image.close();
...@@ -334,50 +324,87 @@ public class JavaCamera2View extends CameraBridgeViewBase { ...@@ -334,50 +324,87 @@ public class JavaCamera2View extends CameraBridgeViewBase {
private class JavaCamera2Frame implements CvCameraViewFrame { private class JavaCamera2Frame implements CvCameraViewFrame {
@Override @Override
public Mat gray() { public Mat gray() {
return mYuvFrameData.submat(0, mHeight, 0, mWidth); Image.Plane[] planes = mImage.getPlanes();
int w = mImage.getWidth();
int h = mImage.getHeight();
ByteBuffer y_plane = planes[0].getBuffer();
mGray = new Mat(h, w, CvType.CV_8UC1, y_plane);
return mGray;
} }
@Override @Override
public Mat rgba() { public Mat rgba() {
if (mPreviewFormat == ImageFormat.NV21) Image.Plane[] planes = mImage.getPlanes();
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4); int w = mImage.getWidth();
else if (mPreviewFormat == ImageFormat.YV12) int h = mImage.getHeight();
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGB_I420, 4); // COLOR_YUV2RGBA_YV12 produces inverted colors int chromaPixelStride = planes[1].getPixelStride();
else if (mPreviewFormat == ImageFormat.YUV_420_888) {
assert (mUVFrameData != null);
Imgproc.cvtColorTwoPlane(mYuvFrameData, mUVFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21); if (chromaPixelStride == 2) { // Chroma channels are interleaved
} else ByteBuffer y_plane = planes[0].getBuffer();
throw new IllegalArgumentException("Preview Format can be NV21 or YV12"); ByteBuffer uv_plane = planes[1].getBuffer();
Mat y_mat = new Mat(h, w, CvType.CV_8UC1, y_plane);
return mRgba; Mat uv_mat = new Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane);
} Imgproc.cvtColorTwoPlane(y_mat, uv_mat, mRgba, Imgproc.COLOR_YUV2RGBA_NV21);
return mRgba;
} else { // Chroma channels are not interleaved
byte[] yuv_bytes = new byte[w*(h+h/2)];
ByteBuffer y_plane = planes[0].getBuffer();
ByteBuffer u_plane = planes[1].getBuffer();
ByteBuffer v_plane = planes[2].getBuffer();
y_plane.get(yuv_bytes, 0, w*h);
int chromaRowStride = planes[1].getRowStride();
int chromaRowPadding = chromaRowStride - w/2;
int offset = w*h;
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.get(yuv_bytes, offset, w*h/4);
offset += w*h/4;
v_plane.get(yuv_bytes, offset, w*h/4);
} else {
// When not equal, we need to copy the channels row by row
for (int i = 0; i < h/2; i++){
u_plane.get(yuv_bytes, offset, w/2);
offset += w/2;
if (i < h/2-1){
u_plane.position(u_plane.position() + chromaRowPadding);
}
}
for (int i = 0; i < h/2; i++){
v_plane.get(yuv_bytes, offset, w/2);
offset += w/2;
if (i < h/2-1){
v_plane.position(v_plane.position() + chromaRowPadding);
}
}
}
public JavaCamera2Frame(Mat Yuv420sp, int width, int height) { Mat yuv_mat = new Mat(h+h/2, w, CvType.CV_8UC1);
super(); yuv_mat.put(0, 0, yuv_bytes);
mWidth = width; Imgproc.cvtColor(yuv_mat, mRgba, Imgproc.COLOR_YUV2RGBA_I420, 4);
mHeight = height; return mRgba;
mYuvFrameData = Yuv420sp; }
mUVFrameData = null;
mRgba = new Mat();
} }
public JavaCamera2Frame(Mat Y, Mat UV, int width, int height) {
public JavaCamera2Frame(Image image) {
super(); super();
mWidth = width; mImage = image;
mHeight = height;
mYuvFrameData = Y;
mUVFrameData = UV;
mRgba = new Mat(); mRgba = new Mat();
mGray = new Mat();
} }
public void release() { public void release() {
mRgba.release(); mRgba.release();
mGray.release();
} }
private Mat mYuvFrameData; private Image mImage;
private Mat mUVFrameData;
private Mat mRgba; private Mat mRgba;
private int mWidth; private Mat mGray;
private int mHeight;
}; };
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment