crow-misia / libyuv-android

LibYUV for Android
Apache License 2.0
99 stars 21 forks source link

How to create I420 in Java from Image #7

Closed bmharper closed 2 years ago

bmharper commented 2 years ago

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

crow-misia commented 2 years ago

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.

bmharper commented 2 years ago

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

crow-misia commented 2 years ago

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.

bmharper commented 2 years ago

Thanks!

shudza commented 1 year ago

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?

crow-misia commented 1 year ago

No, there is not.