RGB в YUV420 Планарный и Полупланарный?

В Android у меня есть byte[] отдельных R, G, B, цвета, которые составляют пиксели изображения.

Мне нужно преобразовать эти цвета в YUV420 планарный или полуплоскостной (в зависимости от устройства), прежде чем я смогу использовать Android MediaCodec и MediaMuxer для создания MP4 из этих изображений.

В настоящее время я тестирую свой Nexus 10, который сообщает, что он использует COLOR_FormatYUV420Planar,

Вот код, который я должен конвертировать RGB в YUV420 planar:

private void convertRGBAtoYUV420P(byte[] rgba, byte[] yuv, int width, int height)
{
    final int frameSize = width * height;
    final int chromasize = frameSize / 4;

    int yIndex = 0;
    int uIndex = frameSize;
    int vIndex = frameSize + chromasize;

    int R, G, B, Y, U, V;
    int index = 0;

    int rgbaIndex = 0;

    for (int j = 0; j < height; j++)
    {
        for (int i = 0; i < width; i++)
        {
            R = rgba[rgbaIndex++] + 128; // My rgba bytes are -128 to 127
            G = rgba[rgbaIndex++] + 128;
            B = rgba[rgbaIndex++] + 128;
            rgbaIndex++; // skip A

            Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
            U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
            V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;

            yuv[yIndex++] = (byte)clamp(Y);

            if (j % 2 == 0 && index % 2 == 0)
            {
                yuv[uIndex++] = (byte)clamp(U);
                yuv[vIndex++] = (byte)clamp(V);
            }

            index++;
        }
    }
}

Я нашел этот код из этого блога.

Это работает, просто цвет не правильный. Белый это серый, а все остальные цвета просто неправильные. Не могу понять, что не так в приведенном выше коде, но я чувствую, что это может быть связано с тем фактом, что мои байты r, g, b, a находятся в диапазоне от -128 до 127, но я пытаюсь исправить это, добавив к ним 128.


Второй вопрос, как изменится приведенный выше код, когда мне нужно будет вместо этого конвертировать из RGB в YUV420 полуплоскостной?

1 ответ

Решение

Просто так есть ответ на этот вопрос.

Проблема в том, что добавление 128 к значениям байта не восстанавливает его первоначальное значение.

Поскольку цветовое пространство определяется значениями от 0 до 255. Они не просто смещаются вниз к отрицательному числу, чтобы оно помещалось в подписанный байт. Все более высокие значения для цветов (> 127) кодируются, чтобы уместиться в байте со знаком, в диапазоне от -128 до -1.

Для того, чтобы восстановить значение до того, что вы хотите, вам нужно применить & 0xff Маска для каждого значения байта.

Другие вопросы по тегам