crow-misia / libyuv-android

LibYUV for Android

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to create I420 in Java from Image

bmharper opened this issue · comments

I have an android.media.Image from a camera in YUV_420_888, and I want to convert it to an android.graphics.Bitmap in RGBA.
I can't figure out how to do this... but I feel like it should be easy.

This is what I'm trying:

I420Buffer yuv = I420Buffer.Factory.wrap(Plane.from(planes[0]), Plane.from(planes[1]), Plane.from(planes[2]), img.getWidth(), img.getHeight());

That fails to compile with this error:

error: cannot access ImageProxy$PlaneProxy
        I420Buffer yuv = I420Buffer.Factory.wrap(Plane.from(planes[0]), Plane.from(planes[1]), Plane.from(planes[2]), img.getWidth(), img.getHeight());
                                                      ^
  class file for androidx.camera.core.ImageProxy$PlaneProxy not found
```
Bottom line.. I can't figure out how to create a libyuv `Plane` from an Android `Image.Plane`

v0.20.0 has been released.

Plane.wrapProxy method with in the same name for image.Plane and imageProxy.PlaneProxy for cameraX.
So, a new method Plane.wrapProxy was created for cameraX.

ImageExt.toI420Buffer method can be used to create I420Buffer from android.media.Image.

Thanks, ImageExt.toI420Buffer works.

I'm getting wrong images out though. It looks like the stride on the UV channels is wrong. The Y channel seems to be coming through correctly. The image looks grey, but I can see the color channels swim over the rest of the image.
I'm looking through the source code of I420Buffer.convertTo(ArgbBuffer), and I can't see anything wrong. Do you have any idea what this might be?

My source camera format is ImageFormat.YUV_420_888.

Screenshot_2022-06-27-12-16-22-649_com journeyapps visiondemo

Android I420_888 is returned in the format I420, NV12, or NV21, depending on Android device model.

If pixelStride of 2nd Plane is 1, it is I420.
If buffer address of 2nd and 3rd planes are
NV12 if 2nd < 3rd.
NV21 if 2nd > 3rd.

Thanks!

Is there any wrapper function that can just convert any YUV_420_888 Image object to ArgbBuffer, regardless of the underlying format? For example, this works on some devices, but has wrong colors on others:

        I420Buffer i420Buffer = ImageExt.toI420Buffer(image);
        ArgbBuffer argbBuffer = ArgbBuffer.Factory.allocate(image.getWidth(), image.getHeight());
        i420Buffer.convertTo(argbBuffer);
        i420Buffer.close();

Could it be handled by adding some conditions and use different ImageExt.to conversions depending on that?

No, there is not.