40 Stimmen

Wie erstelle ich eine PNG-Ressource?

Ich habe ein Formular mit einem großen TImage als Hintergrund. Das Problem ist, dass dies direkt im DFM als Bitmap gespeichert ist, was etwa 3 MB in Anspruch nimmt. Die originale PNG-Datei ist ~250 KB groß. Ich möchte versuchen, die Größe zu reduzieren, indem ich die PNG-Datei als Ressource einbinde und das Formular diese während OnCreate lädt. Das kann ich nun tun, da Delphi 2009 PNG-Unterstützung bietet, nur weiß ich nicht genau, wie man eine Ressourcendatei mit einem PNG erstellt. Weiß jemand, wie das gemacht wird?

62voto

Ondrej Kelle Punkte 36511

Beispieltextdatei (mit dem Namen myres.rc):

MYPNG RCDATA mypng.png

Zum Projekt hinzugefügt:

{$R 'myres.res' 'myres.rc'}

Beispiel für das Laden zur Laufzeit:

uses
  PngImage;

var
  Png: TPngImage;
begin
  Png := TPngImage.Create;
  try
    Png.LoadFromResourceName(HInstance, 'MYPNG');
    Image1.Picture.Graphic := Png; // Image1: TImage auf dem Formular
  finally
    Png.Free;
  end;
end;

0 Stimmen

Ist RCDATA wirklich der spezifischste Ressourcentyp für diesen Grafiktyp? Gibt es beispielsweise kein RT_PNG?

2 Stimmen

Gute Frage, Rob. Mein derzeit installiertes Platform SDK ist für Windows Server 2003 R2, und ich konnte keine PNG-spezifische Konstante in WinUser.h finden. Ich bin mir jedoch nicht sicher. Es könnte irgendwo anders deklariert sein, vielleicht in einer späteren Version des Platform SDK.

12 Stimmen

LoadFromResourceName sucht speziell nach einer Ressource vom Typ RCDATA.

2voto

Cyril Leroux Punkte 2501

Für diejenigen, die C++ Builder verwenden, funktioniert dieser Code für mich:

In der Datei ResourceTest.rc

IMG_BMP BITMAP "Ressources\\myimage.bmp";
IMG_PNG RCDATA "Ressources\\myimage.png";

In der Datei ResourceTest.rh

#ifndef ResourceTestRH
#define ResourceTestRH

#define IMG_BMP "IMG_BMP"
#define IMG_PNG "IMG_PNG"

#endif

In der Datei ResourceTest.cpp

#include "pngimage.hpp"

// bmp-Bild aus Ressource laden
Graphics::TBitmap *bmpImage = new Graphics::TBitmap();
bmpImage->LoadFromResourceName((int)HInstance, IMG_BMP);

// png-Bild aus Ressource laden
TPngImage *pngImage = new TPngImage();
pngImage->LoadFromResourceName((int)HInstance, IMG_PNG);

1voto

Jan Goyvaerts Punkte 20683

Wenn Sie Delphi 2009 verwenden, sollte TImage Ihre PNG-Datei als PNG in die DFM-Datei speichern. Die DFM wird größer sein, da der binäre Inhalt der Picture.Data-Eigenschaft des TImage-Objekts im DFM als hexadekText kodiert ist. Aber wenn der DFM in Ihre EXE kompiliert wird, wird er in eine binäre Ressource kompiliert. Ihr Bild sollte dann im Formular-RCDATA-Ressourcenbereich genauso viel Platz einnehmen, wie das Speichern des PNG in seiner eigenen RCDATA-Ressource würde.

Ich habe dies gerade getestet, indem ich eine meiner eigenen Delphi 2009 DFM-Dateien mit einem TImage-Komponenten, die zum Entwurfszeitpunkt ein PNG-Bild geladen haben, in einem Texteditor geöffnet habe, den Inhalt der Picture.Data-Eigenschaft kopiert und in einen Hexeditor eingefügt habe. Der Hexeditor zeigt mir, dass die Picture.Data-Eigenschaft eine tatsächliche PNG-Datei speichert, die mit 10 Bytes vorangestellt ist. Das erste Byte ist $09 und die nächsten 9 Bytes buchstabieren TPngImage. Wenn ich diese 10 Bytes lösche und die Datei im Hexeditor speichere, erhalte ich eine ordnungsgemäße PNG-Datei.

Also, wenn Sie Delphi 2009 verwenden, laden Sie einfach das PNG-Bild zur Entwurfszeit in eine TImage-Komponente.

0 Stimmen

Interessant, aber was ist mit dem Fall, dass ein Bild auf mehreren Formularen wiederverwendet wird? Ist Delphi intelligent genug, um nur eine Kopie des Bildes zu speichern, oder speichert es das Bild n-mal, wobei n die Anzahl der TImage-Komponenten mit diesem geladenen Bild ist? :)

3 Stimmen

Jedes TImage-Komponente speichert sein Bild unabhängig von anderen TImage-Instanzen. Wenn Sie also dasselbe Bild in n Instanzen von TImage laden, wird dasselbe Bild n-mal gespeichert. Eine Möglichkeit, dies zu lösen, besteht darin, die Formvererbung zu verwenden. Erstellen Sie ein Basiformular mit dem TImage und laden Sie das Bild in dieses. Ableiten Sie dann alle Formulare, die dasselbe TImage haben müssen, von diesem Formular. Alle Eigenschaften, die in abgeleiteten Formularen nicht geändert werden, werden nur im DFM des Vorgängerformulars gespeichert. Dazu gehören auch die Bilddaten eines TImage.

1voto

Ciuly Punkte 11

1voto

Bei der Verwendung von Resource Hacker werden PNG-Bilder mit 'PNG' ResType anstelle von üblichem RT_RCDATA hinzugefügt.

Ein TPngImage-Klassen-Helper bietet eine einfache Lösung für dieses Problem:

Type
  TPngImageHelper = Class Helper For Vcl.Imaging.pngimage.TPngImage
    Procedure LoadFromRHResourceName(Instance: HInst; Const Name: String);
  End;

...

Procedure TPngImageHelper.LoadFromRHResourceName(Instance: HInst; Const Name: String);
Var
  rs: TResourceStream;
Begin
  rs := TResourceStream.Create(Instance, PChar(Name), 'PNG');
  Try
    LoadFromStream(rs);
  Finally
    rs.Free;
  End;
End;

Mit einer einfachen Anwendung:

var
  pngInfo: TPngImage;
begin
  pngInfo := TPngImage.Create;
  try
    pngInfo.LoadFromRHResourceName(HInstance, 'MY_IMAGE.PNG');
    Image1.Picture.Graphic:= pngInfo;
  finally
    pngInfo.Free;
  end;
end;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X