Преобразование цветов RGB 24 в 16 бит - цвета темнеют - PullRequest
2 голосов
/ 09 ноября 2010

Я заметил, что моя процедура преобразования между 24-битным и 16-битным RGB565 RGB888 приводила к постепенному затемнению цветов при каждом преобразовании ... Формула использует линейную интерполяцию, например, так ...

typedef struct _RGB24 RGB24;
struct _RGB24 {
   BYTE B;
   BYTE G;
   BYTE R;
};

RGB24 *s; // source
WORD *d; // destination
WORD r;
WORD g;
WORD b;

// Code to convert from 24-bit to 16 bit
r = (WORD)((double)(s[x].r * 31) / 255.0);
g = (WORD)((double)(s[x].g * 63) / 255.0);
b = (WORD)((double)(s[x].b * 31) / 255.0);
d[x] = (r << REDSHIFT) | (g << GREENSHIFT) | (b << BLUESHIFT);

// Code to convert from 16-bit to 24-bit
s[x].r = (BYTE)((double)(((d[x] & REDMASK) >> REDSHIFT) * 255) / 31.0);
s[x].g = (BYTE)((double)(((d[x] & GREENMASK) >> GREENSHIFT) * 255) / 63.0);
s[x].b = (BYTE)((double)(((d[x] & BLUEMASK) >> BLUESHIFT) * 255) / 31.0);

Преобразование из 16-битного в 24-битное аналогично, но с обратной интерполяцией ... Я не понимаю, как значения продолжают уменьшаться и уменьшаться каждый раз, когда цвет циклически проходит по уравнению, если они противоположны... Первоначально не было бросков, чтобы удвоить, но я подумал, что если бы я сделал это деление с плавающей запятой, у него не было бы спада ... но это все равно ...

Ответы [ 5 ]

3 голосов
/ 23 марта 2011

Не используйте с плавающей запятой что-то простое, как это.Обычный способ, который я видел, - это усекать при понижающем преобразовании, но расширять при повышающем преобразовании (поэтому 0b11111 переходит к 0b11111111).

// Code to convert from 24-bit to 16 bit
r = s[x].r >> (8-REDBITS);
g = s[x].g >> (8-GREENBITS);
b = s[x].b >> (8-BLUEBITS);
d[x] = (r << REDSHIFT) | (g << GREENSHIFT) | (b << BLUESHIFT);

// Code to convert from 16-bit to 24-bit
s[x].r = (d[x] & REDMASK) >> REDSHIFT;                        // 000abcde
s[x].r = s[x].r << (8-REDBITS) | s[x].r >> (2*REDBITS-8);     // abcdeabc
s[x].g = (d[x] & GREENMASK) >> GREENSHIFT;                    // 00abcdef
s[x].g = s[x].g << (8-GREENBITS) | s[x].g >> (2*GREENBITS-8); // abcdefab
s[x].b = (d[x] & BLUEMASK) >> BLUESHIFT;                      // 000abcde
s[x].b = s[x].b << (8-BLUEBITS) | s[x].b >> (2*BLUEBITS-8);   // abcdeabc
3 голосов
/ 09 ноября 2010

Когда вы конвертируете свои двойные значения в WORD, значения усекаются.Например, (126 * 31) / 255 = 15,439, который усекается до 15. Поскольку значения усекаются, они постепенно уменьшаются с каждой итерацией.Вам необходимо ввести округление (добавляя 0,5 к вычисленным значениям перед преобразованием их в целые числа)

Продолжая пример, вы берете 15 и конвертируете обратно: (15 * 255) / 31 = 123,387, который усекается до 123

1 голос
/ 09 ноября 2010

Приведение double к WORD не округляет значение double - оно усекает десятичные цифры.Вам нужно использовать какую-то процедуру округления, чтобы получить поведение округления.Обычно вы хотите округлить половину до четного . Существует вопрос переполнения стека о том, как округлить в C ++, если вам это нужно .


Также обратите внимание, что преобразование из 24 бит в 16 бит навсегда теряет информацию.Конечно, невозможно поместить 24 бита в 16 бит.Вы не можете получить его обратно путем преобразования из 16 бит в 24 бит.

0 голосов
/ 12 января 2011

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

r = (WORD)((double)(s[x].r * 31) / 255.0);

с

r = (WORD)round(s[x].r / 255.0 * 31.0); 

таким образом, компилятор также должен сложить 31.0 / 255.0 в стоимостном выражении.

Очевидно, что если это необходимо повторить для огромного количества пикселей, было бы предпочтительнее создать и использовать вместо этого LUT (справочную таблицу).

0 голосов
/ 20 ноября 2010

это потому, что 16 бит работает со значениями, умноженными на 2, например 2 * 2 * 2 * 2, и получится как rrggbb, и в том же 32-битном случае он умножит все битовые значения на 2.

короче 16 бит 24 бит 32 бит работает с умножением rgb на 2 и показывает значения в виде цвета.
для краткости вы должны найти концепцию битового цвета.проверьте это в Википедии, надеюсь, это поможет вам

...