![]() |
Bild aus Spieldatei extrahieren
Hallo,
diesmal habe ich ein Problem mit Bildern :) Ich möchte ein Logo aus einer Spieldatei extrahieren. Der Inhalt muss zuerst mit ZLib dekomprimiert werden und dann werden die Pixel einzeln ausgelesen (ARGB). Es gibt ein C# Programm, welches das schon kann. Einen Teil davon wollte ich nun nach Delphi übersetzen und es scheint auch, ein bisschen zumindest, zu funktionieren, denn ich sehe einzelne Pixel einer fetten Schrift, allerdings keine farbigen Inhalte.
Code:
Und nun meine Delphi Übersetzung:
MemoryStream stream = new MemoryStream();
stream.Write(compressedBuffer, 2, compressedBuffer.Length - 2); byte[] buffer = new byte[decompressedSize]; stream.Position = 0L; DeflateStream stream2 = new DeflateStream(stream, CompressionMode.Decompress); stream2.Read(buffer, 0, buffer.Length); stream2.Close(); stream2.Dispose(); stream.Close(); stream.Dispose(); Bitmap bitmap = new Bitmap(this.width, this.height); // vorher ausgelesen int x = 0; int y = 0; for (int n = 0; n < decompressedSize; n += 2) { if (x == this.width) { x = 0; y++; if (y == this.height) { break; } } num9 = (buffer[n] & 0x1f) << 3; //b num9 |= num9 >> 5; num8 = ((buffer[n + 1] & 7) << 5) | ((buffer[n] & 0xe0) >> 3); // g num8 |= num8 >> 6; num7 = buffer[n + 1] & 0xf8; // r num7 |= num7 >> 5; num6 = 0xff; // a bitmap.SetPixel(x, y, Color.FromArgb(num6, num7, num8, num9)); x++; }
Delphi-Quellcode:
Dann habe ich noch eine halbwegs funktionierende Delphi Version :p (man kann alles erkennen, allerdings ist es teilweise etwas pixelig und die Farben sind etwas falsch)
deSize := StreamDecompression(vBuf, vOutputStream);
if deSize = -1 then Exit; vOutputStream.Position := 2; // bei dem Stream.Write oben steht auch Offset 2 bmp := TBitmap.Create; bmp.SetSize(FWidth, FHeight); n := 0; x := 0; y := 0; while n < deSize do begin if x = FWidth then begin x := 0; Inc(y); if y = FHeight then Break; end; vOutputStream.Read(b1, 1); vOutputStream.Read(b2, 1); b := (b1 and $1f) shl 3; //b b := b or (b shr 5); g := ((b2 and 7) shl 5) or ((b1 and $e0) shr 3); // g g := g or (g shr 6); r := b2 and $f8; // r r := r or (r shr 5); a := $ff; // a cc := a shl 24 + r shl 16 + g shl 8 + b; // kann man das so machen? bmp.Canvas.Pixels[x, y] := cc; Inc(n, 2); Inc(x); end; Hier wird das Bitmap-Bild komplett manuell erzeugt
Delphi-Quellcode:
Kennst sich jemand mit solchen Dingen gut aus und sieht in dem ganzen einen Sinn? Ich hab keine Ahnung was diese ganze Bit-Rumschieberei bewirkt^^
FillChar(BF, SizeOf(TBitmapFileHeader) , 0);
with BF do begin bfType := Ord('B') + Ord('M') * $100; //2 bfSize := 2 * vOutputStream.Size + SizeOf(TBitmapFileHeader) + SizeOf(TBitmapInfo);//4 ¾ã?¤å¥ó¤j¤p bfReserved1 := 0; //2 bfReserved2 := 0; //2 bfOffBits := SizeOf(TBitmapFileHeader) + SizeOf(TBitmapInfoHeader); //4 ?¤å¥ó?©l¨ì¦ì??Õu?©l¤§?ªº?Õu(bitmap data)¤§?ªº°¾²¾¶q end; vBMPStream.WriteBuffer(BF, SizeOf(TBitmapFileHeader)); FillChar(BI, SizeOf(TBitmapInfo) , 0); with BI do begin BI.bmiHeader.biSize := SizeOf(TBitmapInfoHeader); //Bitmap Info Header)ªº?«× BI.bmiHeader.biWidth := FWidth; BI.bmiHeader.biHeight := FHeight; BI.bmiHeader.biPlanes := 1; BI.bmiHeader.biBitCount := 32; BI.bmiHeader.biCompression := BI_RGB; end; vBMPStream.WriteBuffer(BI, SizeOf(TBitmapInfo)); for y := FHeight - 1 downto 0 do begin vOutputStream.Seek(2 * y * FWidth, 0); for i := 1 to FWidth do begin if vOutputStream.position > vOutputStream.size then pp := 0 else vOutputStream.Read(pp, 2); a := (pp shr 12) and $0F; a := a * $11; r := (pp shr 8) and $0F; r := r * $11; g := (pp shr 4) and $0F; g := g * $11; b := (pp) and $0F; b := b * $11; cc := a shl 24 + r shl 16 + g shl 8 + b; //cc := r shl 16 + g shl 8 + b; vBMPStream.Write(cc, 4); //vBMPStream§Y32¦ìBMP®æ¦¡ªº?¹³?Õu¬y end; end; |
Re: Bild aus Spieldatei extrahieren
Vielleicht weiß jemand, was ich ändern muss, wenn er die Resultate sieht:
So ist es richtig (vom C# Programm): ![]() So sieht es bei meiner Übersetzung aus: ![]() Und so macht es die halbrichtige Delphi Methode: ![]() |
Re: Bild aus Spieldatei extrahieren
Vermutlich sind bei deiner Übersetzung die Variablen b1 und b2 als Byte deklariert.
Das führt dazu, daß bei den Bit-Verschiebungen ein großer Teil der Information einfach verschwindet. var b1, b2: Word; {MSB des Word mit 0 initialisieren $0000} b1 := 0; b2 := 0; {LSB in das Word laden $00xx} vOutputStream.Read(b1, 1); vOutputStream.Read(b2, 1); Das Alpha-Byte gibt es bei TColor nicht (wird nur zur Kennzeichnung von Farben aus Paletten genutzt) und sollte deshalb Null sein. cc := b shl 16 + g shl 8 + r; // $00bbggrr oder cc := RGB(r, g, b); |
Re: Bild aus Spieldatei extrahieren
er kann r, b und g schon als Byte definieren, aber dann muß vor dem SHL die Größe angepaßt werden.
Delphi-Quellcode:
cc := Integer(b) shl 16 + Integer(g) shl 8 + r;
// bzw. cc := TColor(b) shl 16 + TColor(g) shl 8 + r; PS: für mich sieht es so aus, als wenn das zu lesende Bitmap als 16-Bit-Version gespeichert würde ... da könnte man es doch direkt, ohne pixelweise Umwandlung direkt in ein 16-Bit-Bitmap kopieren? bzw. warum nicht einfach direkt als Bitmäp auslesen? TImage/TBitmap können diese Bitmaps doch lesen und wenn ich mir das "selbst erzeugen" so anseh, sieht es ganz nach 'nem normalen Bitmap-Format aus :gruebel: |
Re: Bild aus Spieldatei extrahieren
Tatsächlich benötigt TBitmap zum Lesen auch einen entsprechenden Header in der Datei bzw. Stream
(dort sind z.B. Höhe, Breite, Pixelformat usw. definiert). Da aber das Pixelformat pf16Bit und Breite/Höhe bekannt sind, kann man die Daten auch direkt in das Bitmap speichern.
Delphi-Quellcode:
bmp.Pixelformat := pf16Bit;
for y := 0 to bmp.Height - 1 do AStream.Read(bmp.ScanLine[y]^, bmp.Width * 2); |
Re: Bild aus Spieldatei extrahieren
Danke für eure Tipps! Ich habe die ganzen Bytes in Words umgewandelt und benutze nun RGB(). Klappt wunderbar :thumb:
|
Re: Bild aus Spieldatei extrahieren
Zitat:
aber schneller ginge es halt, wenn du den Datenstrom direkt kopierst und nicht über das sehr langame .Pixels gehst. PS zum Copyright: ist es überhaupt erlaubt Bilder aus dem Spiel rauszuholen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz