YUV_420_888 interpretation on Samsung Galaxy S7 (Camera2)

For people who encounter error

android.support.v8.renderscript.RSIllegalArgumentException: Array too small for allocation type

use buffer.capacity() instead of buffer.remaining()

and if you already made some operations on the image, you'll need to call rewind() method on the buffer.


Look at

floor((float) uvPixelStride*(x)/2)

which calculates your U,V row offset (uv_row_offset) from the Y x-coordinate.

if uvPixelStride = 2, then as x increases:

x = 0, uv_row_offset = 0
x = 1, uv_row_offset = 1
x = 2, uv_row_offset = 2
x = 3, uv_row_offset = 3

and this is incorrect. There's no valid U/V pixel value at uv_row_offset = 1 or 3, since uvPixelStride = 2.

You want

uvPixelStride * floor(x/2)

(assuming you don't trust yourself to remember the critical round-down behavior of integer divide, if you do then):

uvPixelStride * (x/2)

should be enough

With that, your mapping becomes:

x = 0, uv_row_offset = 0
x = 1, uv_row_offset = 0
x = 2, uv_row_offset = 2
x = 3, uv_row_offset = 2

See if that fixes the color errors. In practice, the incorrect addressing here would mean every other color sample would be from the wrong color plane, since it's likely that the underlying YUV data is semiplanar (so the U plane starts at V plane + 1 byte, with the two planes interleaved)