Разбор растровых данных GIF-LZW
Я пытался распаковать GIF в PHP и, похоже, есть все, кроме декомпрессии LZW. Я сохранил изображение, которое показано ниже:
это изображение 3 x 5, как это:
Blue Black Black
Black Blue Black
Black Black Black
White White White
White White White
Я решил пройти вручную в двоичном формате и проанализировать этот файл. Результат ручного анализа приведен ниже. Я все еще застрял в том, как декодировать растровые данные здесь. Может ли кто-нибудь сломать, как растровые данные становятся изображением? Мне удалось сломить одного. образ, но ничего больше (не этот образ). Я опубликовал свое понимание того, как это должно сломаться, но я, очевидно, делаю это неправильно.
01000111 G
01001001 I
01000110 F
00111000 8
00111001 9
01100001 a
Screen Descriptor
WIDTH
00000011 3
00000000
00000101 5
00000000
10010001 GCM (1), CR (001), BPP (001), CD = 2, COLORS = 4
00000000 BGCOLOR Index
00000000 Aspect Ratio
GCM
BLUE
00110101 | 53
00000000 | 0
11000001 | 193
WHITE
11111111 | 255
11111111 | 255
11111111 | 255
BLACK
00000000 | 0
00000000 | 0
00000000 | 0
00000000 | 0
00000000 | 0
00000000 | 0
Extension
00100001 | 21
Function Code
11111001 | F9
Length
00000100 | 4
00000000
00000000
00000000
00000000
Terminator
00000000
Local Descriptor
00101100 Header
XPOS
00000000 | 0
00000000
YPOS
00000000 | 0
00000000
Width
00000011 | 3
00000000
Height
00000101 | 5
00000000
Flags
00000000 (LCM = 0, Interlaced = 0, Sorted = 0, Reserved = 0, Pixel Bits = 0)
RASTER DATA
Initial Code Size
00000010 | 2
Length
00000101 | 5
Data
10000100
01101110
00100111
11000001
01011101
Terminator
00000000
00111011 | ;
00000000
Моя Попытка
10000100
01101110
00100111
11000001
01011101
Начальный Размер Кода = 3 Читайте 2 бита за раз
10
00
Append last bit to first (010)
String becomes 010 or 2. 2 would be color # 3 or BLACK
на данный момент, я уже не так. Первый цвет должен быть синим.
ресурсы я был использование:
http://www.daubnet.com/en/file-format-gif http://en.wikipedia.org/wiki/Graphics_Interchange_Format http://www.w3.org/Graphics/GIF/spec-gif87.txt
5 ответов
парсер GIF
Вы сказали, что хотите написать свой собственный парсер GIF, чтобы понять, как он работает. Я предлагаю вам посмотреть исходный код любой из библиотек, содержащих gif-ридеры, такие как де-факто ссылочная реализация GIFLIB. Соответствующий исходный файл dgif_lib.c
начало at slurp
для декодирования, или перейти к реализация декомпрессии LZW.
вот как ваше изображение декодирует.
Я думаю, проблема заключалась в том, что вы неправильно разделяли входные байты на коды LZW.
количество цветов составляет (0b001 + 1) * 2 = 4
.
размер кода начинается с 2 + 1 = 3 бит.
Итак, начальный словарь
000 = color 0 = [blue]
001 = color 1 = [white]
010 = color 2 = [black]
011 = color 3 = [black]
100 = clear dictionary
101 = end of data
теперь GIF упаковывает коды LZW в байты в LSB-первом порядке. соответственно, первый код хранится как 3 наименее значимых бита первого байта; второй код как следующие 3 бита; и так далее. В вашем примере (первый байт: 0x84
= 10000100
), первые 2 кода таким образом 100
(Clear) и 000
(синий). Все это
01011101 11000001 00100111 01101110 10000100
разбивается на коды (переключается на 4-битные группы после чтения самого высокого 3-битного кода,111
) как
0101 1101 1100 0001 0010 0111 0110 111 010 000 100
это расшифровывается до:
last
code code
100 clear dictionary
000 output [blue] (1st pixel)
010 000 new code in table:
output 010 = [black]
add 110 = old + 1st byte of new = [blue black] to table
111 010 new code not in table:
output last string followed by copy of first byte, [black black]
add 111 = [black black] to table
111 is largest possible 3-bit code, so switch to 4 bits
0110 0111 new code in table:
output 0110 = [blue black]
add 1000 = old + 1st byte of new = [black black blue] to table
0111 0110 new code in table:
output 0111 = [black black]
add 1001 = old + 1st byte of new = [blue black black] to table
...
Итак, начинается вывод (обертывание в 3 столбца):
blue black black
black blue black
black black ...
что вы и хотели.
решение без написания собственного gif reader
к твоему сведенью, это попробовать.
несколько заметок
- ваш GIF-файл GIF89a. Вы связаны со спецификацией GIF87a;спецификация 89a здесь.
- вы, похоже, обеспокоены тем, что использование библиотеки для анализа изображения повредит производительности. В этом нет никакого смысла. Библиотеки, как правило, реализованы в оптимизированном C; ваш ручной прокат решение будет написано на PHP, интерпретируемом языке.
- Вы упомянули PCX, которые поддерживают библиотеки, такие как imagemagick.
или просто используйте PNG
по словам руководство по программированию ZPL 2, PNG поддерживается. Например,~DY
(скачать графику) команда принимает b
(format) параметр, для которого P
(PNG) является опцией, помимо GRF по умолчанию. См. также печать PNG-изображений в сеть zebra принтер.
здесь много библиотек для преобразования GIF в PNG. Вы могли бы использовать ImageMagick (привязка PHP), или просто используйте функции PHP imagecreatefromgif
и imagepng
.
Я не могу помочь вам с декодированием LZW, но не было бы проще просто использовать библиотечную функцию, такую как imagecreatefromgif()
из расширения PHP GD для анализа файла GIF и извлечения данных изображения, которые затем можно преобразовать в целевой формат?
хорошо, что вы хотите знать, как делать LZW без использования библиотек, написанных кем-то другим. LZW не декодирует изображения пиксель за пикселем. Он ищет повторяющиеся блоки в потоке данных, сохраняет их в словаре и ссылается на них. Если 100 пикселей повторяются где-то, для воспроизведения этих 100 пикселей вместо 100 используется только один код, как с растровыми изображениями (BMP). Вот почему GIF отлично подходит для диаграмм, где у вас может быть много серий из 100 белых пикселей, а затем несколько черных нарисовать линию. С другой стороны, это паршиво для фотографий, потому что очень мало длинных повторов, и GIF обычно ограничен 256 цветами, если вы не используете некоторые сложные трюки.
коды, используемые в сжатом файле, длиннее цветовых кодов для каждого пикселя исходного изображения. Только потому, что длинные блоки повторения являются общими в диаграммах, возможно массовое сжатие.
этот сайт является отличным ресурсом о формате GIF и предлагает отличное объяснение процесса сжатия и декомпрессии LZW: