Заполнение в 24-битном RGB растровом изображении - PullRequest
10 голосов
/ 08 апреля 2010

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

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

 if( read % 4 != 0 ) {
   read = 4 - (read%4);
   printf( "Padding: %d bytes\n", read );
   fread( pixel, read, 1, inFile );
  }

Ответы [ 5 ]

7 голосов
/ 08 апреля 2010

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

4 голосов
/ 16 ноября 2016

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

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

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

3 голосов
/ 24 сентября 2015

Я предполагаю, что это было дизайнерское решение для выравнивания для улучшения структуры памяти, при этом не тратя так много места (для изображения шириной 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 Cpu) каждую нагрузку a , b и c необходимо разбить на две нагрузки, так как startRow не делится на 4. В худшем случае (например, sun sparc) ваша программа вылетает с «ошибкой шины».

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

1 голос
/ 22 июня 2016

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

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

8 бит на байт ∴ ячейка: 32 бита = 4 байта ∴ пиксель: 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_ (компьютерная архитектура)

Компьютерные системы в основном имеют предпочтительную «длину слова» (хотя в наши дни это не так важно). Стандартный блок данных допускает все виды оптимизаций в архитектуре компьютерной системы (подумайте, что сделали морские контейнеры для судоходной отрасли). Существует 32-битный стандарт, называемый DWORD он же Double word (я полагаю) - и именно для этого оптимизированы типичные растровые изображения .

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

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

1 голос
/ 08 апреля 2010

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

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

...