Выровнять по границе слова в битовой карте RLE: противоречие в документации Microsoft
Документация Microsoft по сжатию растровых изображений, в частности описание BI_RLE8 (8-битный индексированный цвет с использованием сжатия кодирования по длине прогона), включает следующее описание абсолютного режима:
В абсолютном режиме первый байт равен нулю, а второй байт является значением в диапазоне от 03H до FFH. Второй байт представляет количество байтов, которые следуют, каждый из которых содержит индекс цвета [в таблицу цветов] одного пикселя. [...] В абсолютном режиме каждый прогон должен быть выровнен по границе слова.
Предположительно, это означает, что пробеги с нечетной длиной должны быть дополнены нулями (хотя это и не указано, я предполагаю, что слова имеют длину 16 битов в этом контексте).
Тем не менее, пример в документации включает прогон с нечетной длиной, который не заканчивается на границе слова:
[03 04] [05 06] [00 03 45 56 67] [02 78] [00 02 05 01] [02 78] [00 00] [09 1E] [00 01]
Должен 00 03 45 56 67
быть 00 03 45 56 67 00
?
3 ответа
Я изменил 8-битную индексированную цветную битовую карту, и результаты, по-видимому, указывают на то, что серии действительно должны быть дополнены нулями до конца на 16-битной границе слова (00 03 45 56 67
должно быть 00 03 45 56 67 00
).
Подробности:
В Microsoft Paint (версия 1607, включенная в Windows 10) я создал растровое изображение 4x4, содержащее красные (R), зеленые (G) и синие (B) пиксели в следующем порядке:
BRBR BBBB GGBB RRRG
- Я сохранил файл в виде 256-цветного растрового изображения (не было возможности использовать индексированный цвет или кодирование по длине прогона).
- Я открыл файл в Gnu Image Manipulation Program (GIMP), изменил цветовой режим на индексированный (через Image > Mode > Indexed) и экспортировал его как "Windows BMP", отметив опцию "Run-Length Encoded".
- Я сделал копию файла и открыл его в HxD (шестнадцатеричный редактор).
На этом этапе данные пикселей были представлены следующим образом (обратите внимание, что в соответствии с документацией изображение начинается слева внизу и продолжается слева направо):
03 4F // Three red pixels 01 71 // One green pixel 00 00 // EOL 00 04 71 71 E8 E8 // GGBB 00 00 // etc. 04 E8 00 00 00 04 E8 4F E8 4F 00 01 // EOF
- В начале области данных пикселей я заменил
03 4F
(три красных пикселя указаны в кодированном режиме; обратите внимание, что красный был отображен в индекс 0x4F = 79 в таблице цветов) с00 03 4F 4F 4F
(три красных пикселя указаны в абсолютном режиме без заполнения нулями), обновили размер файла в заголовке и сохранили изменения. - При открытии в GIMP и Paint измененный файл отображался неправильно: пиксели в первых двух строках и нижнем правом пикселе были черными, а последние два пикселя в третьей строке были зелеными, а не голубыми.
- В HxD я изменил
00 03 4F 4F 4F
в00 03 4F 4F 4F 00
(три красных пикселя, заданные в абсолютном режиме, с нулевым байтом, добавленным для завершения цикла на границе 16-битного слова), обновили размер файла в заголовке и сохранили файл. - При открытии в GIMP файл теперь отображается правильно. При открытии в Paint верхний ряд был черным (я подозреваю, что я не обновил поле заголовка, которое используется Paint, но не GIMP), но в остальном изображение было правильным.
Чтобы усилить утверждение в вопросе и существующий ответ, я нашел документ ( http://www.martinreddy.net/gfx/2d/BMP.txt), который содержит определенную спецификацию формата BMP.
Как ни странно, там показан тот же пример, за исключением того, что добавлен правильный байт заполнения (ниже цитата):
Absolute mode is signaled by the first byte in the pair being set to zero and
the second byte to a value between 0x03 and 0xFF. The second byte represents
the number of bytes that follow, each of which contains the color index of a
single pixel. Each run must be aligned on a word boundary. Following is an
example of an 8-bit RLE bitmap (the two-digit hexadecimal values in the
second column represent a color index for a single pixel):
Compressed data Expanded data
03 04 04 04 04
05 06 06 06 06 06 06
00 03 45 56 67 00 45 56 67
02 78 78 78
00 02 05 01 Move 5 right and 1 down
02 78 78 78
00 00 End of line
09 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E
00 01 End of RLE bitmap
Я только что на создал запросперенос этой проблемы, и она была исправлена.