Преобразование iOS vImage
iOS Accelerate Framework документирует следующий алгоритм для функции vImageConvert_RGB565toARGB8888
:
Pixel8 alpha = alpha
Pixel8 red = (5bitRedChannel * 255 + 15) / 31
Pixel8 green = (6bitGreenChannel * 255 + 31) / 63
Pixel8 blue = (5bitBlueChannel * 255 + 15) / 31
Для одноразового преобразования это будет достаточно быстро, но если вы хотите обработать много кадров, вам нужно использовать что-то вроде преобразования iOS vImage или реализовать это самостоятельно, используя NEON intrinsics .
Из учебника форума сообщества ARMs
Сначала рассмотрим преобразование RGB565 в RGB888. Мы предполагаем, что в регистре q0 имеется восемь 16-битных пикселей, и мы хотели бы разделить красные, зеленые и синие цвета на 8-битные элементы по трем регистрам от d2 до d4.
vshr.u8 q1, q0, #3 @ shift red elements right by three bits,
@ discarding the green bits at the bottom of
@ the red 8-bit elements.
vshrn.i16 d2, q1, #5 @ shift red elements right and narrow,
@ discarding the blue and green bits.
vshrn.i16 d3, q0, #5 @ shift green elements right and narrow,
@ discarding the blue bits and some red bits
@ due to narrowing.
vshl.i8 d3, d3, #2 @ shift green elements left, discarding the
@ remaining red bits, and placing green bits
@ in the correct place.
vshl.i16 q0, q0, #3 @ shift blue elements left to most-significant
@ bits of 8-bit color channel.
vmovn.i16 d4, q0 @ remove remaining red and green bits by
@ narrowing to 8 bits.
Эффекты каждой инструкции описаны в комментариях выше, но в итоге, операция, выполняемая на каждом канале:
Удалите данные о цвете для соседних каналов, используя сдвиги, чтобы оттолкнуть биты с любого конца элемента.
Используйте второе смещение, чтобы расположить данные цвета в старших битах каждого элемента, и сузьте, чтобы уменьшить размер элемента с 16 до восьми бит.
Обратите внимание на использование размеров элементов в этой последовательности для адресации 8- и 16-битных элементов для выполнения некоторых операций маскирования.
Небольшая проблема
Вы можете заметить, что если вы используете приведенный выше код для преобразования в формат RGB888, ваши белые цвета не совсем белые. Это связано с тем, что для каждого канала младшие два или три бита равны нулю, а не единице; белый цвет, представленный в RGB565 как (0x1F, 0x3F, 0x1F), становится (0xF8, 0xFC, 0xF8) в RGB888. Это можно исправить, используя shift со вставкой, чтобы поместить некоторые старшие биты в младшие биты.
В качестве примера для Android я обнаружил преобразование YUV-в-RGB , написанное на встроенных элементах.