Вопрос

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

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 и т. д.)?

Это было полезно?

Решение

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

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

Другие советы

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

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

то естьвместо RBG вы можете использовать RGBA.

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

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

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

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);

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top