Browse Source

Handle YUV planes where U/V planes with a pixel stride > 1 in MAUI Android.

pull/768/merge
Canming Huang 1 year ago
parent
commit
495ddb9ca9
  1. 79
      Emgu.CV.Platform/Maui/UI/Platforms/Android/OnYuvImageAvailableListener.cs

79
Emgu.CV.Platform/Maui/UI/Platforms/Android/OnYuvImageAvailableListener.cs

@ -26,6 +26,7 @@ namespace Emgu.CV.Platform.Maui.UI
class OnYuvImageAvailableListener : Java.Lang.Object, ImageReader.IOnImageAvailableListener
{
private byte[] _data = null;
private byte[] _data_buffer = null;
private Mat _bgrMat = null;
private Mat _rotatedMat = new Mat();
@ -64,27 +65,93 @@ namespace Emgu.CV.Platform.Maui.UI
var planes = image.GetPlanes();
int totalLength = 0;
int pixelCounts = image.Width * image.Height;
for (int i = 0; i < planes.Length; i++)
{
Java.Nio.ByteBuffer buffer = planes[i].Buffer;
totalLength += buffer.Remaining();
if (i == 0)
{
//Y plane
totalLength += pixelCounts;
}
else
{
//U, V plane
totalLength += pixelCounts / 4;
}
//Java.Nio.ByteBuffer buffer = planes[i].Buffer;
//totalLength += buffer.Remaining();
}
if (_data == null || _data.Length != totalLength)
{
_data = new byte[totalLength];
_data_buffer = new byte[(image.Height / 2) * planes[1].RowStride];
}
int offset = 0;
for (int i = 0; i < planes.Length; i++)
{
Java.Nio.ByteBuffer buffer = planes[i].Buffer;
int length = buffer.Remaining();
if (i == 0)
{
Java.Nio.ByteBuffer buffer = planes[i].Buffer;
int length = buffer.Remaining();
buffer.Get(_data, offset, length);
offset += pixelCounts;
}
else if (planes[i].PixelStride == 1)
{
Java.Nio.ByteBuffer buffer = planes[i].Buffer;
int length = buffer.Remaining();
buffer.Get(_data, offset, length);
offset += length;
buffer.Get(_data, offset, length);
offset += pixelCounts / 4;
}
else if (planes[i].PixelStride <= 4) // && pixel Stride > 1
{
Java.Nio.ByteBuffer buffer = planes[i].Buffer;
int length = buffer.Remaining();
buffer.Get(_data_buffer, 0, length);
// Need to handle data stride
GCHandle bufferHandler = GCHandle.Alloc(_data_buffer, GCHandleType.Pinned);
GCHandle dataHandler = GCHandle.Alloc(_data, GCHandleType.Pinned);
try
{
using (Mat bufferMat = new Mat(
image.Height / 2,
image.Width / 2,
DepthType.Cv8U,
planes[i].PixelStride,
bufferHandler.AddrOfPinnedObject(),
planes[i].RowStride))
using (Mat dataMat = new Mat(
image.Height / 2,
image.Width / 2,
DepthType.Cv8U,
1,
new IntPtr(dataHandler.AddrOfPinnedObject().ToInt64() + offset),
image.Width / 2))
{
CvInvoke.ExtractChannel(bufferMat, dataMat, 0);
}
}
finally
{
bufferHandler.Free();
dataHandler.Free();
}
offset += pixelCounts / 4;
}
else
{
throw new NotImplementedException("Pixel stride larger than 4 is not supported.");
}
}
//System.Diagnostics.Debug.Assert(offset == _data.Length, "Offset != _data.Length");
System.Diagnostics.Debug.Assert(image.Width * (image.Height + image.Height / 2) == _data.Length, "_data.Length != image pixel count");
GCHandle handle = GCHandle.Alloc(_data, GCHandleType.Pinned);
using (Mat m = new Mat(
new System.Drawing.Size(image.Width, image.Height + image.Height / 2),

Loading…
Cancel
Save