Hallo, Community!
Auch ich habe mal wieder ein Problem, und zwar folgendes:
Für ein Spiel habe ich eine Klasse TTileSkin, die das Sprite des Tiles sowie einige Zusatzinformationen enthält. Das Sprite ist ein TBitmap32. Für das Speichern werden die Sprites mit der PNGImage-Komponente komprimiert und in eienr Datei gespeichert. Das klappt auch sehr gut, es wird ein gültiges PNG gespeichert. Beim Laden werden dann die PNGs wieder ausgelesen - Soweit alles okay. Bei einem bestimmten PNG tritt jedoch ein Fehler auf, wenn ich es anschließend wieder mit der
LoadPNGIntoBitmap32-Funktion in ein TBitmap32 laden will:
Code:
---------------------------
Benachrichtigung über Debugger-
Exception
---------------------------
Im Projekt TileEditor.exe ist eine
Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 0047FF01 in Modul 'TileEditor.exe'. Lesen von Adresse 017A9000' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------
Markiert ist die zeile 4809 der
Unit PNGImage (ImageData[i] := pRGBQuad(@ImageSource[i2 * 3])^), das ist in der procedure TPngObject.DrawPartialTrans(
DC: HDC; Rect: TRect). Die wird von TBitmap32.Assign(TPNGObject) aufgerufen.
Ich bin echt ratlos, weil das ganze mit 7 von 8 Bildern tadellos funktioniert. Und das eine Bild, das nicht funktioniert, wurde ja von der Komponente selbst erzeugt und wird auch anstandslos geladen. Testweise habe ich es auch nochmal direkt nach dem Laden mit SaveToFile abgespeichert, heraus kam ein absolut valides PNG.
Hier noch mein eigener Code. Ich nutze der Einfachkeit halber TRAKBinaryStreamData von Richard Kaspar. (Mit der erzeugten Datei ist aber ebenfalls alles in Ordnung)
Delphi-Quellcode:
// Diese Funktion habe ich selbst geschrieben, um eine beliebige Grafik in ein TBitmap32 zu laden.
function LoadGraphicIntoBitmap32(
const dest: tBitmap32;
const src: tGraphic): boolean;
var
dummy: boolean;
begin
result := false;
if src
is TBitmap
then
begin
dest.Assign(src);
result := true;
end
else if src
is TPNGObject
then
begin
LoadPNGIntoBitmap32(dest,tpngobject(src),dummy);
result := true;
end
else if src
is TGraphicClass
then
begin
dest.SetSize(src.Width,src.height);
dest.Canvas.Draw(0,0,src);
dest.ResetAlpha(255);
result := true;
end;
end;
// Diese Methode lädt den TileSkin aus einem TRAKBinaryTag
procedure TSgTileSkin.LoadFromTag(Tag: TRAKBinarytag);
var
lgraphic: tGraphic;
begin
name := tag.AttributeAsString('
n','
');
// Name laden (irrelevant)
collisionmap.LoadFromTag(tag.FindFirstTag('
cm'));
// Kollisionsmap laden (irrelevant)
if assigned(image)
then freeandnil(image);
// Ggf. das alte Bitmap löschen
begin
Image := tbitmap32.Create;
// Internes Bitmap32 wird erzeugt
lGraphic := tpngobject(TRakBinaryPicture(Tag.AttributeByName('
img')).graphic);
lGraphic.SaveToFile('
c:\hsadhgjh.png');
// Hier habe ich es testweise gespeichert -> kein Fehler, gültiges PNG
if not LoadGraphicIntoBitmap32(image, lGraphic)
then // Wenn das Bild nicht geladen werden konnte
begin
freeandnil(Image);
// Image freigeben
Exception.CreateFmt('
Nicht unterstütztes Format (%s)',
[TRakBinaryPicture(Tag.AttributeByName('
img')).Graphic.ClassName]);
// exception schmeißen
end;
end;
lines.LoadFromTag(tag.FindFirstTag('
l'));
// Spezielle Vektordaten (irrelevant)
end;
Ich habe die PNGs angehängt.
Ich hoffe, wenigstens einer konnte mir folgen
ich kann eifnach nicht erklären...
Danke im Voraus