Разбор растровых данных GIF-LZW

Я пытался распаковать GIF в PHP и, похоже, есть все, кроме декомпрессии LZW. Я сохранил изображение, которое показано ниже: sample image

это изображение 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:

http://www.matthewflickinger.com/lab/whatsinagif/index.html