Seite 1 von 1
Wie indiziertes tga in Unkomprimiertes umwandeln?
Verfasst: 11.10.2009 15:58
von Syntacks_Error
Schreibe ein Programm, das tga-Dateien anzeigt und bearbeitet.
Die Dateien liegen im farb-indizierten Format (8 Bit) mit einer Farbpalette vor. Leider kann das tga_Plugin das nicht lesen. Also muß ich die in ein unkomprimiertes RGB Format (24 Bit, kein Alpha-Kanal) umwandeln. Ich weiß nur nicht wie. Mit den Palettenangaben in den Dateien kann ich nichts anfangen:
Code: Alles auswählen
file = readfile(#PB_Any,"Name der indizierten tga einfuegen")
FileSeek(file,1)
b = readcharacter(file)
Debug "Palette vorhanden: " + Str(b)
b = readcharacter(file)
Debug "Bildtyp: " + Str(b)
b = readword(file)
Debug "Palettenbegin: " + Str(b)
b = readword(file)
Debug "Farbanzahl: " + Str(b)
b = readcharacter(file)
Debug "Groeße Paletteneintrag (Was sagt das?): " + Str(b)
FileSeek(file,16)
b = readcharacter(file)
Debug "Groeße Bildpunkt/Bit: " + Str(b)
Das Format ist hier beschrieben:
http://de.wikipedia.org/wiki/Targa_Image_File
Tga ist wohl ein aussterbenden Format, Gimp kann es noch.
Kann mir irgend jemand helfen?
Hilfsweise: Ich vermute, daß da ein 24 Bit-Farbwert (je 8 Bit für Rot, Grün und Blau) auf 8 Bit herunterskaliert und gespeichert wird.Die Art der Skalierung ist dann in einem 24 Bit Palettenwert gespeichert? Oder kann man alleine aus den 8 Bit wieder halbwegs vernünftige Werte für Rot, Grün und Blau herauspfriemeln? Wie lese ich ein Byte bitweise?
Re: Wie indiziertes tga in Unkomprimiertes umwandeln?
Verfasst: 11.10.2009 16:27
von Marvin
Ich nehme an, dass in der Palette normale RGB-Daten (bzw. in diesem Falle in der Reihenfolge BGR oder mit optionalem Alphakanal, dann BGRA) stehen. Das eine Byte in den Bilddaten gibt dann den Index in dieser Tabelle an.
Hat man zum Beispiel die folgende Palette (BGR):
Dann bedeuten die folgenden Bilddaten die entsprechenden Farben (ungefähr):
$00 $03
$02 $01
Denn die Palette sähe aufgeschlüsselt so aus:
- Index 0: $00 $FF $FF = RGB($FF, $FF, $00)
- Index 1: $00 $40 $FF = RGB($FF, $40, $00)
- Index 2: $FF $40 $00 = RGB($00, $40, $FF)
- Index 3: $00 $00 $00 = RGB($00, $00, $00)
Ich habe mich nicht eingehend mit diesem Format beschäftigt, aber so könnte ich mir das zumindest vorstellen.

Re: Wie indiziertes tga in Unkomprimiertes umwandeln?
Verfasst: 11.10.2009 16:29
von Kaeru Gaman
"indizierte" Codierung bedeutet, dass das Bild eine Palette enthält, die über einen Index angesprochen wird.
Im Header steht also eine Palette, in der 256 Farbwerte vermerkt sind,
und in den Bilddaten selber steht dann für jedes Pixel ein Index 0-255, welche Paletten-Farbe das Pixel hat.
das ist aus der Formatbeschreibung im wiki eigentlich gut ersichtlich.
Re: Wie indiziertes tga in Unkomprimiertes umwandeln?
Verfasst: 11.10.2009 22:05
von Syntacks_Error
Aha. Vielen Dank, jetzt habe ich zumindest eine Vorstellung, wie es funktionieren könnte. Ich tüftle dann also mal ein bißchen weiter ...
Re: Wie indiziertes tga in Unkomprimiertes umwandeln?
Verfasst: 12.10.2009 20:25
von Syntacks_Error
Hurra, ich habe es geschafft:
Code: Alles auswählen
file = readfile(#PB_Any,"geindexte Farb-tga-Datei.tga")
header = 18 ; 18 Bytes Header
Dim header(header)
For x = 1 To 18
header(x) = readcharacter(file)
Next
Debug "Palette 1/0: " + Str(header(2)) ; Header(2) 1/0 => Palette ja/nein
Debug "Indiziert 1/0" + Str(header(3)) ; Wenn Header(3) = 1, indiziert
Debug "Bits/Farbe/Palette " + Str(header(8)); bei mir immer 24
Debug "Index Bit: " + Str(index_bit)
;Palettenbegin (Byte4/5) = immer 0, daher unbearbeitet
;--- doof
FileSeek(file,5)
farben = readword(file) ; Header(6) und (7) sind als Bytes da, aber wie macht man daraus ein word?
FileSeek(file,18); Ende des Headers
;----/doof
Debug "Farben: " + Str(farben)
For x = 1 To header(1) ; Falls BildID im Original, Anzahl Bytes weiternudeln
readcharacter(file)
Next
;Header auf nicht indiziert umstellen
header(1) = 0 ; keine BildID
header(2) = 0 ; keine Palette
header(3) = 2 ; 2 = 24 Bit unkomprimiert
header(6) = 0; 1. byte Farbanzahl, wenn nicht indiziert = 0
header(7) = 0; 2. byte Farbanzahl, wenn nicht indiziert = 0
header(8) = 0; Keine Palette, also Paletten Bits/Farbe = 0
header(17) = 24; Neue Bits/Farbe
; Rest kann bleiben
Structure index
Index_nr.i
rot.b
gruen.b
blau.b
EndStructure
Dim palette.index(Farben)
For x = 0 To farben ; Palettendaten lesen; bei mir immer 3*1 Byte
palette(x)\rot = readcharacter(file)
palette(x)\gruen = readcharacter(file)
palette(x)\blau = readcharacter(file)
Next
test_file = CreateFile(#PB_Any,"nicht_indiziert.tga")
For x = 1 To 18
WriteCharacter(test_file,header(x)) ; neuen Header schreiben
Next
While Not Eof(file)
Index_nr = readcharacter(file) ; Bilddaten => Indexnr der Farbpalette
WriteCharacter(test_file,palette(index_nr)\rot)
WriteCharacter(test_file,palette(index_nr)\gruen)
WriteCharacter(test_file,palette(index_nr)\blau)
Wend
CloseFile(file)
CloseFile(test_file)
Dazu aber noch zwei Fragen:
1) Anfangs habe ich den Header als Bytes(x). Bytes 6 u. 7 geben als Word die Palettenfarbzahl. Wie mache ich aus zwei Bytes ein Word, damit ich das Word nicht nochmal lesen muß? (Fileseek(file,5)/Readword)
2) Schöner wäre es, alles im Speicher abzuwickeln, denn das neue Bild muß ich ja wieder einlesen. Wie bekomme ich das Originalbild in den Speicher, lese es aus und pfriemel das nicht indizierte Bild in den Speicher? (Peek und Poke kann ich im Prinzip, viel mehr aber auch nicht). Außerdem verwende ich das Imagegadget zum Anzeigen des Bildes. Wie greife ich für dafür das neue Bild im Speicher ab?
Re: Wie indiziertes tga in Unkomprimiertes umwandeln?
Verfasst: 13.10.2009 17:50
von Marvin
Allgemein: Ich würde statt ReadCharacter() lieber ReadByte() nehmen. Denn ein Character ist nicht garantiert ein Byte.
1)
2) An sich forderst du erstmal einen genügend großen Speicherbereich z. B. mit *mem = AllocateMemory(...) an. Dann ersetzt du dein WriteCharacter(test_file, Wert) (bzw. WriteByte(test_file, Wert)) einfach mit PokeB(*mem, Wert) und *mem + 1 (um ein Byte weiter zu gehen). Dann solltest du das Bild direkt mit CatchImage() von der ursprünglichen Speicherstelle laden können.
Beispiel:
Code: Alles auswählen
*basemem = AllocateMemory(18 + (Lof(file) - Loc(file)) * 3)
*mem = *basemem
For x = 1 To 18
PokeB(*mem, header(x) & $FF)
*mem + 1
Next
While Not Eof(file)
index_nr = ReadByte(file)
PokeB(*mem, palette(index_nr)\rot)
*mem + 1
PokeB(*mem, palette(index_nr)\gruen)
*mem + 1
PokeB(*mem, palette(index_nr)\blau)
*mem + 1
Wend
CloseFile(file)
UseTGAImageDecoder()
img = CatchImage(#PB_Any, *basemem)