Mein Format Codieren
Die Umwandlung eines BMP-Bildes in ein DSO/TRN (Abklatsch des JPG-Formates)
1.0 Einleitung
Eine genaue Ausprogrammierung des JPG- Formates war leider nicht möglich,
da eine gute Beschreibung des Formates nicht aufzutreiben war. Ich hatte
zwar eine C-Version, doch erstens war diese Version wieder an DOS angepasst.
Und wer C kennt, versteht, daß eine 600KB Ausprogrammierung eine
Lesezeit von etwa einem Monat erwartet. Die Programmierung eines Formates
kann so nicht erfolgen. Das Verständnis des Formates erfordert jede
Einzelheit, da eine Optimierung sonst nicht möglich wird. So kam es
jedenfall zu einem eigenständigem Format. Dieses Format wurde vom
Algorithmus ähnlich dem JPG aufgebaut, jedoch mit folgenden Unterschieden:
-
größere Bildblöcke
-
Bildaufbau von unten nach oben (Windowsanpassung)
-
festgesetzte eigene Huffman- und Quantisierungs- Tabellen
-
begrenzte Freguenzbereiche und Farbtiefe (nur 24bit)
-
Quantisierungstabellen mit 2'er Potenzen
Es sei zu sagen, daß die Kompressionsrate im Vergleich zur Qualität
dem JPG leider nachsteht, da eine Einarbeitung in die Huffmancodierung
zeitlich nicht mehr möglich war. Ich glaube hier (Huffmancodierung)
liegt auch noch ein anderes großes
Manko, denn die Huffman- Tabellen sind nicht im File gespeichert. So
wird dieses Format eigentlich schwer änderbar und nur in sich kompatibel
sein
2.0 Die schrittweise Umwandlung
von BMP nach DSO bzw. TRN
Die Umwandlung eines 24bit Bildes in ein DSO bzw TRN- Format erfolgt schrittweise.
Die Unterteilung der Schritte ist hier kurz dargestellt.
-
1. Schritt Umwandlung eines RGB- Bildes in ein YUV(4:1:1)- Bild
-
2. Schritt Cosinustransformation einer 8 * 8- Matrix
-
3. Schritt Quantisierung einer 8 * 8- Matrix
-
4. Schritt Zig-Zag-Scanning einer 8 * 8- Matrix in 64iger Vektor
-
5. Schritt Eliminierung / Zusammenfassung der Nullen in 6 Vektoren
-
6. Schritt Huffmann- Codierung von zusammengefaßten Vektorblöcken
2.1 Der 1. Schritt, Umwandlung eines RGB- Bildes
in ein YUV(4:1:1)- Bild
Die Vorlage zum Packen ist ein ganz normales 24bit BMP-Bild. Dieses Bild
wird blockweise gelesen. Ein Bildblock besteht aus 16 Zeilen. Falls der
letzte Block kleiner als 16 Zeilen ist, werden die restlichen Zeilen mit
der zuletzt gelesenen Zeile aufgefüllt. Damit wird der Fehler am kleinsten
gehalten, und eine höhere Packrate wird erzielt, weil wahrscheinlich
somit die geringste Änderungen vorhanden ist. Der gelesene 16 Zeilenblock
wird nun in kleinere Blöcke unterteilt. Diese kleineren Blöcke
nenne ich MCU-Block Eine MCU besteht aus 16 * 16 Pixeln. Sollte die letzte
MCU nicht vollständig gefüllt sein (Zeilenlänge mod 16 <>
0), so wird die MCU mit der letzten Pixelspalte gefüllt, um den geringsten
Fehler herzustellen. Zusammengefaßt kann man sagen: "Ein Bild wird
in 16 * 16 Pixel- Matrizen aufgeteilt". Diese MCU wird wiederum in vier
8 * 8- Matrizen zerlegt. (Die 8 * 8 Matrizen sind für die Cosinustransformation.
Wir brauchen vier 8 * 8 RGB-Matrizen. Da aus vier
8 * 8 RGB-Matrizen vier 8 * 8 Y-Matrizen werden und je eine 8 * 8 U-Matrix
und eine 8 * 8 V-Matrix. Also kann damit immer eine vollständige 8
* 8 Matrix bei der Umwandlung entstehen.) Jede 8 * 8 RGB-Matrize wird dann
als sechzehn je
2 * 2 Pixel- Matrizen betrachtet. Nun warum das Ganze zerlegen? Eine
schrittweise Erklärung erfolgt.
Der erste Umwandlungsschritt ist die YUV-Zerlegung. YUV ist ein Farbmodell,
das wie das RGB-Modell aus drei Komponenten besteht. Das RGB-Modell geht
von der Intensität der 3 Komponenten Rot,Grün und Blau aus. Ein
Pixel, der z.B. voll Rot ist, hat somit Rot=255, Grün=O, Blau=O.
Die Farbe Weiß ist ein Gemisch mit Rot=255, Blau=255 und Grün=255.
Bei Schwarz sind die drei Komponenten auf Null usw. Das YUV-Modell legt
Wert auf die Helligkeit eines Pixels,den Rot und den Blauanteil. (Y=Helligkeit,
U=Blaukomponente und V ist die Rotkomponente). Worin liegt der Sinn des
Ganzen? Das rnenschlich Auge ist 10mal empfinlicher auf Helligkeitsunterschiede
als auf Farbunterschiede. Außerdem wird die Farbe Grün am stärksten
wahrgenommen. (Das Auge ist am empfindlichsten auf Frequenzen im Grünbereich).
Eine Umwandlung von RGB nach YUV wird formelmäßig später
beschrieben. Durch diese Umwandlung wir nichts verändert, außer
die Wertebedeutung. Jedoch kann man die Farbinformationen ein wenig "ausdünnen".
Wir nehmen 4 beieinanderliegende Pixel, und wandeln die Pixel ins YUV.
So entstehen 4 Y,4 U, 4 V Werte. Aus den 4 U-Werten bilde ich den Mittelwert
und reduziere ihn auf eine Blaukomponente je 4Pixel. Das gleiche wird mit
der Rotkomponente durchgeführt. Damit wäre der 1.Schritt getan.
Aus je 4 RGB-Werten werden 4Y- ein U- und ein V– Wert. Dieses Format nennt
sich YUV 4:1:1. Das ungeübte Auge erkennt nach einer Rückwandlung
bzw.Darstellung keinen Unterschied. Bei genauer Betrachtung fällt
es aber doch auf und zwar bei harten Farbübergängen.
Vollständige MCU in einem RGB-Bild-Ausschnitt
|
|
|
E0 E1
F0 F1
|
E2 E3
F2 F3
|
E4 E5
F4 F5
|
E6 E7
F6 F7
|
|
|
E8 E9
F8 F9
|
EA EB
FA FB
|
EC ED
FC FD
|
EE EF
FE FF
|
|
|
|
0E 0F
1E 1F
|
|
2E 2F
3E 3F
|
|
4E 4F
5E 5F
|
|
6E 6F
7E 7F
|
|
|
00 11
10 11
|
02 03
12 13
|
04 05 14 15
|
06 07
16 17
|
|
20 21
30 31
|
22 23
32 33
|
24 25
34 35
|
26 27
36 37
|
|
40 41
50 51
|
42 43
52 53
|
44 45
54 55
|
46 47
56 57
|
|
60 61
70 71
|
62 63
72 73
|
64 65
74 75
|
66 67
76 77
|
|
|
08 19
18 19
|
0A 0B
1A 1B
|
0C 0D 1C 1D
|
0E 0F
1E 1F
|
|
28 29
38 39
|
2A 2B
3A 3B
|
2C 2D
3C 3D
|
2E 2F
3E 3F
|
|
48 49
58 59
|
4A 4B
5A 5B
|
4C 4D
5C 5D
|
4E 4F
5E 5F
|
|
68 69
78 79
|
6A 6B
7A 7B
|
6C 6D
7C 7D
|
6E 6F
7E 7F
|
|
|
00 11
10 11
|
|
20 21
30 31
|
|
40 41
50 51
|
|
60 61
70 71
|
|
|
8E 8F
9E 9F
|
|
AE AF
BE BF
|
|
CE CF
DE DF
|
|
EE EF
FE FF
|
|
|
80 81
90 91
|
82 83
92 93
|
84 85 94 95
|
86 87
96 97
|
|
A0 A1
B0 B1
|
A2 A3
B2 B3
|
A4 A5
B4 B5
|
A6 A7
B6 B7
|
|
C0 C1
D0 D1
|
C2 C3
D2 D3
|
C4 C5
D4 D5
|
C6 C7
D6 D7
|
|
E0 E1
F0 71
|
E2 E3
F2 F3
|
E4 E5
F4 F5
|
E6 E7
F6 F7
|
|
|
88 89
98 99
|
8A 8B
9A 9B
|
8C 8D 9C 9D
|
8E 8F
9E 9F
|
|
A8 A9
B8 B9
|
AA AB
BA BB
|
AC AD
BC BD
|
AE AF
BE BF
|
|
C8 C9
D8 D9
|
CA CB
DA DB
|
CC CD
DC DD
|
CE CF
DE DF
|
|
E8 E9
F8 F9
|
EA EB
FA FB
|
EC ED
FC FD
|
EE EF
FE FF
|
|
|
80 81
90 91
|
|
A0 A1
B0 B1
|
|
C0 C1
D0 D1
|
|
E0 E1
F0 F1
|
|
|
|
|
00 01
10 11
|
02 03
12 13
|
04 05
14 15
|
06 07
16 17
|
|
|
08 09
18 19
|
0A 0B
1A 1B
|
0C 0D
1C 1D
|
0E 0F
1E 1F
|
|
|
2.1.1 Programmtechnische
Umsetzung
Es werden mit einem Mal vier 4 * 4 RGB-Pixel in das YUV-Format umgerechnet,
da sich das leichter rechnen läßt und einen
geringeren Proceduren- Overhead verursacht. Man könnte auch eine
ganze 8 * 8 Matrix berechnen. Doch dann wird der Programmcode nur wesentlich
größer und vielleicht nur geringfügig schneller.
Quelle ist das RGB- Bild
|
P00
|
P01
|
P02
|
P03
|
P04
|
P05
|
P06
|
P07
|
|
P10
|
P11
|
P12
|
P13
|
P14
|
P15
|
P16
|
P17
|
|
Punkt bestehen aus Rot Grün Blau Komponenten
Pxy = Rxy + Gxy + Bxy = 3Bytes je Punkt
¼ Ausschnitt aus der
ersten 8 * 8 RGB- Matrix |
nach der Umwandlung entsteht das YUV- Bild
|
Y00
|
Y01
|
Y02
|
Y03
|
Y04
|
Y05
|
Y06
|
Y07
|
|
Y10
|
Y11
|
Y12
|
Y13
|
Y14
|
Y15
|
Y16
|
Y17
|
|
¼- Ausschnitt aus der Y- Matrix = 1Bye je Punkt(Y) |
|
|
Farbwert der Blaukomponenten (1/16- Ausschnitt der U- Matrix) 1Byte
je 4Punkte |
|
|
Farbwert der Rotkomponenten (1/16- Ausschnitt der V- Matrix) 1Byte
je 4Punkte |
2.1.2 Umwandlungformel von RGB —> YUV
| Y := 0.299 * R + 0.587 * G + 0.114
* B |
maxY= +255.000 |
minY= 0.000 |
| U := B-Y |
maxU= +225.930 |
minU= -225.930 |
| V := R-Y |
maxV= +178.755 |
minV= -178.755 |
U und V liegen im Integerbereich. Daraus folgt eine Skalierung der Größen
in den Shortint- Bereich. Da Shortint im Bereich -128 bis 127 liegt, folgt
eine Sklaierung mit dem kleinsten Skaler 127/???, da 128/??? aus dem shortint
Maximum führen würde. So wird dann U mit 127/225.93 scaliert
und V wird logischerweise mit 127/178.755 skaliert. Im Min- Bereich geht
nach der Skalierung der Min-Wert bis minimal -127. Man verschenkt somit
einen Wert,deshalb könnte man mit ein wenig Aufwand diesen Wert
retten, aber ich glaube, das lohnt sich nicht – da ich so schon gegen das
Zeitproblem ankämpfe. Die FPU wurde bei der Procedure auf die Strafbank
gesetzt, da die Gleitkomma- Arithmetik wie immer zu langsam ist. Die Brüche
z.B. 0.299 100/299 wurden auf Brüche mit 2^n im Nenner umgestellt,
da mit der CPU das leichter zu rechnen ist. Mit allen Mühen und Statistischen
Messungen, d.h ich habe die FPU-Werte und die Integer-Werte verglichen,
habe ich minimale Abweichungen mit 16bit Befehlen erreicht. 9999 Werte
von 10000 sind nach den Messungen zu folge richtig gerundet worden. Daraus
folgt die maximale Abweichung von rund ±0.75 und im Durchschnitt
bei rund ±0.2, das gilt für Y, U und V.Ich finde, daß
dies eine beachtliche Leistung für Integeroperationen ist.
2.2 Aus einer 8 * 8 Y-Matrix wird eine 8 * 8 DCC-Matrix
Formel: Cosinus Transformation = F(u,v) = c(u) * c(v) / 4*-(x=0-7)–(y=0-7)f(x,y)cos(pi*u(2x+1)/16)cos(pi*v(2x+1)/16)
für u,v=0,1,2,3,4,5,6,7;
c(?) = 1/
2, wenn
?=0; sonst c(?) =0;
Dies ist eine sehr umständliche Formel und erfordert eine Menge
Berechnungszeit. Es kann aus der Formel durch genaues Hinsehen (mathematische
Ironie "... und wie man leicht sieht ...") eine Matrizenmultiplikation
hergeleitet werden, die das Ganze beschleunigt und übersichtlich macht.
Wie folgt: F = DCT * Y * DCT ' (DCT '
ist die transponierte DCT, d.h. DCT=(DCT')';
DCT ist eine Koeffizienten- Matrix; eine Matrize mit vorberechneten Cosinuswerten).
Die Punkte der 8 * 8 Y-Matrix werden durch eine "nur" zweifache Matrizenmultiplikation
berechnet. Es werden dazu 2 Koeffizientenmatrizen erstellt, die wie folgt
berechnet werden (allgemeine Formel für N * N-Matrix).
DCT i,j = 1/
N;
wenn i (die Zeile) =0, sonst
DCT i,j = 1/
N*
cos[(2j+1)* i * pi / 2N], wenn i>0;
in unserem Fall ist N=8, dh: i, j laufen von 0..7
Dies ist ein Ausschnitt der DCT
| DCT = |
|
.
|
— |
|
|
—
|
. |
|
|
|
+0.3535 |
+0.3535 |
..... |
+0.3535 |
| |
|
|
|
+0.4904 |
+0.4157 |
|
-0.4904 |
| |
|
|
|
:
|
:
|
:
|
:
|
| |
|
|
|
+0.0975 |
-0.2777 |
..... |
-0.0975 |
| |
|
'
|
— |
|
|
—
|
´ |
|
Die Multiplikationen der Matrix habe ich in einer Assemblerlösung
vollzogen, da eine FPU-Lösung zu langsam wäre..
Pascal- Programm mit FPU -Lösung
var d:array[0..7,0..7] of real; --- Die DCT – Matrix ---
t:array[0..7,0..7] of real; --- Die DCT'-
Matrix ---
Y:array[0..7,0..7] of byte; --- Die Y
– Matrix ---
e:array[0..7,0..7] of real; --- ein zwischen
Ergebnis
f:array[0..7,0..7] of real; --- Das Endergebnis
1s,lz,tm:integer;
--- Ein paar Laufvariablen
begin
for ls:=0 to 7 do d[0][ls]:=1/sqrt(8);
--- 0. Zeile der DCT
for 1z:=1 to 7 do for 1s:=0 to 7 do
--- 1-7. Zeile der DCT
d[lz][ls]:=sgrt(2/8)*cos((2*ls+1)*lz*pi/(2*8));
--- Die Formel
for 1z:=0 to 7 do for ls:=0 to 7 do
--- Die Transponierte
t[lz][ls]:=d[ls][lz];
--- Die DCT'
for 1z:=0 to 7 do
--- << Y * DCT' >>
for 1s:=0 to 7 do
--- ! Skale Y-Matrix
for tm:=0 to 7 do
--- !! Y-128
e[lz][ls]:=e[lz][ls]+(i[lz][tm]-128)*t[tm][ls
];--– rechne
for 1z:=0 to 7 do
for 1s:=0 to 7 do
for tm:=0 to 7 do
f[lz][ls]:=f[lz][ls]+d[lz][trn]*e[tm][ls];
end.
In meinem Assemblerprogramm wird mit Integerarithmetik die FPU emuliert.
Die Realzahlen z.B. 1/
8
= 0.35355 wurde mit Vielfachen von 2 multipliziet, so z.Bsp. mit 16384,
dh. 1/
8 —> 5792.
Bei einer zweifachen Matrixmultiplikation habe ich eine maximale Abweichung
von ±0.75 erreicht und mit einer 92%-igen Sicherheit sind die Werte
im richtigen Bereich gerundet. Nach der Quantisierung werden 100tige Ergebnisse
erreicht.
Der 3. und 4. Schritt Quantisierung
& ZigZag Scanning der DCC Matrix
Aus der 8 * 8 F- Matrix wird eine Quantisierte 8 * 8 F- Matrix. Jedes Element
wird mit einem festen Faktor (hier die SAR- Matrizen), der über die
Qualität entscheidet, dividiert. Danach wir die quantisierte F- Matrix
in einem Zig-Zag-Scaning gespeichert. Es sind logischerweise 64 Elemente
in der F-Matrix, die in ein einfaches Feld gespeichert werden. D.h. aus
8 * 8 M —> 64iger Vektor die Elemente des ZigZag-Scan-Vektors
werden wie folgt bestimmt. Nach dern unten folgendem Bild. So wäre
z.B. V[ 0] := M[0][0];
V[ 2] := M[1][0];
V[23] := M[4][2];
V[64] := M[7][7];
Lage Vektorelemente in 8 * 8 Matrix
| |
xO x1 x2 x3 x4 x5 x6 x7 |
0x
1x
2x
3x
4x
5x
6x
7x |
00 01 05 06 14 15 27 28
02 04 07 13 16 26 29 42
03 08 12 17 25 30 41 43
09 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
|
|
==> |
64'iger Vektor mit Elementen aus 8 * 8 Matrix
|
|
x0
|
x1
|
x2
|
x3
|
x4
|
x5
|
x6
|
x7
|
x8
|
x9
|
|
0x
|
OO
|
01
|
10
|
20
|
11
|
02
|
03
|
12
|
21
|
30
|
|
1x
|
40
|
31
|
22
|
13
|
04
|
05
|
14
|
23
|
32
|
41
|
|
2x
|
50
|
60
|
51
|
42
|
33
|
24
|
15
|
06
|
07
|
16
|
|
3x
|
25
|
34
|
43
|
52
|
61
|
70
|
71
|
62
|
53
|
44
|
|
4x
|
35
|
26
|
17
|
27
|
36
|
45
|
54
|
63
|
72
|
73
|
|
5x
|
64
|
55
|
46
|
37
|
47
|
56
|
65
|
74
|
75
|
66
|
|
6x
|
57
|
67
|
76
|
77
|
|
|
|
|
|
|
|
In den folgenden Tabellen sind die Quantisierungstabellen aufgelistet,
die von meinem Programm verwendet werden. Jede Division wird mit SAR (Assembler
Shift Arithmetik Right) ausgedrückt. Das SAR-Effektiv
ist deshalb aufgeführt, da mit der SAR-Bewegung in meinem Programm
die Werte gleichzeitig normiert werden. Das heist, die Brüche (aus
der FPU-Emulation)
bestehen aus Zahl/2^5 (Zahl/32'igstel). Mit diesem SAR werden also
2 Fliegen mit einer Klappe geschlagen, Quantisierung plus Normierung. SAR
wird deswegen genommen, damit die negativen Zahlen erhalten bleiben.
1. Quantisierungstabelle 1-2% sehr
gute Qualität
|
Devisor Matrix
|
SAR-Matrix
|
SAR-Effektiv
|
|
01 02 02 02 04 08 08 08
02 02 02 08 08 08 08 08
02 04 04 08 08 08 08 08
02 04 08 08 08 08 08 08
04 08 08 08 08 08 08 08
08 08 08 08 08 08 08 08
08 08 08 08 08 08 08 08
08 08 08 08 08 08 08 08
|
0 1 1 1 2 3 3 3
1 1 1 3 3 3 3 3
1 2 2 3 3 3 3 3
1 2 3 3 3 3 3 3
2 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3
|
5 6 6 6 7 8 8 8
6 6 6 8 8 8 8 8
6 7 7 8 8 8 8 8
6 7 8 8 8 8 8 8
7 8 8 8 8 8 8 8
8 8 8 8 8 8 8 8
8 8 8 8 8 8 8 8
8 8 8 8 8 8 8 8
|
2. Quantisierungstabelle 15% gute Qualität
|
Devisor Matrix
|
SAR-Matrix
|
SAR-Effektiv
|
|
01 02 02 04 08 16 16 16
02 04 04 16 16 16 16 16
04 08 08 16 16 16 16 16
04 08 16 16 16 16 16 16
08 16 16 16 16 16 16 16
16 16 16 16 16 16 16 16
16 16 16 16 16 16 16 16
16 16 16 16 16 16 16 16
|
0 1 1 2 3 4 4 4
1 2 2 4 4 4 4 4
2 3 3 4 4 4 4 4
2 3 4 4 4 4 4 4
3 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
|
5 6 6 7 8 9 9 9
6 7 7 9 9 9 9 9
7 8 8 9 9 9 9 9
7 8 9 9 9 9 9 9
8 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9
|
3. Quantisierungstabelle 40% ausreichende
Qualität
|
Devisor Matrix
|
SAR-Matrix
|
SAR-Effektiv
|
|
01 08 08 08 16 16 32 32
08 08 08 32 32 32 32 32
08 16 16 32 32 32 32 32
08 16 32 32 32 32 32 32
16 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32
|
0 3 3 3 4 4 5 5
3 3 3 5 5 5 5 5
3 4 4 5 5 5 5 5
3 4 5 5 5 5 5 5
4 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5
|
5 8 8 8 9 9 A A
8 8 A A A A A A
8 9 9 A A A A A
8 9 A A A A A A
9 A A A A A A A
A A A A A A A A
A A A A A A A A
A A A A A A A A
|
4. Quantisierungstabelle 60% schlechte
Qualität
|
Devisor Matrix
|
SAR-Matrix
|
SAR-Effektiv
|
|
01 16 16 16 32 32 64 64
16 16 16 64 64 64 64 64
16 32 32 64 64 64 64 64
16 32 64 64 64 64 64 64
32 64 64 64 64 64 64 64
64 64 64 64 64 64 64 64
64 64 64 64 64 64 64 64
64 64 64 64 64 64 64 64
|
0 4 4 4 5 5 6 6
4 4 4 6 6 6 6 6
4 4 4 6 6 6 6 6
4 5 6 6 6 6 6 6
5 6 6 6 6 6 6 6
6 6 6 6 6 6 6 6
6 6 6 6 6 6 6 6
6 6 6 6 6 6 6 6
|
5 9 9 9 A A B B
9 9 9 B B B B B
9 A A B B B B B
9 A B B B B B B
A B B B B B B B
B B B B B B B B
B B B B B B B B
B B B B B B B B
|
2.5 5. Schritt Eliminierung bzw. Zusammenfassung
der Nullen in 6 Vektoren
Nach der Umsetzung der vier 8 * 8 RGB Matrizen sind nun 6 Quantisierte
Vektoren entstanden. Davon sind die ersten 4 Vektoren Y-Informationen,
der 5. Vektor ist die U-Information und der 6. Vektor ist die V-Information.
So ist nun ein 64 * 6-Integervektor entstanden. Viele der Werte in dem
Vektor sind NULL (Teilweise weit über 90%.). Durch die DCT wurden
aus den Bytewerten Integerwerte. Durch langes Probieren (Zufallszahlen
in den Matrizen) habe ich den Wertebereich abgesteckt. Ich fand keinen
Wert der die ±1000 überschritt. Also habe ich den Wertebereich
von 1023 bis -1023 festgelegt. Falls es Zahlen geben sollte, die diesen
Wertebereich übertreffen, so werden sie mit dem Maximalwert 1023 bzw.
-1023 festgelegt. Wie man sieht ist der Integerbereich nicht voll ausgeschöpft.
Es werden 5 bits der 16-bit Zahl gar nicht genutzt. Da
das Signed- bit genau an der Stelle "F" des words steht, skaliere ich
die Zahl. Ich addiere 1024 dazu. Somit liegt die Zahl im Wertebereich von
0..2047. Nun sind die oberen 5bits frei. Dann werden noch alle Nullen gezählt.
Hier stehen mir 5 bits zur Verfügung, dh maximal 31 Nullen können
mit gespeichert werden. Werden mehr als 31 Nullen gezählt, so wird
der Null-Zähler auf 31 gelassen; die nächste Wertzahl wird auf
0 gesetzt (Aufgepasst! Nach der Skalierung entspricht eine Null der 1024),
und erneut werden die Nullen gezählt.
Aufteilung der 16bit Zahl
Anzahl Null .-------
ZAHL ------.
F E D C B A
9 8 7 6 5 4 3 2 1 0
n n n n n
D D D D D D D D D D D
Bsp. 7 Vektorzahlen werden zusammengefaßt zu 2 Null-codierten
Zahlen
|
Vektorwert
|
Gespeicherter Wert
|
Bitfolge Codiert
|
|
12
0
|
12 + 1 x Null
|
1xNull
12
0000100000001100
FEDCBA9876543210
|
|
5
0
0
0
|
5 + 3 x Null
|
1xNull
12
0001100000000101
FEDCBA9876543210
|
6 ganze Vektoren (6 * 64 Werte) werden Null-Codiert. Jeder nullcodierte
Block wird in einern Puffer abgelegt. Sollte die Puffergröße
beim nächsten Eintrag 4097 Werte übersteigen oder das Bild ist
zu Ende, so wird der Block Huffmancodiert und auf Platte gespeichert.
6.Schritt Huffmann-Codierung von zusammengefaßten
Vektor-Blöcken
Dieses Thema ist am dünnsten ausgefallen, hier kann noch viel rausgehohlt
werden. Hier existiert als Ausgang ein Integerblock in der Größe
von etwa 4000 Integerwerten. Diese Integerwerte werden aufgeteilt in High
und Low- Bytes, da es Unterschiede in der Häufigkeitsverteilung gibt.
Ich habe verschiedene "nullgepackte Bilder" gespeichert. Danach habe ich
von einem Programm die auftretenden Bytes für High und Low- Bytes
zählen lassen. Dann habe ich mehrere Tabelle per Hand erstellt, die
die verschiedenen Bit-Kombinationen für jedes Byte festlegen. Für
häufig auftretende Zeichen werden kurze (2-3bit) Bitkombinationen
und für selten auftretende Zeichen werden lange (bis zu 15bit) Bitkombinationen
verwandt. Vorgehen des Algorithmuses.
-
1. Entnahme des HighBytes
-
2. Suchen in HighByte- Tabelle der Bitsanzahl für diese Zeichen
-
3. Suchen des BitCodes für das HighByte
-
4. Einfügen des BitCodes in den BitStream
-
-
5. Entnahme des LowBytes
-
6. Suchen in LowByte- Tabelle der Bitsanzahl für diese Zeichen
-
7. Suchen des BitCodes für das LowByte
-
8. Einfügen des BitCodes in den BitStream
-
9. Gehe zu 1.
Ein sehr einfacher und schneller Algorithmus, spart aber relativ
wenig ein (etwa 50%).
Praktikum