Как представить бинарную прозрачность? - PullRequest
1 голос
/ 28 ноября 2009

В последнее время меня интересует представление несжатых растровых изображений в памяти. Тем не менее, я не уверен, как правильно реализовать бинарную прозрачность. Например, я начинаю с чего-то вроде этого:

struct RGBPixel {
 uint8_t red;
 uint8_t green;
 uint8_t blue;
};

struct bitmap {
 struct RGBPixel *data;
 size_t width;
 size_t height;
 size_t bytesPerPixel;
 size_t bytewidth;
 /* etc. */
};

Полагаю, самый простой способ был бы таким:

struct RGBPixel {
 uint8_t red;
 uint8_t green;
 uint8_t blue;
 bool transparent;
};

Но это кажется немного расточительным (вы могли бы также добавить полный альфа-канал). Единственная другая возможность, о которой я могу подумать, это зарезервировать один из цветов как прозрачный, но тогда вы потеряете способность отображать этот цвет. Есть ли стандартный способ сделать это?

Как это отражают общие форматы (GIF, 8-битный PNG и т. Д.)?

Ответы [ 5 ]

1 голос
/ 28 ноября 2009

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

Как вы указали, попытка сохранить один бит на пиксель с пиксельными данными RGB неэффективна. Вам, вероятно, следует либо сохранить все пиксели RGB в одном указателе, а затем растровое изображение с теми же размерами H и V в другом указателе, либо вы можете выполнить хроматическую настройку. Вы можете хранить данные с R, G, B и битовой картой прозрачности отдельно, как упомянуто выше, но это обычно очень неэффективно, когда дело доходит до их рисования.

1 голос
/ 28 ноября 2009

Gif использует указанный цвет для прозрачного. (например, допустим, что 0xFFFF00 прозрачен, поэтому все пиксели с этим цветом будут отображаться как прозрачные.) Этот цвет не может быть использован в этом изображении.
Png имеет альфа-канал, что означает другое целое число, представляющее альфа-значение пикселя. (например: 0 = полностью прозрачный, 255 = непрозрачный, 128 = полупрозрачный)

0 голосов
/ 28 ноября 2009

Вы можете хранить прозрачность в отдельной памяти или даже хранить каждый канал отдельно, например ::100100

struct bitmap {
 uint8_t *red;
 uint8_t *green;
 uint8_t *blue;
 uint8_t *transparency;
 // or packed: uint8_t *RGB, *transparency;
 size_t width;
 size_t height;
};

Затем выделите width*height / 8 байтов для канала прозрачности, и, предполагая, что 8 бит на канал цвета, вы можете получить доступ к битам следующим образом:

bool get_transparency( struct bitmap* bmp, size_t x, size_t y ) {
  size_t idx = y * bmp->width + x;
  size_t tidx = idx >> 3; // = idx / 8
  uint8_t t8 = (uint8_t)( idx & 7 ); // = idx % 8
  uint8_t mask = 1 << t8;
  return ( bmp->transparency[tidx] & mask ) != 0;
}

Обратите внимание, доступ к битам можно оптимизировать, это только пример.

Другое решение: вы можете провести немного по одному из цветовых каналов и определить свою структуру следующим образом:

struct RGBPixel {
 uint8_t red : 7;
 uint8_t transparency : 1;
 uint8_t green;
 uint8_g blue;
};

При сохранении или чтении красного канала вы должны соответственно масштабироваться, например, red = (uint8_t)( ( (uint16_t)pix->red * 8 ) / 7 );

0 голосов
/ 28 ноября 2009

Двоичная прозрачность также называется Chroma Keying. Вы определяете цвет как прозрачный цвет и в своей функции рисования рисуете пиксель, если его цвет не является цветным ключом (обозначен прозрачным цветом).

Альфа на пиксель используется при многоуровневой прозрачности, такой как тени.

0 голосов
/ 28 ноября 2009

Обычно существует четвертый альфа-канал для представления прозрачности.

т.е. вместо RBG у вас может быть RGBA.

...