Hallo Cheatah,
zum Testen hab ich mir in PSP (3.11) mal ein Bildchen
von 16 Pixel Breite und 2 Pixel Höhe in 16 Farben
gebaut und in GIF87a abgespeichert. Die Farben sind
in der Reihenfolge der Palette angeordnet.
Übereinanderliegende Bytes haben gleiche Farben.
Und so sieht die Datei aus:
-------- HEADER
47 49 46 'GIF' = Signature
38 37 61 '87a' = Version Number
-------- SCREEN DESCRIPTOR
10 00 Screen Width
02 00 Screen Heigth
B3 1011_0011
M = 1 = Global Color Map
cr = 011 = Number of Color Resolution
0 = %
pixel = 011
00 Background Color Index
00 %
-------- GLOBAL COLOR MAP
00 00 00 color#0
BF 00 00 color#1
00 BF 00 color#2
BF BF 00 color#3
00 00 BF color#4
BF 00 BF color#5
00 BF BF color#6
C0 C0 C0 color#7
80 80 80 color#8
FF 00 00 color#9
00 FF 00 color#10
FF FF 00 color#11
00 00 FF color#12
FF 00 FF color#13
00 FF FF color#14
FF FF FF color#15
-------- EXTENSION BLOCK
21 '!' = Extension Block Introducer
F9 Function Code
04 Byte Count
01 00 00 Function Data Bytes
00 Extension Block Terminator
-------- IMAGE DESCRIPTOR
2C ',' = Image Separator Character
00 00 Image Left
00 00 Image Top
10 00 Image Width
02 00 Image Height
00 Flags
-------- RASTER DATA BLOCK
04 Code Size
12 Block Byte Count
10 04 31 Raster Data
48 31 07
25 B5 58
73 8F 44
59 98 C6
79 60 04
00 Block Terminator
--------
3B ';' = GIF TERMINATOR
--------
Der Header ist wie erwartet.
Beim Screen Descriptor waren aber schon ein paar
unerwartete Dinge dabei.
Die Bildbreite und die Höhe sind um ein bit größer
als ich erwartet hätte. So wie es ist, kannst Du
theoretisch ein Bild der Größe null definieren.
Wozu soll das gut sein? PSP läßt nur ab 2*2 zu.
Der Rest des Screen Descriptors ist wie erwartet.
Die Global Color Map hat PSP mir gemacht und ent-
spricht halt 'steinzeitlichen' Farbpaletten wie
sie dazumal bei CGA-Karten üblich waren.
Dann kommt unerwartet ein Extension Block.
Wozu PSP den reinschreibt ist mir nicht klar,
in der GIF87a-Spezifikation steht zwar, daß er
existieren kann, das hört sich wie optional an.
Dann steht aber dabei, daß ein Dekoder den Block
erkennen und bearbeiten können muß. Wenn er ihn
nicht verarbeiten kann, dann muß er die Anweisungen
ignorieren, stolpern darf er jedoch nicht!
Dieser Block ist nicht komprimiert.
Eine Erklärung für Function Code hab' ich auf
die Schnelle nicht gefunden.
Byte Count sieht mir wie ein Offset auf den
nächsten Block vor, zeigt in diesem Fall von
sich selbst auf das letzte Zeichen des Extension
Blocks, oder wie bei Prozessoren üblich, schon auf
das erste Zeichen des darauffolgenden Blocks.
Bei PERL wohl eher der erste Fall.
Der Image Descriptor fängt, wie spezifiziert mit
dem Komma an. Die vier Werte für Offset und Größe
sind wie erwartet.
Bei den Flags hätte ich aber schon was erwartet (Bit_2..0).
Bit_7 = M ist null weil es keine Local Color Map gibt.
Bit_6 = I ist null weil sequentiell = not interlaced.
Bit_5 = Null weil reserved (oder S wie Sorted).
Bit_4 = Null weil reserved.
Bit_3 = Null weil reserved.
Bit_2..0 = bits/pixel wieso null?
Zumindest eine 1 hätte ich da erwartet.
In der 87a-Spezifikation steht was von:
pixel+1 - # bits per pixel for this image.
Wenn ich von dem Wert noch einen abziehe,
dann liege ich wohl voll daneben.
Also muß es wohl so verstanden werden, daß diesem Wert
noch eine 1 dazugezählt werden muß um den endgültigen
Wert zu erhalten. Naja, 'ne Zuweisung steht da nirgends.
Raster Data Block fängt mit der Code Size an. Das war
doch die Sache mit der man die 'string table' für die
Komprimierung aufbaut? Versuch kommt noch.
Danach kommt das Block Byte Count Byte. Ein Block darf
also maximal 256 Byte enthalten (komprimierte Bytes!)
Innerhalb des Raster Data Blocks wiederholen sich dann
gegebenenfalls Block Byte Count und die Daten.
Code Size und Terminator sind für ein ganzes Bild gemeinsam.
GIF Terminator ist wie erwartet.
--------
RASTER DATA
Wenn ich mich nicht furchtbar täusche, sollten die
unkomprimierten Bilddaten wie folgt lauten:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
Ob's stimmt? Wenn ich das in .BMP abspeichere
steht es folgendermaßen in der Datei:
01 23 45 67 89 AB CD EF 01 23 45 67 89 AB CD EF
Auch logisch bei 4-bit-Farben.
Auch schon etwas komprimiert, zumindest gepackt.
Auch wenn ich das als .TIF unkomprimiert abspeichere,
sehe ich so ein Muster. Hab' ich mich nun getäuscht?
Wenn ich die Längen vergleiche glaub ich das aber
wieder nicht. Das .BMP-Muster ist 16 Byte oder 32
Nibble lang, das komprimierte .GIF-Muster ist 18
Byte lang und meine erste Annahme ist 32 Byte lang.
Die komprimierten Daten sollten (laut PSP) so aussehen:
10 04 31 48 31 07 25 B5 58 73 8F 44 59 98 C6 79 60 04
Dazwischen liegt nur noch der Kompressionsalgorithmus.
Mal sehen ob ich Steve Blackstock nachvollziehen kann.
Das erste was zu machen ist, ist die 'string table'.
Wie wär's mit:
<CC><EOI>
#0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #A #B #C #D #E #F #10 #11
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11
Der code für <CC> ist auf 10hex gesetzt. In der Beschreibumg
steht, daß dieses der erste auszugebende code sein soll.
In der Tat hat PSP das auch so gemacht.
Und nun?
Das erste Eingangszeichen ist 00hex. Das Zeichen existiert
in der 'string table', [.c.] wird 0, sonst passiert nichts.
Nun holen wir das nächste Zeichen = 01.
Damit ist [.c.]K = 0001. Das Zeichen ist nicht in der 'string
table', wir schreiben eine #0 in den Ausgangastrom und tragen
0001 in #12 der 'string table' ein.
Hmmm, irgendwie komme ich damit nicht klar.
Wenn die eben rausgeschriebene 0 ei Nibble ist, dann ist das
zwar noch als erster Teil der 04 in Ordnung, aber wie zum
Teufel soll ich auf die 4 der 04 kommen?
Da werde ich wohl doch noch mal weiterknobeln und
schmökern müssen.
Klaus