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:
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++;
}
Und nun meine Delphi Übersetzung:
Delphi-Quellcode:
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;
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)
Hier wird das Bitmap-Bild komplett manuell erzeugt
Delphi-Quellcode:
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;
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^^