Einzelnen Beitrag anzeigen

ScotsMan

Registriert seit: 1. Nov 2006
Ort: Leipzig
13 Beiträge
 
Delphi XE5 Professional
 
#1

JPG-Ressourcennutzung in eigenem kompilierten Programm

  Alt 10. Feb 2014, 21:01
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;
$ route add default roma.it
  Mit Zitat antworten Zitat