So, nun habe ich endlich etwas zum Zeigen.
Erste ZVID Version (meinetwegen beta alpha oder sonstwas) ist fertig !
Das sind ein paar Videos, von Spielen, und von ein paar FLI's zum Größenvergleich, ich kündigte ja an,
dass die Komprimierung effektiver sein würde als FLI.
Einfach ZVDEMO aufrufen und den Videonamen eingeben, oder als Kommandozeilenparameter, ohne Erweiterung.
Die Palette habe ich jeweils aus Prinzip extra gespeichert, weil das so in der letzendlichen Verwendung des Formats
auch so sein wird, denn es soll eigentlich gar kein Videoformat werden wie AVI oder soetwas, sondern vielmehr die
effiziente Speicherung von Grafiken ermöglichen, die man dann in einem Spiel etc. verwenden kann.
Die Demo macht am Anfang eine kurze Pause, damit sich Röhrenmonitore
auf den anderen Bildschirmmodus einschwingen können.
Hier der Link:
http://www.zatzen.net/zvdemo.zip (1,25 MB)
Hier mal der Größenvergleich FLI - ZVD:
SKELLY -- FLI: 151K ZVD: 61K
SMLSPIDR -- FLI: 228K ZVD: 132K
EARTH -- FLI: 192K ZVD: 139K
HIT_ANY -- FLI: 647K ZVD: 209K
TIGERCAT -- FLI: 99K ZVD: 53K
JABBER -- FLI: 46K ZVD: 37K
FLY -- FLI: 46K ZVD: 25K
MARILYN -- FLI: 37K ZVD: 19K
Je nach Ausgangsmaterial ist die ZVD Kompression auch deutlich effektiver als ZIP.
Darauf dann aber nochmal ZIP abgewendet, wird es nochmals eine ganze Ecke kleiner.
Im Moment sind die Viewer-Routinen noch langsam, aber das wird sich ändern.
Die Vorgehensweise des Formats ist:
- alles in 8x8 Blöcke zerlegen
- diese Blöcke jeweils so klein wie möglich speichern (nur so viel Bits wie nötig etc.)
- Redundante (d.h. mehrfach vorkommende) Blöcke gesondert abspeichern und
in den jeweiligen Bildern nur Verweise darauf speichern
- gleiche aufeinanderfolgende Blöcke RLE codieren.
- nicht für jeden bitreduziert-optimiert codierten Block die indizierten Farben speichern,
sondern die indizierten Daten für alle Blöcke in einer Gesamtpalette sammeln, diese
möglichst kompakt optimieren, und dann für jeden Block nur ein Offset in diese Daten
hinein speichern, je nach Offsetposition ein Byte oder ein Word.
Eine ZVID-Datei kann mehrere Frames enthalten (Viewer unterstützt derzeit ca. 8000), es gibt vier Bänke,
die redundante Blockdaten enthalten. Vier deshalb, falls die redundanten Blockdaten größer als 64K oder
gar 192K werden. Die Erfahrung wird aber zeigen ob das wirlich nötig ist, wenn nicht kann ich mir beim
Viewer eine Pointer-Ebene sparen, was auch eine kleine Geschwindigkeitssteigerung mit sich bringen würde.
Schliesslich noch die "Paletten"-Daten, sprich die Indizes für die verschiedenen Blöcke, bspw. wenn ein Block
mit 3 Bit gespeichert wird, braucht er noch je nachdem 5-8 Indizes welche Farben gemeint sind.
Verbesserungswürdig ist momentan vor allem der Viewer für den Real Mode, dort sind die Assembler-Routinen
noch nicht optimal, und es gibt statt Sprungtabelle für die Routinen derzeit noch IF-Abfragen.
Zudem, und das ist wohl das größte Manko, wird momentan, zum ersten sicheren Testen, noch doppelt und dreifach
Speicher herumgeschoben, heisst: Die Daten aus dem Blockdaten-Stream werden ersteinmal in einen Puffer für
die decodier-Routinen kopiert, dann in einen 8x8 Pixel-Puffer decodiert, und dieser dann erst in den Bildschirmpuffer
kopiert.
Bei der Demo kommt noch hinzu, dass ich eben noch einen Screenpuffer vorschalte, damit das Bild bei zu viel
Leistungsanforderung nicht schwabbelt sondern alles nur langsamer wird.
Umso interessanter wäre Feedback von euch, wie langsam oder schnell das jetzt schon auf diesem oder jenem System läuft,
und ob die Framerate (hier standard-Timer-mäßig 18.2 fps) erreicht wird.
Einige Videos sind aber gecaptured und auf 18.2 fps konvertiert obwohl sie in echt noch weniger Framerate hatten, daher
kann man das nicht immer so gut beurteilen.
Die Festplatte meines Pentiums ist leider gerade defekt, und der neue Rechner hat kein Diskettenlaufwerk um eine Boot Disk
zu machen. Okay, Boot CD-ROM wäre eine Optium.
Beim Converter bzw. Encoder sollte noch hinzugefügt werden, dass auch Spiegelungen der Blöcke als redundant erkannt
werden, das würde noch ein wenig die Blockdaten jedes Frames reduzieren und gleichzeitig die Datengröße der redundanten
Blöcke je nach Quellmaterial deutlich verkleinern.
Auch könnte man prüfen, ob ganze Frames mehrfach vorkommen, das wäre aber eher nur interessant für Videos und
weniger für Sprites.
Der Converter ist übrigens in Freepascal geschrieben, da es sehr hohe Speicherauslagen gibt (gerne mal 100MB im RAM bei
Videos), und dennoch ist er sehr langsam. Aber er funktioniert, und wenn es nur wenige tausend Blöcke sind geht das auch
innerhalb einer Sekunde. Man muss eben bedenken, dass wir bei einem Video mit sagen wir mal 1000 Frames eben eine
Million Blöcke haben!
Auch werde ich für zukünftige Versionen noch weitere Blocktypen einbauen. Derzeit gibt es nur Blöcke komplett einfarbig
oder transparent, Blockdaten 1-5 Bit, Block 1:1 nur kopieren (ab 33 versch. Farben / Block).
Denkbar sind Blocktypen, wenn z.B. ein Block hauptsächlich eine Farbe darstellt, und nur ein paar Pixel eine andere Farbe
haben, dann speichert man nur diese Hauptfarbe und die paar Pixel mit Koordinaten (d.h. Blockposition 0-63).
Zudem können auch geditherte Bereiche einer Grafik sehr effizient gespeichert werden, indem einfach nur die beiden
Farben vermerkt werden.
Ich habe hier für die Demo ersteinmmal nur Vollbild-Videos gemacht. Prinzipiell wird man das Format aber auch für Sprites
einsetzen können.
Ich gehe davon aus, dass mit gründlicher Optimierung des Viewers noch eine deutliche Geschwindigkeitsteigerung drin ist.
Trotzdem wird es natürlich nie so schnell sein wie ein einfacher Kopiervorgang.
Je nachdem was wichtiger ist, Geschwindigkeit oder Speicherplatz, kann man abwägen, ob es Sinn macht, das Format zu
verwenden.
Natürlich kann man auch Mischen, bspw. Hintergrundgrafiken nur schnell kopieren und eher kleine Sprites, aber mit vielen
Bewegungsphasen, mit ZVID einbinden. Die Handhabung der Unit ist sehr simpel, zuerst initialisieren, wie viele "slots" ein-
gerichtet werden sollen, d.h. wie viele .ZVD Dateien man laden will, auch übergibt man den Pointer des Videopuffers und die
X-Y Dimensionen von diesem. Zum Laden einer .ZVD gibt es eine Routine, ganz einfach nur Dateiname und "slot"-Nummer
angeben. Dann kann mittels einer Procedure aus einem beliebigen slot ein beliebiger Frame an beliebiger X-Y Position
dargestellt werden.
Auch wenn das Format im Prinzip langsamer ist als simple Sprite-Routinen, kann es sich unter Umständen die Waage halten,
aus zwei Gründen, in Zusammenhang mit Transparenz:
- Für Blöcke, die effektiv keine transparente Farbe enthalten,
findet keine pixelweise Transparenzprüfung statt.
- Blöcke, die komplett transparent sind, werden gar nicht erst
Pixel für Pixel durchgeprüft sondern es wird lediglich einfach
die Zieladresse entsprechend erhöht um den Bereich zu überspringen.
Die Bit-decodier-Routinen sind momentan noch ziemlich langsam, da ich sie ersteinmal generell gehalten habe. So werden
bei 1 Bit Codierung insgesamt 128 Byte gelesen, plus 64x ein Byte aus der Palette, die Bitposition gezählt u.a. Wenn ich das
konkretisiere und die Schleifen "entrolle", dann kann ich da viel effizienter rangehen, es genügt dann bei 1 Bit, alle 8 Pixel
ein Byte zu lesen, um daraus den Paletten-Index zu bestimmen - und eine 2-Farben-Palette kann bequem in Registern
gehalten werden, so dass das decodieren einer 1-Bit-Grafik sogar schneller gehen könnte als das kopieren einer 8-Bit-Grafik
- wenn Registerarbeit deutlich schneller ist als Speicher-Lesen.
Bei Interesse kann ich gerne noch Details über das Format erklären.
Es ist vielleicht eine gute Sache für Leute, die nicht gerne
viele gleiche Bytes aneinandergereiht mögen.