Willkommen im cgboard - classic games Forum! Deine gemütliche Retro Gaming Community. Besuche uns auch im Discord Chat.

[Grafik] Bräuchte mal eine kleine Hilfe für ein Dekompression Algorithmus für ILBM Bild Dateien
#1
0
Hallo liebe Entwickler aus dem Forum. ^^

Ich habe ein kleines Umsetzungsproblem zwecks eines simplen RLE Decompressions Algorithmus.

Es geht um ILBM Bild Dateien von Electronic Arts.

Ich kann mit meinem aktuellen Programm soweit alles laden, Header, Palette, etc. pp.
Nun bin ich aber schon eine Weile daran diese blöde Lauflängenkodierung zu decodieren, damit ich das jeweilige Bild wieder habe und zeichnen lassen kann.

Im Internet gibt es zwars ein Pseudo Code wie der Prozess auszusehen hat, aber ich kann das irgendwie nicht so recht in meiner Programmiersprache umsetzen, weil ich irgendwo ein Gedankenfehler habe.

Die Palette ist nicht das Problem und wird einwandfrei erkannt.

Es geht nämlich um ein 256 Farb Bild.

Hier mal der Pseudo Code auf Wikipedia: https://en.wikipedia.org/wiki/ILBM#Compression

Hier mein QB64 (http://www.qb64.net/) Code dafür:
Code:
'##############################################################
      '# Problem with Decompressing
      '# https://en.wikipedia.org/wiki/ILBM#Compression
      '#
      '# Content TINY and Body have the same Compression
      '##############################################################

      'Only for Compressed DATA
      i = 0
      DO
        picData = sRO(of, 1)
        IF picData > 128 THEN ' Decompressing value
          decomp = 257 - picData
          picData = sRO(of, 1)
          FOR r = 0 TO decomp - 1
            thumbnail(i + r) = picData
          NEXT r
          i = i + decomp - 1
        ELSE
          IF picData < 128 THEN ' Non-Decompressing value
            decomp = picData
            r = 0
            DO
              picData = sRO(of, 1)
              IF picData = 128 THEN EXIT DO
              thumbnail(i + r) = picData
              r = r + 1
            LOOP WHILE r = decomp - 1
            i = i + decomp
          END IF
        END IF
        i = i + 1
        PRINT i 'Current position
      LOOP UNTIL i >= (ILBM.TINYwidth * ILBM.TINYheight)

      '#####################################################
      '#####################################################

Zum Zeichen soll dann später folgendes dienen:
Code:
'#-------------------------
      '# Testing Picture Output
      '#-------------------------

      'Set screen mode VGA 320x200 by 256 color for Graphic
      '                               or 40x25 for Textmode
      SCREEN 13
      PALETTE USING pal() ' useing the loading palette from CMAP

      'draw the image
      FOR y = 0 TO ILBM.TINYheight - 1
        FOR x = 0 TO ILBM.TINYwidth - 1
          PSET (x, y), pal(thumbnail(y * ILBM.TINYwidth + x))
        NEXT x
      NEXT y

Das Bild ist in Indexen gespeichert. Jeder Index entspricht einen Wert aus der Farbpalette. 0 - 255.
Mit sRO lade ich jeweils ein Byte an der jeweiligen Offset Adresse die in der Variable 'of' enthalten ist. of wird beim nutzen von sRO immer um 1 erhöht, sodass ich dann den nächsten Offset habe.
i und r sind Zählvariablen. Wobei i die Größe des Bildes in Byte ergeben soll. Die Schleife endet sobald i > oder = die Höhe * Breite des Bildes hat. Sprich die Gesamt Bytes.

thumbnail ist ein Array das als Speicher der dekomprimierten Indexwerte dienen soll. Sprich das Bild wird in diesem Array festgehalten dann.

Ich habe hier auch mal eine RAW Datei hochgeladen, wo ihr das dann selbst probieren könnt.
Enthält die Palette, die Auflösung und das Bild selbst. Ihr braucht also nicht den ganzen Quark zwecks ILBM jetzt auslesen. Reicht wenn ich das dann habe xD.

http://www.mediafire.com/file/hqk2uakt1b9bbhu/test.pbm

Die Testdatei ist folgendermaßen gegliedert:
Offset 0 - Palette -> Größe 768 Bytes (300h)
-> 768 / 3 = 256 Farben. Jeweils 1 Byte für Rot, Grün und Blau.

Offset 300 - Auflösung -> Größe 4 Byte (4h)
-> 2 Byte Breite + 2 Byte Höhe. Beides als BigEndian gespeichert

Offset 304 - Bild Informationen (Komprimiert)
-> Siehe oben für die Problemlösungssuche.

Das Testbild müsste dann im Endeffekt so aussehen:
[Bild: 7f8mrz94.png]

Wäre Geil wenn mir das einer irgendwie beibiegen kann. Smile
Zitieren
#2
0
Probier mal hiermit:

Code:
i = 0
      DO
        picData = sRO(of, 1)
        IF picData > 128 THEN ' Decompressing value
          decomp = 257 - picData
          picData = sRO(of, 1)
          FOR r = 0 TO decomp - 1
            thumbnail(i + r) = picData
          NEXT r
          i = i + decomp
        ELSE
          IF picData < 128 THEN ' Non-Decompressing value
            decomp = picData + 1
            r = 0
            DO
              picData = sRO(of, 1)
              thumbnail(i + r) = picData
              r = r + 1
            LOOP WHILE r < decomp
            i = i + decomp
          END IF
        END IF
        PRINT i 'Current position
      LOOP UNTIL i >= (ILBM.TINYwidth * ILBM.TINYheight)

Hier (http://fileformats.archiveteam.org/wiki/PackBits) steht, dass 128 als Code-Byte ignoriert werden soll, so lange nicht die vorher angekündigte Bildgröße ausgelesen wurde.
Außerdem habe ich den Loop etwas vereinfacht.
Zitieren
#3
0
Danke tomwatayan

In Zeile 17 gibt es nach deinem Muster für das Array ein 'Out of Range'.

Sprich Zähler i geht über den Wert hinaus den die Auflösung von Breite und Höhe ergibt.
Folglich geht es über die dimensionierte Feldgröße hinaus.

Das Bild wird, wenn ich den Fehler ignoriere, komplett falsch dargestellt.
Irgendwas scheint vermutlich noch zuviel zu sein.

Oder der Ganze Ablauf ist noch verkehrt wie ich es geschrieben habe. Mir gehen echt die Ideen aus. ^^

Ich denke mal das der Dekomprimierungsprozess in der ersten Hälfte der If Abfrage hinhaut. Aber der Non-Decompress Teil, da wird noch der Wurm begraben sein.


Edit
====================
Ich habe mal für das Testfile was ich im Startpost gepostet habe für euch mal ein Standalone Programm verfasst. Einzig und allein der Dekompressions Algorithmus geht noch nicht. ^^

Kann mit QB64 getestet werden. http://www.qb64.net/
Code:
CONST ILBMfile = "test.pbm"

DIM of AS _UNSIGNED LONG

'Array for Palette and Image
DIM pal(255) AS LONG
REDIM image(0) AS _UNSIGNED _BYTE

'Resolution
DIM w AS _UNSIGNED INTEGER
DIM h AS _UNSIGNED INTEGER

'Counter
DIM i AS _UNSIGNED INTEGER
DIM r AS _UNSIGNED INTEGER

'Image temp Variables
DIM picData AS _UNSIGNED _BYTE ' 0-255
DIM decomp AS INTEGER
DIM x AS INTEGER, y AS INTEGER


'#==================================
'# Open the test file for ILBM Files
'# Only for Decompression Algorithmus
'#==================================

OPEN ILBMfile FOR BINARY ACCESS READ AS #1

'Reading Palette
FOR i = 0 TO 255
  RED = sRO(of, 1)
  GREEN = sRO(of, 1)
  BLUE = sRO(of, 1)
  '# Calculate the VGA Color for screen mode 13
  pal(i) = (BLUE \\ 4) * 65536 + (GREEN \\ 4) * 256 + RED \\ 4
NEXT i

'Reading Resolution
w = sRO(of, 2)
h = sRO(of, 2)

'Dimension of Image
REDIM image(w * h)

'##############################################################
'# Problem with Decompressing
'# https://en.wikipedia.org/wiki/ILBM#Compression
'#
'# Content TINY and Body have the same Compression
'##############################################################

'Only for Compressed DATA
i = 0
DO
  picData = sRO(of, 1)
  IF picData > 128 THEN ' Decompressing value
    decomp = 257 - picData
    picData = sRO(of, 1)
    FOR r = 0 TO decomp - 1
      image(i + r) = picData
    NEXT r
    i = i + decomp - 1
  ELSE
    IF picData < 128 THEN ' Non-Decompressing value
      decomp = picData + 1
      r = 0
      DO
        picData = sRO(of, 1)
        image(i + r) = picData
        r = r + 1
      LOOP WHILE r < decomp
      i = i + decomp
    END IF
  END IF
  PRINT i 'Current position
LOOP UNTIL i >= (w * h)

'#####################################################
'#####################################################

CLOSE #1 'Closing the Open File


'#-------------------------
'# Testing Picture Output
'#-------------------------

'Set screen mode VGA 320x200 by 256 color for Graphic
'                               or 40x25 for Textmode
SCREEN 13
PALETTE USING pal() ' useing the loading palette from CMAP

'draw the image
FOR y = 0 TO ILBM.TINYheight - 1
  FOR x = 0 TO ILBM.TINYwidth - 1
    PSET (x, y), pal(thumbnail(y * ILBM.TINYwidth + x))
  NEXT x
NEXT y



'#======================
'#      Functions
'#======================

'#----------------------
'# Signed Reading Offset
'#----------------------
FUNCTION sRO~& (offset AS _UNSIGNED LONG, offlength AS _UNSIGNED _BYTE)
  DIM value AS _UNSIGNED _BYTE
  DIM values AS _UNSIGNED LONG

  offset = offset + 1

  DO
    GET #1, offset, value
    values = values + value * 2 ^ ((offlength - 1) * 8)
    offlength = offlength - 1
    offset = offset + 1
  LOOP UNTIL offlength = 0

  offset = offset - 1

  sRO~& = values
END FUNCTION
Zitieren
#4
0
Ich habe dein Standalone-Programm entsprechend angepasst, dass es nicht in einer Endlosschleife festhängt und bin mit dem Ergebnis eigentlich ganz zufrieden. Da ist glaube ich nur noch die Farbpalette falsch:

[Bild: test_pbmzpso2.png]

Code:
CONST ILBMfile = "test.pbm"

DIM of AS _UNSIGNED LONG

'Array for Palette and Image
DIM pal(255) AS LONG
REDIM image(0) AS _UNSIGNED _BYTE

'Resolution
DIM w AS _UNSIGNED INTEGER
DIM h AS _UNSIGNED INTEGER

'Counter
DIM i AS _UNSIGNED INTEGER
DIM r AS _UNSIGNED INTEGER

'Image temp Variables
DIM picData AS _UNSIGNED _BYTE ' 0-255
DIM decomp AS INTEGER
DIM x AS INTEGER, y AS INTEGER


'#==================================
'# Open the test file for ILBM Files
'# Only for Decompression Algorithmus
'#==================================

OPEN ILBMfile FOR BINARY ACCESS READ AS #1

'Reading Palette
FOR i = 0 TO 255
    RED = sRO(of, 1)
    GREEN = sRO(of, 1)
    BLUE = sRO(of, 1)
    '# Calculate the VGA Color for screen mode 13
    pal(i) = (BLUE \\ 4) * 65536 + (GREEN \\ 4) * 256 + RED \\ 4
NEXT i

'Reading Resolution
w = sRO(of, 2)
h = sRO(of, 2)

'Dimension of Image
REDIM image(w * h)

'##############################################################
'# Problem with Decompressing
'# https://en.wikipedia.org/wiki/ILBM#Compression
'#
'# Content TINY and Body have the same Compression
'##############################################################

'Only for Compressed DATA


DIM outputIndex AS _UNSIGNED LONG
outputIndex = 0
DO
    picData = sRO(of, 1)
    IF picData > 128 THEN ' Decompressing value
        decomp = 257 - picData
        PRINT "Dec: picData: ", picData, "decomp: ", decomp
        picData = sRO(of, 1)
        FOR r = 0 TO decomp - 1
            image(outputIndex + r) = picData
        NEXT r
        outputIndex = outputIndex + decomp
    ELSE
        IF picData < 128 THEN ' Non-Decompressing value
            decomp = picData + 1
            PRINT "Ndec: picData: ", picData, "decomp: ", decomp
            r = 0
            DO
                picData = sRO(of, 1)
                image(outputIndex + r) = picData
                r = r + 1
            LOOP WHILE r < decomp
            outputIndex = outputIndex + decomp
        END IF
    END IF
    PRINT "Position: ", outputIndex, "Size: ", (w * h) 'Current position
LOOP UNTIL outputIndex >= (w * h)

'#####################################################
'#####################################################

CLOSE #1 'Closing the Open File

'#-------------------------
'# Testing Picture Output
'#-------------------------

'Set screen mode VGA 320x200 by 256 color for Graphic
'                               or 40x25 for Textmode
SCREEN 13
PALETTE USING pal() ' useing the loading palette from CMAP

'draw the image
FOR y = 0 TO h - 1
    FOR x = 0 TO w - 1
        PSET (x, y), pal(image(y * w + x))
    NEXT x
NEXT y



'#======================
'#      Functions
'#======================

'#----------------------
'# Signed Reading Offset
'#----------------------
FUNCTION sRO~& (offset AS _UNSIGNED LONG, offlength AS _UNSIGNED _BYTE)
DIM value AS _UNSIGNED _BYTE
DIM values AS _UNSIGNED LONG

offset = offset + 1

DO
    GET #1, offset, value
    values = values + value * 2 ^ ((offlength - 1) * 8)
    offlength = offlength - 1
    offset = offset + 1
LOOP UNTIL offlength = 0

offset = offset - 1

sRO~& = values
END FUNCTION
Zitieren
#5
0
Tausend Dank. ^^
Jetzt läuft das. Ich muss mir morgen erst mal den Code zu Gemüte führen den du da geschrieben hast.

Die Farben waren schon richtig, nur ich Blödmann habe statt den Palettenindex anzugeben, die Ganze Farbe an PSET übergeben. Das war Fail. Hab doch vorher schon die Palette geladen xD
Ich sollte mal ne Pause mit den Kram machen xD

Das hier sollte nun gehen:
Code:
CONST ILBMfile = "test.pbm"

DIM of AS _UNSIGNED LONG

'Array for Palette and Image
DIM pal(255) AS LONG
REDIM image(0) AS _UNSIGNED _BYTE

'Resolution
DIM w AS _UNSIGNED INTEGER
DIM h AS _UNSIGNED INTEGER

'Counter
DIM i AS _UNSIGNED INTEGER
DIM r AS _UNSIGNED INTEGER

'Image temp Variables
DIM picData AS _UNSIGNED _BYTE ' 0-255
DIM decomp AS _UNSIGNED INTEGER
DIM x AS INTEGER, y AS INTEGER


'#==================================
'# Open the test file for ILBM Files
'# Only for Decompression Algorithmus
'#==================================

OPEN ILBMfile FOR BINARY ACCESS READ AS #1

'Reading Palette
FOR i = 0 TO 255
  RED = sRO(of, 1)
  GREEN = sRO(of, 1)
  BLUE = sRO(of, 1)
  '# Calculate the VGA Color for screen mode 13
  pal(i) = (BLUE \\ 4) * 65536 + (GREEN \\ 4) * 256 + RED \\ 4
NEXT i

'Reading Resolution
w = sRO(of, 2)
h = sRO(of, 2)

'Dimension of Image
REDIM image(w * h)

'##############################################################
'# Problem with Decompressing
'# https://en.wikipedia.org/wiki/ILBM#Compression
'#
'# Content TINY and Body have the same Compression
'##############################################################

DIM outputIndex AS _UNSIGNED LONG
outputIndex = 0
DO
  picData = sRO(of, 1)
  IF picData > 128 THEN ' Decompressing value
    decomp = 257 - picData
    PRINT "Dec: picData: ", picData, "decomp: ", decomp
    picData = sRO(of, 1)
    FOR r = 0 TO decomp - 1
      image(outputIndex + r) = picData
    NEXT r
    outputIndex = outputIndex + decomp
  ELSE
    IF picData < 128 THEN ' Non-Decompressing value
      decomp = picData + 1
      PRINT "Ndec: picData: ", picData, "decomp: ", decomp
      r = 0
      DO
        picData = sRO(of, 1)
        image(outputIndex + r) = picData
        r = r + 1
      LOOP WHILE r < decomp
      outputIndex = outputIndex + decomp
    END IF
  END IF
  PRINT "Position: ", outputIndex, "Size: ", (w * h) 'Current position
LOOP UNTIL outputIndex >= (w * h)

'#####################################################
'#####################################################

CLOSE #1 'Closing the Open File


'#-------------------------
'# Testing Picture Output
'#-------------------------

'Set screen mode VGA 320x200 by 256 color for Graphic
'                               or 40x25 for Textmode
SCREEN 13
PALETTE USING pal() ' useing the loading palette from CMAP

'draw the image
FOR y = 0 TO h - 1
  FOR x = 0 TO w - 1
    PSET (x, y), image(y * w + x)
  NEXT x
NEXT y



'#======================
'#      Functions
'#======================

'#----------------------
'# Signed Reading Offset
'#----------------------
FUNCTION sRO~& (offset AS _UNSIGNED LONG, offlength AS _UNSIGNED _BYTE)
  DIM value AS _UNSIGNED _BYTE
  DIM values AS _UNSIGNED LONG

  offset = offset + 1

  DO
    GET #1, offset, value
    values = values + value * 2 ^ ((offlength - 1) * 8)
    offlength = offlength - 1
    offset = offset + 1
  LOOP UNTIL offlength = 0

  offset = offset - 1

  sRO~& = values
END FUNCTION


War ja dann schon fast dran wenn ich das richtig sehe. Vermutlich hat mich der Pseudo Code zu sehr verwurschtelt. xD

Aber wirklich nochmal Tausend Dank dafür.

Wenn das Endresultat von meinen richtigen Programm sich sehen lassen kann, werde ich es im Forum mal posten.
Die Testdatei hab ich mit dem Hexeditor stark vereinfacht.
An sich sind die Bilder zusätzlich noch in einer XLD Datei verkapselt und haben mehrere Tag-Abschnitte.

Aber das läuft alles schon soweit.

Nur bei diese verfackte RLE Kompression stand ich grad irgendwo auf dem Schlauch.
Zitieren
#6
0
Bitte, gern geschehen. Auf diese Weise habe ich auch gleich Qb64 kennengelernt. Von dem Projekt hatte ich vorher noch gar nichts gehört. Das ist schon cool, wenn man da die alten DOS-Bildmodi und wohl auch alten Q-Basic-Code nutzen kann, aber das Ergebnis unter Windows 7 nativ lauffähig ist. Smile

Ich glaube, wenn ich den Code jetzt noch einmal betrachte, war das Hauptproblem die Schleifenbedingung im zweiten Teil: LOOP WHILE r = decomp - 1 wird wohl fast immer nach einem Durchgang abbrechen, während LOOP WHILE r < decomp ein paar Runden mehr dreht. Und, aber ich denke das war eher ein Transkriptionsfehler für das Standalone-Programm: i ist als _UNSIGNED INTEGER (max. 65535) zu klein für die Bildgröße.
Zitieren
#7
0
OpenGL Programmierung ist auch möglich. ^^

Das tolle aber daran ist das man endlich auch weitere Datentypen zur Verfügung hat.

Wie z.B. hatte man im Original unter DOS ja bei Long nur den Werte Bereich von -2.147.483.648 bis 2.147.483.647.

Wollte man aber 0 bis 4294967295, so musste man schon Double nehmen.

Jetzt kann man aber in QB64 gleich ein Unsigned Datentyp deklarieren und kann so viel genauer und vor allem angenehmer arbeiten ^^

Was bei QB64 jedoch nicht übernommen werden kann sind alte Assembler Befehle aus älteren QB Programmen. Die müssen dann schon komplett neu auf die neue Umgebung ausgelegt werden.

Auch lassen sich mit QB64 nun auch Dynamic Link Libraries laden und nutzen. Wie z.B. den Common Dialog von Windows. So kann man in seinem QB Programm ganz leicht ein Laden und Speichern ermöglichen.

Habe damit schon einige Tools geschrieben ^^
Wie z.B. diesen Extractor LucasArt's MONSTER.SOU Extractor

Und ich sag mal... für so kleine Grafikspielereien oder kleine Tools ist das recht angenehm sogar. ^^
Zitieren
#8
0
Gerade fürs Plotten war Q-Basic ja früher schon predästiniert. Ich weiß noch, wie wir das früher z.B. verwendet haben, um für Kurvendiskussionen mal eben die entsprechende Kurve zu zeichnen, weil wir die Spezialtaschenrechner immer nur vor jeder Unterrichtsstunde ausgehändigt bekamen und sie hinterher wieder eingesammelt wurden. Aber das DOS-Original lässt sich ja heute nur so kompliziert über die DOSBox starten, deshalb bin ich gerade ganz erstaunt, dass es so eine angenehme Windows-Portierung gibt.
Zitieren


Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
  [Info] 18 Monate Linux Mint- Ein Erfahrungsbericht marka 9 455 13.04.2024, 20:08
Letzter Beitrag: Topper_Harley
  [Frage] Interesse für Gamelisten Tool? Pobeller 2 331 07.11.2023, 17:32
Letzter Beitrag: Pobeller
  [Suche] Mitstreiter für LSL1 VGA Übersetzung gesucht. STiGMaTa_ch 58 24.216 09.10.2023, 16:46
Letzter Beitrag: Mustrum
  SWF-Dateien abspielen? Atreyu 16 1.632 17.05.2023, 08:18
Letzter Beitrag: Juttar
  [Suche] Tips für GoodOldDay Manager Pobeller 13 1.228 06.04.2023, 17:58
Letzter Beitrag: Pobeller

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste