Aufgabe 6: Ein JPEG-Decoder

Ähnliche Dokumente
Datenkompression. 1 Allgemeines. 2 Verlustlose Kompression. Holger Rauhut

JPEG Kompression technische Realisierung

JPEG, MPEG & Co. Alex Titze Angewandte Informatik FHTW-Berlin

JPEG - Kompression. Steffen Grunwald, Christiane Schmidt, Stephan Weck TIT01EGR BA-Mannheim 21. Mai 2002

Bildkompression InTh, 2005, JPEG, Hak, Rur, 1

Kompressionsverfahren

Verlustbehaftete Kompression. JPEG: Joint Photographic Experts Group

ffl Die Portable Bitmap Utilities (PBM) manipulieren monochrome Bilder. ffl Die Portable Greymap Utilities (PGM) manipulieren Grauwert-Bilder.

JPEG. Seminar: Kompressionsalgorithmen. Ruslan Ragimov. 5. September 2012

Kodierung. Kodierung von Zeichen mit dem ASCII-Code

Multimediatechnik / Video

J.P.E.G. Standard. J.P.E.G. Eigenschaften. J.P.E.G. System. JPEG Verschlüsselungsschritte. Farbmodell

Diskrete Cosinus-Transformation (DCT)

5. Licht, Farbe und Bilder

Dynamisches Huffman-Verfahren

Proseminar Datenkomprimierung Dr. U. Tamm. JPEG - Kompression WS 2002/03. Torsten Zichner

Bilddatenformate BMP GIF JPG. Digitale Bildverarbeitung Liedtke 7.1. Bezeichnung: Microsoft Windows Bitmap, BMP, DIB

6. Komprimierung. (Text)komprimierung ist ein Wechsel der Repräsentation von Daten, so daß sie weniger

GI Vektoren

Grafikformate. Grafikformate. Digitale Bildverarbeitung Bildkompression

Einführung in die Medieninformatik 1

Zusatzaufgabe 3 für Informatiker

Algorithmus zur komprimierten Übertragung von Textdaten an mobile Endgeräte

DIGITALE VIDEO KOMPRESSION AM BEISPIEL DES JPEG-VERFAHRENS

Digitalisierung. analoges Signal PAM. Quantisierung

16 - Kompressionsverfahren für Texte

3. Aufgabe: Bitmap-Datei

Algorithmen und Datenstrukturen

Grafikformate: JPG - PNG

Einführung Aufgabe 3 - MPEG. Tobias Reinsch 2011

Datenkompression. Vortrag von Markus Durzinsky Student der Otto-von-Guericke-Universität Magdeburg

Eigenschaften von Kompressionsverfahren

Informatik-Seminar Thema 6: Bäume

Grafikformate. Auflösung Farbtiefe Farbmodelle

Proseminar. Thema: Shannon-Fano und Huffman Verfahren

Molekulare Bioinformatik

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 14. Bäume. Bäume 1

DIGITALISIERUNG VON BILDERN. Ivana

Eine verlustbehaftete Komprimierung ist es, wenn wir einige Kleidungsstücke zu

Optimalcodierung. Thema: Optimalcodierung. Ziele

Bildkompression Proseminar Datenkompression Daniel Koch

Kompressionsverfahren

Grundlagen von Rasterdaten

Beispielhafte Testfragen (auch aus Schülerreferaten, Fragen können redundant sein, keine Audio Kompression berücksichtigt):

{0,1} rekursive Aufteilung des Datenraums in die Quadranten NW, NE, SW und SE feste Auflösung des Datenraums in 2 p 2 p Gitterzellen

Strings. Daten aus Dateien einlesen und in Dateien speichern.

Huffman-Kodierung. Fachbereich Medieninformatik. Hochschule Harz. Huffman-Kodierung. Referat. Henner Wöhler. Abgabe:

Diskrete Cosinustransformation (DCT)

Technische Informatik - Eine Einführung

10%, 7,57 kb 20%, 5,3 kb 30%, 4,33 kb 40%, 3,71 kb 50%, 3,34 kb. 60%, 2,97 kb 70%, 2,59 kb 80%, 2,15 kb 90%, 1,62 kb 99%, 1,09 kb

Algorithmen, Datenstrukturen und Programmieren II SS 2001

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Übungen zu Programmierung I - Blatt 8

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Digitales Video. Digitales Video

Einführung in die Informatik II Aus der Informationstheorie: Datenkompression

4. Licht, Farbe und Bilder

Gierige Algorithmen Interval Scheduling

Kodierungsalgorithmen

1.2.1 Analoges Speichern auf Vinyl Erläutern Sie die prinzipielle Funktionsweise von Langspielplatten bzw. Plattenspielern.

Digitale Bildverarbeitung (DBV)

Seminar Kompressionsalgorithmen Huffman-Codierung, arithmetische Codierung

Bildbearbeitung: Grafikformate II und Farbmodelle

Grundlagen der Informatik I Information und Daten

Übungspaket 32 Einfach verkettete, sortierte Liste

LZSS und Deflate. Lars Kunert. April 18, Seminar Kompressionsalgorithmen RWTH Aachen

Digital Imaging Einführung

Fragen 1. Muss eine DTM ein Wort zu Ende gelesen haben, um es zu akzeptieren? a) Ja! b) Nein!

6 Der Advanced Encryption Standard (AES)

Erinnerung Blockchiffre

Bilddateien. Für die Speicherung von Bilddaten existieren zwei grundsätzlich unterschiedliche Verfahren. Bilder können als

Arithmetisches Codieren

Einführung in die Informatik I

Teil VII. Hashverfahren

Binärbäume: Beispiel

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

Video. Grundlagen Videokompression

Wann sind Codes eindeutig entschlüsselbar?

Proseminar Datenkomprimierung Dr. U. Tamm. Bildkompression WS 2002/03. Florian Strunk

Die Digitalisierung von Musik

4.4 Quadtrees. Literatur

Digitale Bilder. Ein Referat von Jacqueline Schäfer und Lea Pohl Am

Die (Un-)Sicherheit von DES

Grundlagen digitaler Bildbearbeitung

Transkript:

Aufgabe 6: Ein JPEG-Decoder Einleitung JPEG ist ein populärer Standard zur Kompression von Bildern. Neben verlustfreien Kompressionsalgorithmen werden auch verlustbehaftete benutzt. Bei diesen wird die besondere Struktur von Bildern so ausgenutzt, daß der Informationsverlust der Kompression dem menschlichen Betrachter nur wenig auffällt. JPEG is nach seinen Schöpfern benannt, der Joint Photographic Expert Group. In JPEG werden verschiedene Techniken kombiniert: Huffman-Kodierung, Quantisierung, Fourier- Transformation, Differentielle Kodierung und andere. Ziel dieser Aufgabe ist es, ein C-Programm zu schreiben, welches eine JPEG-Datei der einfachsten und häufigsten Art (nicht-differentielle Huffman-Kodierung, drei Farbebenen, keine Zusatzfunktionen) dekodiert und dekomprimiert. Als Ergebnis soll eine Datei im PPM (portable pixmap)-format erzeugt werden. Digitalisierte Bilder: das PPM-Format Ein digitalisiertes Bild besteht aus einzelnen Bildpunkten, Pixel genannt. PPM ist eine naive Form der Speicherung dieser Pixel ohne jegliche Komprimierung oder Umordnung der Daten. Eine PPM-Datei beginnt mit einer Kennung. Das ist eine Zeile, die nur aus den 2 Zeichen P6 besteht. Es folgt eine Zeile, die aus 2 Zahlen besteht, der Breite w und Höhe h des Bildes in Pixel ( z.b. 608 320 ) und eine weitere Zeile, die für unsere Zwecke nur aus der Zahl 255 besteht. An diese 3 Zeilen schließt sich ein Strom von 3 w h Bytes an. Jeweils 3 Bytes kodieren Farbe und Helligkeit eines Pixels. Dazu wird jedes Byte als vorzeichenlose ganze Zahl zwischen 0 und 255 interpretiert. Die 3 Zahlen beschreiben die Intensität des Rot-, Grün- und Blauanteils (RGB-Kodierung): (0, 0, 0) ist Schwarz, (255, 255, 255) Weiß, (230, 230, 0) ein helles Gelb etc. Die Pixeldaten stehen einfach in Leserichtung (Zeile für Zeile von links nach rechts und oben nach unten) hintereinander. Huffman-Kodierung Die Huffman-Kodierung ist ein verlustfreier Kompressionsalgorithmus. Ein Alphabet soll so kodiert werden, daß die häufigere Zeichen durch kürzere Bit-Sequenzen dargestellt werden (ein Prinzip, von dem sich schon Samuel Morse bei der Erfindung seines Morsealphabets leiten ließ). Wie bei wohl allen Kompressionsalgorithmen ist das Entpacken wesentlich einfacher als das Packen. Letzteres erfordert eine umfangreiche Analyse der Input-Daten, ersteres bloß das Anwenden eines mitgelieferten Rezeptes. Das Rezept zur Huffman-Dekodierung läßt sich am einfachsten in Form einer Baumstruktur kodieren. Nehmen wir als Beispiel die Sprache Vokalisch, deren Alphabet die 5 Buchstaben A,E,I,O,U umfaßt. Der häufigste Buchstabe sei E, gefolgt von O,A,I und U. 0 1 E A 0 U 0 1 0 1 1 I O Der Datenstrom 101111101000 wird mit Hilfe des Huffman-Baums so dekodiert: Wir starten an der Wurzel des Baumes (wie in der Informatik üblich, steht der Baum auf dem Kopf) und nehmen die Bitfolge als Wegbeschreibung: 0 heißt den linken Weg nehmen, 1 den rechten Weg nehmen. Wenn wir eine Zweigspitze erreicht haben, steht ein Buchstabe fest und wir beginnen wieder an der Wurzel. Damit führt uns 1011 zu I, 11 zu O und 1010 zu U, 0 zu E und 0 zu E: IOUEE. Obwohl wir es mit einem Code variabler Länge zu tun haben, ist kein spezielles Trennzeichen nötig. Natürlich ist die Kompression nicht optimal. Sie könnte verbessert werden, indem man Silben aus 2 Buchstaben in den Huffman-Baum aufnimmt, dann Silben aus 3 Buchstaben etc. 1

Der JPEG-Algorithmus verwendet mehrere Huffman-Bäume, allerdings auf recht indirekte Art und Weise. Beschreibung des JPEG-Formats Im Folgenden wird das JPEG-Format beschrieben, wobei die Kapitel dieser Beschreibung (Farbmodell, Downsampling, Quantisierung, Fourier-Transformation, Huffman-Dekodierung, Analyse der Datei) vom Dekompressor in umgekehrter Reihenfolge angewandt werden müssen. Farbmodell JPEG verwendet nicht das RGB-Farbmodell, sondern eines, das YUV genannt wird: 3 Zahlen beschreiben Helligkeit (Y), Blauanteil (U) und Rotanteil (V) eines Pixels. Die Umrechnung in RGB ist durch die lineare Transformation R G = 1 0 8 5 1 1 3 4 Y 5 U B 1 2 0 V möglich. Implementierungshinweis: Die YUV-Werte, die man nach Fourier-Transformation und Dequantisierung aus den JPEG-Daten erhält, sind vorzeichenbehaftet, liegen zwischen -128 und 127. Dasselbe gilt auch für die RGB-Werte, die obige Transformation liefert. Manchmal können sie auch über diesen Bereich hinausschießen. Um sie z.b. mit der Funktion putc (die ihr Argument zu einem unsigned char konvertiert) korrekt in eine PPM-Datei ausgeben zu können, empfiehlt es sich: a) 128 zu addieren, b) zu testen, ob der Wert nun zwischen 0 und 255 liegt und kleinere Werte durch 0, größere durch 255 zu ersetzen. Downsampling Zentrales Objekt der Kompressionsalgorithmen ist eine data unit. Dies ist eine 8 8-Matrix von Y-, U- oder V-Werten. Im einfachsten Fall beschreibt sie auch einen Bildausschnitt von 8 8 Pixeln. Durch eine (verlustbehaftete) Kompressionsmethode namens Downsampling kann sie jedoch auch die Informationen für bis zu 32 32 Pixel enthalten. Dabei wird jeweils ein kleiner (z.b. 2 2) Block von Pixeln durch ein gemitteltes Pixel ersetzt. Üblicherweise wird das Downsampling nicht auf die Helligkeit (Y) angewendet, sondern nur auf die Farbkomponenten. Dadurch bleibt der wahrnehmbare Qualitätsverlust gering. Für jede der 3 Farbkomponenten YUV wird das Downsampling beschrieben durch 2 Parameter (h, w) (height, width): Blöcke aus h w Pixel wurden duch einen Pixel ersetzt. h und w können Werte zwischen 1 und 4 annehmen. Beim Entpacken muß also ein Upsampling durchgeführt werden, bei dem die 8 8-Matrix zu einer( 8h 8w-Matrix ) aufgebläht wird, indem man jeden Eintrag x durch eine h w-blockmatrix x x ersetzt. Für die Downsampling-Parameter h Y, h V, h U muß gelten kgv(h i ) = max(h i ) und kgv(w i ) = max(w i ). x Das Bild wird in kleine Rechtecke aus (8 max(h i ) 8 max(w i )) Pixel zerlegt, die MCUs (Minimal Coding Units) genannt werden. Nehmen wir an, die Y-Information wird nicht downsampled und die U- und V-Komponente werden um die Faktoren 2 2 bzw 4 4 downsampled. Dann beschreibt eine MCU 32 32 Pixel des Bildes und sie ist kodiert durch 16 Y-data-units, 4 U-data-units und eine V-data-unit. In genau dieser Reihenfolge sind sie auch im Datenstrom gespeichert, wobei die 16 Y-data-units (und 4 U-data-units) in Lesereihenfolge zeilenweise von links nach rechts und oben nach unten abgespeichert sind. x kgv: kleinstes gemeinsames Vielfaches. Dies bedeutet einfach, daß die elementaren Quadrate oder Rechtecke, in die das Bild für die verschiedenen Farbkomponenten zerschnitten wird, ineinander aufgehen müssen. 2

Der Datenstrom, der das Gesamtbild beschreibt, besteht aus einer Folge von MCUs ([16Y, 4U, 1V ], [16Y, 4U, 1V ],...), ebenfalls in Lesereihenfolge. Nach der Dekomprimierung hat man ein Bild, dessen Größe ein Vielfaches der MCU-Größe ist. Um es auf die Größe (H, W ) des Originals zu bringen, muß man eventuell rechts und unten ein paar Pixel wegschneiden. Fourier-Transformation und Quantisierung Der Schlüssel zur hohen Kompressionsrate von JPEG ist, daß die Bilddaten nicht direkt komprimiert, sondern vorher Fourier-transformiert werden. Die verwendete spezielle Form der Fourier-Transformation wird als Diskrete Cosinus-Transformation (DCT) bezeichnet. Die DCT führt eine 8 8-Matrix von Farbwerten in eine 8 8-Matrix über, deren [0, 0]-Komponente den Mittelwert der Originaldaten beschreibt, die anderen beschreiben die Amplituden der verschiedenen Schwankungen um diesen Wert. Zur Rücktransformation sind folgende Schritte nötig: Die JPEG-Datei enthält für jede Komponente (Y, U und V) eine Quantisierungstabelle aus 64 ganzen Zahlen. Jede der 64 Zahlen du[i], i=0...63 einer data-unit ist mit der entsprechenden Zahl aus der Quantisierungstabelle zu multiplizieren. Das Ergebnis ist in Fließkommazahlen umzuwandeln. Aus diesen 64 Zahlen wird jetzt eine 8 8-Matrix aufgebaut. Um eine optimale Kompression zu erreichen, sind diese Zahlen allerdings nicht zeilen- oder spaltenweise angeordnet, sondern im Zigzag. Das folgende Codestück beschreibt die notwendige Umordnung: const int zigzag[8][8] ={ { 0, 1, 5, 6,14,15,27,28}, { 2, 4, 7,13,16,26,29,42}, { 3, 8,12,17,25,30,41,43}, { 9,11,18,24,31,40,44,53}, {10,19,23,32,39,45,52,54}, {20,22,33,38,46,51,55,60}, {21,34,37,47,50,56,59,61}, {35,36,48,49,57,58,62,63}}; for(i=0; i<8; i++) for(j=0; j<8; j++) mat[i][j] = du[ zigzag[i][j] ]; Auf jede Zeile dieser Matrix (gelesen als Vektor Y 0,..., Y 7 ) und anschließend auf jede Spalte des Ergebnisses ist die inverse DCT X i = 1 2 2 Y 0 + 7 j=1 Y j ((2i 2 cos + 1)j π ) 16 für i = 0... 7 anzuwenden. Die Fließkommazahlen werden in ganze Zahlen umgewandelt. Dabei ist zur Null hin zu runden: 3, 7 3; 12, 8 12. Huffman-Dekodierung Zur Kodierung werden für jede der 3 Farbkomponenten 2 Huffman-Bäume verwendet, DC-Baum und AC-Baum genannt. Das Einlesen eines der 64 Werte du[i], i=0...63 einer data-unit aus dem Datenteil des SOS- Segments ist ein zweistufiger Prozeß, da nicht der Wert selbst, sondern seine Länge Huffmankodiert ist. 3

Der DC-Baum dient nur zum Einlesen des ersten Wertes du[0]: Lese Bits vom Datenstrom und laufe durch den DC-Baum, bis eine Spitze erreicht ist. Der an dieser Spitze gespeicherte Wert s gibt die Anzahl der nun einzulesenden Bits an. Die nächsten s Bits aus dem Datenstrom sind als positive ganze Zahl n zu interpretieren. Diese Zahl wird in eine vorzeichenbehaftete Zahl konvertiert nach der Vorschrift m = extend(n, s) { n if n 2 s 1 extend(n, s) = n + 1 2 s otherwise Dieser Wert m ist nur dann gleich du[0], wenn es sich um die erste data-unit des Bildes zu einer Farbkomponente handelt. Sonst ist m die Differenz zum Wert du[0] der vorhergehenden data-unit derselben Farbkomponente. Zur Dekodierung der übrigen 63 Werte wird der AC-Baum verwendet. Die an dessen Spitzen gespeicherten Bytes (Zahlen x zwischen 0 und 255) sind als zwei 4-Bit-Zahlen ( nibbles ) (r, s) = (x/16, mod (x, 16)) zu interpretieren. Die Dekodierung erfordert folgende Schritte: 1. Lese Bits aus dem Datenstrom ein, bis eine Spitze (r, s) des AC-Baumes ereicht ist. 2. Wenn r = s = 0, fülle die restlichen Felder von du[] mit Nullen, die data-unit ist fertig gelesen. 3. Wenn r > 0 ist, werden die nächsten r Felder in du[] mit Nullen gefüllt. 4. Dann werden die die nächsten s Bits aus dem Datenstrom gelesen und das Ergebnis von extend(n, s) wird in das nächste freie Feld von du[] gespeichert. 5. Wiederhole 1.-4., bis alle Felder von du[] gefüllt sind. Aufbau einer JPEG-Datei Eine JPEG-Datei besteht aus einer Folge von Segmenten verschiedenen Typs. Segmente beginnen mit 2 Startbytes, die den Segmenttyp kodieren, gefolgt von 2 Bytes, die die Länge L des Segments (ohne die beiden Startbytes) angeben und von L 2 Datenbytes. Eine Ausnahme sind die Segmente Start of Image (SOI) am Dateianfang und End of Image (EOI) am Dateiende, sie bestehen nur aus den 2 Bytes FFD8 (SOI) und FFD9 (EOI). In der folgenden Übersicht steht ein für ein Halbbyte (4 Bits), auch nibble genannt. SOI Start of Image FFD8 EOI End of Image FFD9 COM Comment FFFE L L-2 Bytes Kommentartext DQT Define Quantization Table FFDB 64 Bytes... 64 Bytes L = 2 + 65 n L i 1 QT 1 i n QT n SOF Start of Frame FFC0 3 Bytes... 3 Bytes L = 2 + 6 + 3 ne L cd H W ne Ebene 1 Ebene ne Jede Ebene hat den Aufbau i e w h n qt 4

DHT Define Huffman Table FFC4 16 Bytes data... 16 Bytes data L tc th ns[i] tc th ns[i] L = 2 + 1 + 16 + 15 i=0 ns[i] +... + 1 + 16 + 15 i=0 ns[i] SOS Start of Scan FFDA 2 Bytes... 2 Bytes data L nc Komponente 1 Komponente nc 3 Bytes Jede Komponente hat den Aufbau i c td ta Es gibt noch eine Reihe weiterer Segmente. Wenn Segmente mit den Kennungen FFC1, FFC2, FFC3, FFC5, FFC6, FFC7, FFC9, FFCA, FFCB, FFCC, FFCD, FFCE oder FFCF auftauchen, soll unser Entpacker abbrechen. Sie bedeuten, daß noch andere Kompressionsalgorithmen (differentielle arithmetische Kodierung, differentielle Huffman-Kodierung u.a.) angewendet wurden. Andere Segmente der Form FF L-2 Bytes können ignoriert werden. Sie könenn z.b. thumbnails ( daumennagelgroße Varianten des Bildes, die ein Programm zur Vorschau o.ä. verwenden kann) enthalten. Beschreibung der Segmente DQT JPEG-Dateien können bis zu 4 Quantisierungstabellen enthalten (auch wenn die hier besprochene Variante nur 3 verwendet). Sie können durch mehrere DQT-Segmente oder gemeinsam in einem DQT-Segment gespeichert sein. Die Anzahl der Tabellen in einem DQT-Segment läßt sich aus der Längenangabe L ableiten. Jede Tabelle hat eine Nummer i n. Die Tabelle selbst besteht aus 64 Bytes, von denen jedes eine Zahl zwischen 0 und 255 repräsentiert. Implementierungshinweis: int i; i=getc(filepointer); liest ein Byte korrekt in diesem Sinne (als Zahl zwischen 0 und 255) ein, weil getc() das eingelesene Byte als unsigned char interpretiert. Ebenso kann man die durch 2 Bytes kodierten Zahlen (wie die Längenangabe L) einlesen: int i,l; i=getc(filepointer); L=256*i+getc(filepointer); SOF Ein Frame enthält globale Informationen über das Bild. dc (1 Byte) enthält die Farbtiefe (color depth). Für unsere Zwecke sollte sie 8 sein: Jeder Farbwert wird mit 8 Bit (einem Byte) kodiert. H und W (je 2 Byte) geben die tatsächliche Größe des Bildes (Höhe und Breite in Pixeln) an. ne (1 Byte) gibt die Anzahl der Farbkomponenten an. Unser Dekoder soll nur mit genau 3 Farbkomponenten umgehen können. Es gibt auch schwarzweiße JPEG-Dateien mit nur einer Farbkomponente. Es folgen jeweils 3 Bytes für jede Farbkomponente. Sie enthalten eine Nummer i e und die Downsampling-Parameter w und h dieser Farbkomponente sowie die Nummer der Quantisierungstabelle n qt, die für diese Komponente zu verwenden ist. Es ist die Tabelle zu verwenden, für die i n = n qt gilt. 5

DHT Implementierungshinweis: Aus diesen Daten läßt sich die Größe einer MCU sowie die Anzahl der MCUs berechnen. Hierbei ist daran zu denken, daß man aufrunden muß, wenn H oder W nicht durch die Höhe oder Breite einer MCU teilbar ist. Die nibbles h und w lassen sich so einlesen: int x,h,w; x=getc(filepointer); w=x/16; h=x%16; Für jede Farbkomponente Y,U und V werden 2 Huffman-Bäume benötigt, ein DC- und ein AC- Baum. Die Bäume können in einem odere mehreren DHT-Feldern beschrieben sein. Sie sind numeriert durch die nibbles tc und th. Wenn tc ungleich 0 ist, dient der Baum als AC-Baum, wenn tc gleich 0 ist, als DC-Baum. th ist seine Nummer. Es folgt eine 16 Bytes lange Liste ns[]. Die Bytes geben an, wieviele Huffman-Kodes der Länge 1 Bit, 2 Bit,... 16 Bit abgespeichert sind. (Für unseren Vokal-Beispielbaum hieße das ns = [1, 1, 1, 2, 0,...].) Danach folgt eine Liste der an den Zweigspitzen zu speichernden Daten, nach aufsteigender Länge der Kodes sortiert. Diese Liste ist somit 15 i=0 ns[i] Bytes lang. Die Daten sind Bytes, Zahlen zwischen 0 und 255. Bei den AC-Bäumen werden sie später als 2 nibbles interpretiert. Diese Daten bestimmen einen Baum eindeutig, wenn er so konstruiert wird, daß der Abstand Spitze-Wurzel von links nach rechts zunimmt. B A D E F G C H Ein Beispiel: Sei ns = [0, 1, 5, 1, 1] und die 8 Bytes in diesem Baum sind in der Reihenfolge BADEFG- CH gegeben. Damit sind die Huffman-Kodes B=00, A=010, D=011, E=100, F=101, G=110, C=1110, H=11110. Die letzte Spitze bleibt leer. Implementierungshinweis: Material zu Bäumen und anderen Datenstrukturen findet man z.b. in R. Sedgewick, Algorithmen in C. Eine Möglichkeit ist, einen Knoten des Baumes als Struktur mit Zeigern auf die Unterknoten zu definieren und den Baum gemäß den DHT-Daten durch Aufrufe von createnode zu erzeugen. Dies kann z.b. auch rekursiv geschehen. struct node { unsigned char Item; struct node *l; struct node *r; }; struct node * createnode(unsigned char a){ struct node * x = malloc(sizeof(struct node)); x->l=0; x->r=0; x->item=a; return x; } SOS Das eigentliche Datenfeld. Bevor es losgeht mit dem Strom Huffman-kodierter und komprimierter MCUs, folgen nochmal Daten über die Farbkomponenten. Im nc-byte steht nochmal deren Anzahl, dann folgt für jede Komponente ein 2-Byte-Feld, das aus 3 Zahlen besteht: einem Index i c und den Nummern td und ta der für diese Komponente zu verwendenden DC- und AC-Huffmanbäume. Die Daten mit dem Index i c ergänzen die Daten aus dem SOF-Segment mit dem gleichen Index i e. Es folgen noch 3 Bytes, deren Inhalt für die hier beschriebene JPEG-Variante irrelevant ist. Beim Einlesen des folgenden Datenstroms ist eine Besonderheit zu beachten: Er endet, wenn ein neuer Segment-Markierer kommt, d.h., ein FF-Byte gefolgt von einem Byte ungleich 0. In der Regel wird das der EOI-Marker FFD9 und auch das Ende der Datei sein. Nun können solche Sequenzen natürlich auch als Teil der Bilddaten entstehen. Deshalb gilt eine Sonderregel: Wenn die Bilddaten ein FF-Byte enthalten, wird ihm ein zusätzliches 00-Byte angehängt. Dieses 00-Byte ist nicht Teil der Bilddaten und muß beim Einlesen herausgefiltert werden. 6