Fix # 1:
Вы хотите быть уверенным, что попали в правильную область цветовой плоскости (ий) для значений UV:
val ub = plane1.buffer[((x + xOffset)/2) * 2 + plane1.rowStride * ((y + yOffset)/2)].toFloat()
val vb = plane1.buffer[((x + xOffset)/2) * 2 + 1 + plane1.rowStride * ((y + yOffset)/2)].toFloat()
Я намеренно использовал plane1
для обоих как своего рода хак. С вашим конкретным устройством эти Images
выходят с чередующимися цветными плоскостями. plane1
и plane2
являются по существу одним и тем же массивом (некоторые предостережения). Они оба «указывают» на одну и ту же область в ОЗУ; они перекрываются на 99,9%. И они содержат такие значения: «U / V / U / V / U / V», поэтому pixelStride
равно двум. Я думаю, что это также сработало бы, если бы вы сделали это:
val ub = plane1.buffer[((x + xOffset)/2) * 2 + plane1.rowStride * ((y + yOffset)/2)].toFloat()
val vb = plane2.buffer[((x + xOffset)/2) * 2 + plane2.rowStride * ((y + yOffset)/2)].toFloat()
... потому что, очевидно, интерфейс ByteBufferDirect
абстрагировал тот факт, что plane2
запускает 1 байт справа от plane1
( в родной памяти). (Все выглядело бы немного иначе, если бы вы делали это на нативной стороне, от JNI.)
Исправление ((x + xOffset)/2)*2
предназначено для учета этого чередования, а pixelStride
. Поправка ((y + yOffset)/2)
учитывает тот факт, что все остальные строки пикселей пропускаются в процессе субдискретизации 4: 2: 0. (Каждый второй столбец также пропускается, но поскольку каждый пиксель состоит из 2 байтов (U, V) рядом друг с другом, нам необходимо удвоить смещение обратно с помощью * 2
. Integer math ; мы пытаемся сделать четное число, поэтому смещение ссылки всегда находится на «U»).
Fix # 2:
В этой области:
val r: Float = output.float * 255
val g: Float = output.float * 255
val b: Float = output.float * 255
... вы не хотите умножать на 255, потому что ваши значения уже находятся в диапазоне 0..255.
Fix # 3:
Как вы заметили, значения массива интерпретируются как "подписанные"; Ваш алгоритм преобразования ожидает, что это будет без знака, поэтому лучше иметь их в диапазоне 0..255.
Рекомендуемое улучшение
Было бы более эффективно, если yuvToRGB()
использовал интегральный тип данных для ввода и вывода вместо floats
.