Заполнение в 24-битном растровом файле rgb

может кто-нибудь объяснить мне, почему в 24-битном растровом файле rgb мне нужно добавить дополнение, размер которого зависит от ширины изображения? Зачем?

Я имею в виду, что я должен добавить этот код в свою программу (в C):

 if( read % 4 != 0 ) {
   read = 4 - (read%4);
   printf( "Padding: %d bytes\n", read );
   fread( pixel, read, 1, inFile );
  }
6
задан salieri 08 апр. '10 в 18:52
источник поделиться

5 ответов

Поскольку 24 бита представляют собой нечетное число байтов (3), и по целому ряду причин все строки изображения должны начинаться с адреса, который состоит из 4 байтов.

5
ответ дан Paul R 08 апр. '10 в 18:54
источник поделиться

В соответствии с Wikipedia формат растрового файла указывает, что:

Биты, представляющие пиксели растрового изображения, упаковываются в строки. Размер каждой строки округляется до кратного 4 байта (32-разрядный DWORD) путем заполнения. Для добавления длины строк в четыре байта необходимо добавить байты заполнения (не обязательно 0) в конец строк. Когда массив пикселей загружается в память, каждая строка должна начинаться с адреса памяти, который является кратным 4. Это ограничение адреса/смещения является обязательным только для загружаемых в память пиксельных массивов. Для целей хранения файлов только размер каждой строки должен быть кратным 4 байтам, а смещение файла может быть произвольным. 24-битная растровая карта с шириной 1, будет иметь 3 байта данных в строке (синий, зеленый, красный) и 1 байт заполнения, а Width = 2 - 2 байта заполнения, ширина = 3 - 3 байта padding, а Width = 4 не будет иметь никакого дополнения.

Статья в википедии о Прокладка структуры данных также является интересным чтением, которое объясняет причины, по которым прокладки обычно используется в информатике.

2
ответ дан MxNx 16 нояб. '16 в 10:46
источник поделиться

Я предполагаю, что это было конструктивное решение для выравнивания для более качественных паттернов памяти, не тратя впустую столько места (для изображения шириной 319 пикселей вы бы потратили 3 байта или 0,25%)

Представьте, что вам нужно получить доступ к некоторой нечетной строке напрямую. Вы можете получить доступ к первым 4 пикселям n-й строки, выполнив:

uint8_t *startRow = bmp + n * width * 3; //3 bytes per pixel
uint8_t r1 = startRow[0];
uint8_t g1 = startRow[1];
//... Repeat
uint8_t b4 = startRow[11];

Обратите внимание, что если n и ширина являются нечетными (и bmp равно), startRow собирается быть нечетным.

Теперь, если вы попытались сделать следующее ускорение:

uint32_t *startRow = (uint32_t *) (bmp + n * width * 3);
uint32_t a = startRow[0]; //Loading register at a time is MUCH faster
uint32_t b = startRow[1]; //but only if address is aligned
uint32_t c = startRow[2]; //else code can hit bus errors!

uint8_t r1 = (a & 0xFF000000) >> 24;
uint8_t g1 = (a & 0x00FF0000) >> 16;
//... Repeat
uint8_t b4 = (c & 0x000000FF) >>  0;

У вас возникло бы много проблем. В лучшем случае (то есть процессор Intel) каждый ваш груз a, b и c должен быть разбит на две нагрузки, поскольку startRow не делится на 4. В худшем случае (например, sun sparc) ваша программа будет сбой с "ошибкой шины".

В более новых конструкциях принято принудительно выравнивать строки по крайней мере до размера строки кеша L1 (64 байта на Intel или 128 байтов на nvidia gpus).

2
ответ дан vguberinic 24 сент. '15 в 17:49
источник поделиться

Это зависит от формата, есть ли отступ в конце каждой строки.

На самом деле это не так уж и важно для изображений с 3 x 8-битными каналами, так как I/O по-прежнему ориентирован на байты. Для изображений с пикселями, упакованными менее чем в байты (например, 1 бит/пиксель), заполнение полезно, так что каждая строка начинается со смещения байта.

1
ответ дан ergosys 08 апр. '10 в 19:18
источник поделиться

Краткая версия

Поскольку формат файла bmp указывает, что строки должны идеально вписываться в "ячейки памяти" размером 32 бита. Поскольку пиксели - 24 бита, некоторые комбинации пикселей не будут идеально сидеть в 32-битных "ячейках". В этом случае ячейка "заполняется до" всех 32 бит.

8 бит на байт ∴ ячейка: 32bit = 4bytes ∴ пиксель: 24 бит = 3 байта

 // If doesn't fit perfectly in 4 byte "cell"
 if( read % 4 != 0 ) {
   // find the difference between the "cell", and "the partial fit"
   read = 4 - (read%4); 
   printf( "Padding: %d bytes\n", read ); 
   // skip the difference 
   fread( pixel, read, 1, inFile ); 
  }

Длинная версия

При вычислении слово является естественной единицей данных, используемой конкретным дизайном процессора. Слово представляет собой часть данных фиксированного размера, обрабатываемых как единица набором команд или аппаратным обеспечением процессора.

- wiki: Word_ (computer_architecture)

В компьютерных системах в основном есть предпочтительная "длина слова" (хотя в наши дни это не так важно). Стандартный блок данных допускает всевозможные оптимизации в архитектуре компьютерной системы (подумайте, какие контейнеры для судоходства сделали для судоходной отрасли). Существует 32-битный стандарт, называемый DWORD aka Двойное слово (я думаю) - и это то, что типично растровые изображения оптимизированы.

Итак, если у вас есть 24 бит на пиксель, будут разные длины строк "буквальные пиксели", которые не будут хорошо вписываться в 32 бита. Поэтому в этом случае отложите его.

Примечание: сегодня вы, вероятно, используете компьютер с размером в 64 бит. Проверьте процессор.

0
ответ дан Ashley Coolman 22 июня '16 в 17:57
источник поделиться

Другие вопросы по меткам