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;