![]() |
JPG-Ressourcennutzung in eigenem kompilierten Programm
Hi all,
nach langem Suchen und unter Verknüpfung verschiedener Beiträge aus den Foren hier bin ich endlich auf eine recht adrette (finde ich ;-) - Abkürzungen willkommen) Lösung gekommen für ein Problem im Umgang mit JPEGs, welches ich hatte, gelöst habe und hier zugänglich machen möchte: Hintergrund: Ich arbeite ab und an mit postum (also: nach dem Kompilieren) veränderten EXE-Dateien. Was wie pures hacking klingt, hat seinen Sinn: Wenn man z.B. eine Client-Server-Anwendung schreibt, dann sollte der Client-Installer Informationen (...IP) über seinen konkreten Server bekommen, wenn dieser installiert wird. Das Installieren des Servers macht aber schon der Programmnutzer - also muß mein Installer quasi "zur Laufzeit" modifiziert werden. Ein anderes Beispiel, an dem ich gerade arbeite, ist "Pack & Go" - also, z.B. Jemandem eine Bildershow als _eine_ Datei mitzugeben. Und da sind wir an der interessanten Stelle: Ich packe eine EXE-Datei und ein (später x JPegs) JPeg zusammen in eine Datei. Für Windows ist das uninteressant, die Arbeit der EXE ist nicht beeinträchtigt, wenn sie an erster Stelle steht. Ich selbst aber weiß, daß mein Programm #xx# Byte lang ist, und das JPeg #yy# Byte. Jetzt möchte ich das JPeg in meinem Programm darstellen - wie kriege ich das aus der Datei wieder heraus? Und zwar natürlich, ohne schreibend auf die Festplatte zuzugreifen! Das Beispielprogramm hier trägt aus der VCL nur einen Button und ein Image. Achtung: F9 gilt hier nicht! Nach(!) dem Kompilieren und VOR(!) jedem Ausführen muß man die EXE mit dem JPeg verlinken! Also nie aus der IDE heraus aufrufen! Ansonsten muß man in den ausführlich erklärten Code nur die beiden Zahlen #xx# und #yy# eintragen. Ach so: In Wirklichkeit sollte man die Länge des JPEG besser an das Ende der Datei schreiben (z.B. als Cardinal), dann zuerst die 4 Byte auslesen und dann damit auf das Startbyte des JPeg springen, um von der Länge des Programmcodes unahängig zu sein. Das verkompliziert das Beispiel aber, deshalb habe ich darauf verzichtet... ebenso auf Sicherheiten, es geht hier nur um das Prinzip! Have fun! ScotsMan
Delphi-Quellcode:
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Buttons; type TForm1 = class(TForm) BitBtn1: TBitBtn; Image1: TImage; procedure BitBtn1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} // OLE-Handling erfolgt über ActiveX-Steuerelemente // diese werden hiermit eingebunden uses axCtrls; procedure TForm1.BitBtn1Click(Sender: TObject); var aByteBuffer : Array of Byte; MyFileName : string; MyFilestream : TFileStream; MyFileSize : integer; ABitmap : TBitmap; OleG: TOleGraphic; MyOutStream : TMemoryStream; begin // Dateieigenschaften // Name (ich selbst) MyFileName := ParamStr(0); //...Öffnen MyFileStream := TFileStream.create(MyFileName ,fmOpenRead or fmShareDenyNone); // Byteposition: Zahl der Bytes der Originaldatei MyFileStream.Position := #xx#; // Bytezahl: Größe des Bildes MyFileSize := #yy#; // Zwischenpuffer für das Bild in korrekter Größe einrichten SetLength(aByteBuffer, myFileSize); // Dateistreamfragment nach Bytepuffer einlesen MyFilestream.read( aByteBuffer[0], myFileSize); // Aufräumen: Datei schließen MyFilestream.free; // MemoryStream im Speicher anlegen MyOutStream := TMemoryStream.Create; // kompletten Puffer in MemoryStream schreiben MyOutStream.Write(aByteBuffer[0],myFileSize); // Aufräumen: Buffer freigeben SetLength(aByteBuffer, 0); // MemoryStream: Zeiger an den Anfang setzen MyOutstream.Position := 0; // TOLeGraphic ist in axCtrls ("grafischer Container ... für Bitmaps") OleG := TOleGraphic.Create; // Laden aus dem Memory Stream in den Container OleG.LoadFromStream(MyOutStream); // Aufräumen: MemoryStream freigeben MyOutStream.Free; // Neue Bitmap schaffen ABitmap := TBitmap.Create; // Parameter vom OLE-Container nehmen und zeichnen with ABitmap do begin Width := OleG.Width; Height := OleG.Height; Canvas.Draw(0,0,OleG); end; // Aufräumen: OLE-Container freigeben OleG.Free; // Bitmap in das Image (Standard-Control) übernehmen Image1.Picture.Bitmap.Assign(ABitmap); // Parameter des Bitmaps vom Original setzen Image1.Width := ABitmap.Width; Image1.Height := ABitmap.Height; // Aufräumen: Bitmap freigeben ABitmap.Free; // Image positionieren Image1.Top := 50; Image1.Left := 1; // fertig... end; |
AW: JPG-Ressourcennutzung in eigenem kompilierten Programm
Warum legst du denn den Puffer aByteBuffer an?
Du kannst doch direkt vom FileStream in den MemoryStream kopieren.
Delphi-Quellcode:
MyOutStream.CopyFrom(MyFilestream, myFileSize);
Dein Code ist übrigens überkommentiert. Du hast es sicher gutgemeint, aber ein Kommentar für jede einzelne Zeile ist zu viel. Ich würde den Code lieber so aufbereiten, dass man eine Funktion mit Übergabeparametern hat die man aufrufen kann. |
AW: JPG-Ressourcennutzung in eigenem kompilierten Programm
Hallo, und Danke.
1.) Ja, thanks, der CopyFrom-Befehl erspart das Einrichten eines Puffers - gerade ausprobiert und ab sofort im Programm eingesetzt. 2.) Das Überkommentieren habe ich nur für die Darstellung hier gemacht, um evtl. auch Newbies zu zeigen, was wo passiert. Normalerweise sieht mein Quellcode weniger grün aus, "ischwöre" :-) ScotsMan |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:17 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 by Thomas Breitkreuz