'green bitmap on analyze in cameraX when imageproxy to bitmap by using Samsung S20
I already use bottom code. But It apear green bitmap when I use imageproxy to bitmap only about lastest smartphone. Such as Samsung s20
Bottom code work well on past device Who does have some problem?
fun Image.toBitmap(): Bitmap {
val yBuffer = planes[0].buffer // Y
val uBuffer = planes[1].buffer // U
val vBuffer = planes[2].buffer // V
val ySize = yBuffer.remaining()
val uSize = uBuffer.remaining()
val vSize = vBuffer.remaining()
val nv21 = ByteArray(ySize + uSize + vSize)
//U and V are swapped
yBuffer.get(nv21, 0, ySize)
vBuffer.get(nv21, ySize, vSize)
uBuffer.get(nv21, ySize + vSize, uSize)
val yuvImage = YuvImage(nv21, ImageFormat.NV21, this.width, this.height, null)
val out = ByteArrayOutputStream()
yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 50, out)
val imageBytes = out.toByteArray()
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
}
Solution 1:[1]
val nv21 = ByteArray(ySize + uSize + vSize)
Not every YUV_420_888
buffer is actually NV21 format. You also have to handle other formats, e.g. NV12, YU12 and YV12. There's a YUV to bitmap converter sample on the camera samples Github repo, try it out, it should work correctly.
Solution 2:[2]
I have been encountering a similar problem. I first tried it using a low-end android device, and then with a high-end device, and both had the same problem.
What I tried:
- Save as RGB not YUV
- Change imageFormat from Nv21 to YUV2
- Try to convert from Nv21 to other formats using custom functions
- Convert to bitmap and then to []byte
Nothing worked. Still works good on several Samsung, Huawei and LG devices of various qualities and ages.
Link to post:Image.Analyzer gives out unclear picture from camera on certain devices
Solution 3:[3]
The problem for me turned out to be the fact that different devices have different rates at which they can analyze a video. More on that later, but the main problem was, accessing data from the imageProxy using byte buffers BEFORE USING the converted bitmap. ImageProxy
objects seem to be hard-coded pass-by-reference Java objects, which means even if you pass that ImageProxy
out of the analyzer via state-hoisting or something, if you then modify it's bytes INSIDE the analyze method, it will affect the passed value too. Hence, before using the value anywhere in your code, be sure to call
<yourImageProxyObject>.planes[index_used].buffer.rewind()
This shifts the cursor back to the zero-th position, allowing the readers to access the correct bytes instead of random noisy ones.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Husayn Hakeem |
Solution 2 | GeorgeRaspberry |
Solution 3 | Richard Onslow Roper |