Есть хорошие и быстрые способы это сделать?
сам я делаю в лоб так:
//4444 -> 8888 void getPixel(const unsigned char *data, Pixel &p) const { unsigned short color = *( ( unsigned short *)data); p.r = ( ( color & 0xF000) >> 8); p.g = ( ( color & 0xF00) >> 4); p.b = ( ( color & 0xF0)); p.a = ( ( color & 0xF) << 4); } //8888 -> 4444 void setPixel( unsigned char *data, const Pixel &p) { unsigned short *pshort = ( unsigned short *)data; *pshort = ( ( p.r >> 4) << 12) | ( ( p.g>>4) << 8) | ( ( p.b>>4) << 4) | ( ( p.a>>4)); }
тут есть проблемы, которые особенно заметны на альфа канале (8888 -> 4444 -> 8888):
255 отображается в 240, объект становится слегка прозрачным и это заметно
можно сделать так
p.a = ((color & 0xF) << 4) + 0xf;
255 отобразится в 255
но
0 отобразится в 15, т.е явно невидимое станет видимым
и тд
примерно тоже самое касается преобразований 565<->888
я понимаю можно все сделать на float, но интересует быстрое и красивое решение на целочисленной арифметике
вот щас подумал, что можно табличку преобразований расчитать в offline через float и прям в код ее вставить
если у кого есть готовая поделитесь:)
чтобы прозрачные объекты не становились немного непрозрачными, и непрозрачные не становились немного прозрачными, можешь посчитать честное линейное преобразование, которое четырёхбитное число [0..15] переводит в диапазон [0..255]. умножаешь число на 255.0f/15.0f и округляешь вниз. если это медленно, то можешь сделать табличку convert4to8[16], где будут храниться уже посчитанные значения каждого из 16 значений компоненты цвета. в обратную сторону проще, просто свдигаешь побитово вправо, не внося дополнительной информации.
Suslik
спасибо, конечно, но только об этом я уже выше написал)
А чем плохо a*255/15 в целых числах.
shekh
> А чем плохо a*255/15 в целых числах.
Тем что делить на 15 в целых числах несколько медленнее (даже используя хитрую методику
для деления на числа вида 2^n -1) чем на 16 (которое реализуется простым сдвигом).
Hybernaculum
> > А чем плохо a*255/15 в целых числах.
> Тем что делить на 15 в целых числах несколько медленнее (даже используя хитрую
> методику
> для деления на числа вида 2^n -1) чем на 16 (которое реализуется простым
> сдвигом).
Я комментировал идею считать это же деление в float.
shekh
> Я комментировал идею считать это же деление в float.
Во флоатах нет целых чисел ;)
Hybernaculum
можно сделать так
p.a = ((color & 0xF) << 4) + 0xf;
255 отобразится в 255
но
0 отобразится в 15
а можно так:
p.a = ((color & 0xF) << 4) | (color & 0xF);
AleX AciD
> а можно так:
> p.a = ((color & 0xF) << 4) | (color & 0xF);
Ты к чему это мне написал и при этом процитировал Frankinshtein ?
AleX AciD
> можно сделать так
> p.a = ((color & 0xF) << 4) + 0xf;
> 255 отобразится в 255
> но
> 0 отобразится в 15
>
> а можно так:
> p.a = ((color & 0xF) << 4) | (color & 0xF);
так чёрное перестанет быть чёрным, прозрачное - прозрачным.
А не проще ли воспользоваться float на SSE и считать чесное линейное преобразование? Грамотно использовать команды преобразования типов и всё будет ок.
Bishop
не везде SSE есть ;-)
>>Тем что делить на 15 в целых числах несколько медленнее
на сколько медленнее?
const unsigned char lookupTable4to8[] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; const unsigned char lookupTable5to8[] = {0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255}; const unsigned char lookupTable6to8[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255};
пользуйтесь кому надо
6->8 великовата получилась, может для нее хотя бы хитрая побитовая магия есть?:)
Suslik
> > p.a = ((color & 0xF) << 4) | (color & 0xF);
> так чёрное перестанет быть чёрным, прозрачное - прозрачным.
Имелось ввиду следующее:
// распаковка red = (( color & 0xF000) >> 8); green = ( ( color & 0xF00) >> 4); blue = ( ( color & 0xF0)); alpha = ( ( color & 0xF) << 4); // 0x00 -> 0x00; 0x10 -> 0x11; ... 0xE0 ->0xEE; 0xF0 -> 0xFF red |= red >> 4; green |= green >> 4; blue |= blue >> 4; alpha |= alpha >> 4; p.r = red; p.g = green; p.b = blue; p.a = alpha;
Тема в архиве.