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

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

#0
22:42, 19 мар 2012

Есть хорошие и быстрые способы это сделать?


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

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

#1
22:46, 19 мар 2012

вот щас подумал, что можно табличку преобразований расчитать в offline через float и прям в код ее вставить
если у кого есть готовая поделитесь:)

#2
23:53, 19 мар 2012

чтобы прозрачные объекты не становились немного непрозрачными, и непрозрачные не становились немного прозрачными, можешь посчитать честное линейное преобразование, которое четырёхбитное число [0..15] переводит в диапазон [0..255]. умножаешь число на 255.0f/15.0f и округляешь вниз. если это медленно, то можешь сделать табличку convert4to8[16], где будут храниться уже посчитанные значения каждого из 16 значений компоненты цвета. в обратную сторону проще, просто свдигаешь побитово вправо, не внося дополнительной информации.

#3
0:12, 20 мар 2012

Suslik
спасибо, конечно, но только об этом я уже выше написал)

#4
0:20, 20 мар 2012

А чем плохо a*255/15 в целых числах.

#5
1:14, 20 мар 2012

shekh
> А чем плохо a*255/15 в целых числах.
Тем что делить на 15 в целых числах несколько медленнее (даже используя хитрую методику
для деления на числа вида 2^n -1) чем на 16 (которое реализуется простым сдвигом).

#6
1:53, 20 мар 2012

Hybernaculum
> > А чем плохо a*255/15 в целых числах.
> Тем что делить на 15 в целых числах несколько медленнее (даже используя хитрую
> методику
> для деления на числа вида 2^n -1) чем на 16 (которое реализуется простым
> сдвигом).

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

#7
2:13, 20 мар 2012

shekh
> Я комментировал идею считать это же деление в float.
Во флоатах нет целых чисел ;)

#8
2:31, 20 мар 2012

Hybernaculum

можно сделать так
p.a = ((color & 0xF) << 4) + 0xf;
255 отобразится в 255
но
0 отобразится в 15

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

#9
3:46, 20 мар 2012

AleX AciD
> а можно так:
> p.a = ((color & 0xF) << 4) | (color & 0xF);
Ты к чему это мне написал и при этом процитировал Frankinshtein ?

#10
3:51, 20 мар 2012

AleX AciD
> можно сделать так
> p.a = ((color & 0xF) << 4) + 0xf;
> 255 отобразится в 255
> но
> 0 отобразится в 15
>
> а можно так:
> p.a = ((color & 0xF) << 4) | (color & 0xF);
так чёрное перестанет быть чёрным, прозрачное - прозрачным.

#11
5:39, 20 мар 2012

А не проще ли воспользоваться float на SSE и считать чесное линейное преобразование? Грамотно использовать команды преобразования типов и всё будет ок.

#12
5:51, 20 мар 2012

Bishop
не везде SSE есть ;-)

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

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

#14
1:57, 23 мар 2012

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;
ПрограммированиеФорумГрафика

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