Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / преобразование из rgba8888 в rgba4444 туда и обратно

преобразование из rgba8888 в rgba4444 туда и обратно

FrankinshteinПостоялецwww19 мар. 201222:42#0
Есть хорошие и быстрые способы это сделать?


сам я делаю в лоб так:

                //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, но интересует быстрое и красивое решение на целочисленной арифметике

                       

FrankinshteinПостоялецwww19 мар. 201222:46#1
вот щас подумал, что можно табличку преобразований расчитать в offline через float и прям в код ее вставить
если у кого есть готовая поделитесь:)
SuslikМодераторwww19 мар. 201223:53#2
чтобы прозрачные объекты не становились немного непрозрачными, и непрозрачные не становились немного прозрачными, можешь посчитать честное линейное преобразование, которое четырёхбитное число [0..15] переводит в диапазон [0..255]. умножаешь число на 255.0f/15.0f и округляешь вниз. если это медленно, то можешь сделать табличку convert4to8[16], где будут храниться уже посчитанные значения каждого из 16 значений компоненты цвета. в обратную сторону проще, просто свдигаешь побитово вправо, не внося дополнительной информации.
FrankinshteinПостоялецwww20 мар. 20120:12#3
Suslik
спасибо, конечно, но только об этом я уже выше написал)
shekhПостоялецwww20 мар. 20120:20#4
А чем плохо a*255/15 в целых числах.
HybernaculumПостоялецwww20 мар. 20121:14#5
shekh
> А чем плохо a*255/15 в целых числах.
Тем что делить на 15 в целых числах несколько медленнее (даже используя хитрую методику
для деления на числа вида 2^n -1) чем на 16 (которое реализуется простым сдвигом).
shekhПостоялецwww20 мар. 20121:53#6
Hybernaculum
> > А чем плохо a*255/15 в целых числах.
> Тем что делить на 15 в целых числах несколько медленнее (даже используя хитрую
> методику
> для деления на числа вида 2^n -1) чем на 16 (которое реализуется простым
> сдвигом).

Я комментировал идею считать это же деление в float.

HybernaculumПостоялецwww20 мар. 20122:13#7
shekh
> Я комментировал идею считать это же деление в float.
Во флоатах нет целых чисел ;)
AleX AciDПостоялецwww20 мар. 20122:31#8
Hybernaculum
можно сделать так
p.a = ((color & 0xF) << 4) + 0xf;
255 отобразится в 255
но
0 отобразится в 15

а можно так:
p.a = ((color & 0xF) << 4) | (color & 0xF);

HybernaculumПостоялецwww20 мар. 20123:46#9
AleX AciD
> а можно так:
> p.a = ((color & 0xF) << 4) | (color & 0xF);
Ты к чему это мне написал и при этом процитировал Frankinshtein ?
SuslikМодераторwww20 мар. 20123:51#10
AleX AciD
> можно сделать так
> p.a = ((color & 0xF) << 4) + 0xf;
> 255 отобразится в 255
> но
> 0 отобразится в 15
>
> а можно так:
> p.a = ((color & 0xF) << 4) | (color & 0xF);
так чёрное перестанет быть чёрным, прозрачное - прозрачным.
BishopПостоялецwww20 мар. 20125:39#11
А не проще ли воспользоваться float на SSE и считать чесное линейное преобразование? Грамотно использовать команды преобразования типов и всё будет ок.
FrankinshteinПостоялецwww20 мар. 20125:51#12
Bishop
не везде SSE есть ;-)

>>Тем что делить на 15 в целых числах несколько медленнее
на сколько медленнее?

FrankinshteinПостоялецwww20 мар. 201213:25#13
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 великовата получилась, может для нее хотя бы хитрая побитовая магия есть?:)

AleX AciDПостоялецwww23 мар. 20121:57#14
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;

/ Форум / Программирование игр / Графика

Тема в архиве.

2001—2018 © GameDev.ru — Разработка игр