Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Umwandlung jpeg --> Bitmap hier: Zeitbedarf (https://www.delphipraxis.net/101101-umwandlung-jpeg-bitmap-hier-zeitbedarf.html)

KPBecker 8. Okt 2007 13:59


Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, Delphi-Praktiker,

Umwandlung eines eingelesenen jpeg-Bildes (jpgBild) in eine Bitmap (bmpBild):
(Zweck: Die Kamera liefert ein jpeg, zur einfachen Bearbeitung brauche ich das Bitmap.)

Delphi-Quellcode:
    jpgBild.LoadFromFile(BildName);
    bmpBild.Assign(jpgBild);
Dieses Verfahren (Assign) dauert ziemlich lange (0,7 MB jpeg-Datei ca. 200ms, 3 MB jpeg-Datei ca. 1,2 s bei 3 GHz CPU).
(Das Laden fällt demgegenüber gar nicht ins Gewicht.)


Bei dem Ziel, 4-8 Bilder / s zu verarbeiten, ist das ein ko-Kriterium.

Frage:
Benutzt Assign schon schnelle Algorithmen oder gibt es deutliche bessere Lösungen ?

Vielen Dank,
Klaus-Peter

mkinzler 8. Okt 2007 14:08

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Das .LoadFromFile() wandelt das bild schon in BMP, da dies das interne Format von TImage ist.

KPBecker 8. Okt 2007 14:51

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, mkinzler,

nach dem Laden meiner jpeg-Datei ('BildName' ist ein jpeg-File)

Delphi-Quellcode:
  jpgBild.LoadFromFile(BildName);
habe ich zunächst ein jpeg-Bild zur Verfügung, das ich in bmp umwandeln muß - dachte ich.

Ich weise dieses Bild keinem TImage zu (ich will es gar nicht sehen), sondern brauche eine Bitmap zur Weiterbearbeitung.

Wie komme ich (in meinem Beispiel) von jpgBild nach bmpBild, ohne Assign zu verwenden ?

Lösung ???:
Wenn ich jpgBild einem TImage zuweise, geht das (nach einem ersten Versuch) tatsächlich deutlich flotter als das Assign !!
Ist der Umweg jpgBild --> TImage (unsichtbar, von der Sache her unnötig) --> bmpBild die schellere Lösung ?

Delphi-Quellcode:
    imgBild.Picture.Assign(jpgBild);
Frage 1 daher, wie komme ich (schnell) an das Bitmap, das dem TImage intern wohl zu Grunde liegt ?
Frage 2: Wenn das alles über diesen Umweg besser funktioniert, warum ist

bmpBild.Assign(jpgBild); so langsam und
imgBild.Picture.Assign(jpgBild); soviel schneller ??


Klaus-Peter

mkinzler 8. Okt 2007 14:54

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
das Assign ist unnötig, da das bild nach dem laden im Bmp-Format vorliegt. du kannst es deshalb direkt als Bmp Speichern.

KPBecker 8. Okt 2007 15:02

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, mkinzler,

entschuldige, ich hab's immer noch nicht:

Delphi-Quellcode:
var:
  jpgBild: TJPEGImage;
  bmpBild: TBitmap;
begin
  jpgBild:= TJPEGImage.Create;
  bmpBild:= TBitmap.Create;
  jpgBild.LoadFromFile(Bildname);  //  bmpBild.LoadFromFile(BildName) geht nicht !

  // und nun ?? 
  // wie bekomme ich das Bild nach bmpBild ?

  ...
end;
Klaus-Peter

mkinzler 8. Okt 2007 15:04

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Du brauchst das 2. TImage nicht!
Delphi-Quellcode:
var
  jpgBild: TJPEGImage;
begin
  jpgBild:= TJPEGImage.Create;
  jpgBild.LoadFromFile(Bildname);
  jpgBild.SaveToFile( Bildname2);

KPBecker 8. Okt 2007 15:16

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Ich versteh's immer noch nicht:


Zitat:

Zitat von mkinzler
Du brauchst das 2. TImage nicht! --> wo habe ich ein zweites TImage ???
Delphi-Quellcode:
var
  jpgBild: TJPEGImage;
begin
  jpgBild:= TJPEGImage.Create;
  jpgBild.LoadFromFile(Bildname);   --> soweit, so gut
  jpgBild.SaveToFile( Bildname2);   --> ich möchte nichts "To File Saven"


Ich möchte das eingelesene JPEG-Bild zur weiteren Bearbeitung als Bitmap in bmpBild stehen haben.

bmpBild:= xxxxx oder so ähnlich.


Klaus-Peter

mkinzler 8. Okt 2007 15:21

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Ein TImage (oder abgeleitete klasse) speichert intern immer im Bitmap-Format!

Delphi-Quellcode:
Uses ...jpeg, ...
...
var
  bmpBild: TBitmap;
begin
  bmpBild:= TBitmap.Create;
  bmpBild.LoadFromFile('Bildname.jpg');
sollte eigentlich auch funktionieren.

SirThornberry 8. Okt 2007 15:23

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
hast du es schon mit einem einfachen Draw versucht? Also erst die Größe des Bitmaps mit Bitmap.SetSize setzen und dann mit Bitmap.Canvas.Draw das jpeg auf die Canvas des bitmaps bringen.

@mkinzler: Warum schreibst du etwas von einem TImage? Das wird doch gar nicht gebraucht.
Und nein, ein TBitmap kann kein jpeg laden. Es heißt ja nicht umsonst TBitmap und nicht TJPEG, TTGA, TTIF etc.
ein TBitmap kann eigentlich nur ein Bitmap laden.

KPBecker 8. Okt 2007 15:40

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Zitat:

Zitat von mkinzler
Ein TImage (oder abgeleitete klasse) speichert intern immer im Bitmap-Format!

Delphi-Quellcode:
Uses ...jpeg, ...
...
var
  bmpBild: TBitmap;
begin
  bmpBild:= TBitmap.Create;
  bmpBild.LoadFromFile('Bildname.jpg');
sollte eigentlich auch funktionieren.


Habe ich auch gedacht, aber ich bekomme den Fehler

Im Projekt ... ist eine Exception der Klasse EInvalidGraphic aufgetreten. Meldung: "Bitmap ist ungültig".

Also
Delphi-Quellcode:
;
  jpgBild.LoadFromFile('BildName.jpg');
  bmpBild.Assign(jpgBild);
--> geht

Die Änderung der ersten Zeile in
Delphi-Quellcode:
    bmpBild.LoadFromFile('BildName.jpg');
--> bringt die genannte Fehlermeldung. (bmpBild ist hier schon genau so definiert, wie im Beispiel oben.)


Aber:
Die Zuweisung eines JPEG an ein TImage geht sehr schnell und dabei findet, wie Du sagst, ja auch schon eine Umwandlung in ein Bitmap statt. Wie komme ich an dieses Bitmap, um es meiner Variablen bmpBild zuzuweisen.
Das würde helfen.

Klaus-Peter

DeddyH 8. Okt 2007 15:53

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Das steht in Image.Picture.Bitmap

KPBecker 8. Okt 2007 16:06

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, Jens,

Dein Vorschlag funktioniert, aber das Draw benötigt genau so viel Zeit wie das Assign (Vielleicht wird derselbe Weg genommen.)

Klaus-Peter

KPBecker 8. Okt 2007 16:13

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, Deddy,

Zitat:

Zitat von DeddyH
Das steht in Image.Picture.Bitmap

Dann müßte doch gehen

bmpBild.Assign(jpgBild.Picture.Bitmap);

Das bringt aber den Fehler "Undefinierter Bezeichner Picture"

Klaus-Peter

axelf98 8. Okt 2007 17:03

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
und wie schaut's damit aus?

Delphi-Quellcode:
..
var bmp:TBitmap;
    jpg: TJPEGImage;
begin
     bmp := TBitmap.Create;
     jpg := TJPEGImage.Create;
     jpg.LoadFromFile(...);
     bmp.Width := jpg.Width;
     bmp.Height := jpg.Height;
     bmp.canvas.Draw(0,0,jpg);
EDIT: noch ein Tipp: Wenn nicht die volle Auflösung gebraucht wird:
Delphi-Quellcode:
     jpg := TJPEGImage.Create;
     jpg.scale := jsQuarter;
Aus der Hilfe
Zitat:

jsFullSize Zeigt die Grafik in voller Größe an.
jsHalf Zeigt die Grafik in halber Göße, dafür aber in doppelter Geschwindigkeit an.
jsQuarter Zeigt die Grafik in einem Viertel der maximalen Größe, dafür aber viermal so schnell an.
jsEighth Zeigt die Grafik in einem Achtel der maximalen Größe, dafür aber achtmal so schnell an.

Scale wird beim Einlesen von Dateien (d.h. beim Dekomprimieren) verwendet.

DeddyH 8. Okt 2007 17:11

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Zitat:

Zitat von KPBecker
bmpBild.Assign(jpgBild.Picture.Bitmap);

Das bringt aber den Fehler "Undefinierter Bezeichner Picture"

Wenn jpgBild wirklich ein TImage ist, sollte das in der Tat gehen.

Dani 8. Okt 2007 17:42

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Vielleicht hilft das:

Ich habe Delphi 6 Prof und in folgendem Code ist Img.Bitmap ein ungültiger Bezeichhner.

Delphi-Quellcode:
uses Jpeg

...

procedure TForm1.Button1Click(Sender: TObject);
var Img: TJpegImage;
    Bmp: TBitmap;
begin
  Img := TJpegImage.Create;

  Img.LoadFromFile('C:\1.jpg');

  Bmp := Img.Bitmap;

  with Bmp.Canvas do begin
     Brush.Style := bsSolid;
     Brush.Color := clGreen;
     Pen.Color := clPurple;
     FillRect(Rect(0,0,20,20));
  end;

  Bmp.SaveToFile('C:\1.bmp');
end;
Leitet man eine neue Klasse von TJpegImage ab, ohne irgendwas hinzuzufügen, ist es plötzlich sichtbar.

Delphi-Quellcode:
uses Jpeg

...

type
  TJpegImage2 = class(TJpegImage)
  private
  protected
  public
  published
  end;

...

procedure TForm1.Button1Click(Sender: TObject);
var Img: TJpegImage2;
    Bmp: TBitmap;
begin
  Img := TJpegImage2.Create;

  Img.LoadFromFile('C:\1.jpg');

  Bmp := Img.Bitmap;

  with Bmp.Canvas do begin
     Brush.Style := bsSolid;
     Brush.Color := clGreen;
     Pen.Color := clPurple;
     FillRect(Rect(0,0,20,20));
  end;

  Bmp.SaveToFile('C:\1.bmp');
end;
Fragt mich nicht, warum.

KPBecker 8. Okt 2007 19:38

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, Axelf98,

Dein Vorschlag entspricht dem vom Sir (Jens, s. dort).
Das funktioniert, ist aber leider genau so langsam wie das Assign, das ich vermeiden möchte (s. KPBecker, 17:06).

Klaus-Peter

KPBecker 10. Okt 2007 15:58

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Hallo, Delphi-Praktiker,

hier eine Zusammenfassung der Recherchen und Ergebnisse (Tenor: Still confused, but on a higher level !):

Ziel ist, mit LoadFromFile ein JPEG-Bild einzulesen und als Bitmap (TBitmap) für die weitere Bearbeitung zur Verfügung zu stellen.
- Die Umsetzung ist zeitkritisch und sollte daher schnell gehen.
- Eine Anzeige des Bildes in einem TImage ist nicht notwendig.

Varianten:
0. 30 ms: LoadFromFile in eine TJPEGImage-Variable (jpgBild: TJPEGImage) (Testbild 2,8 MB, JPEG).

1. 950 ms: Assign auf ein Bitmap (bmpBild: TBitmap) ---> bmpBild.Assign(jpgBild).

2. 950 ms: Assign auf ein Bitmap ---> bmpBild.Assign(jpgBild.Bitmap);

3. 1400 ms: Zeichnen auf den Canvas des Bitmap ---> bmpBild.Canvas.Draw(0,0,jpgBild);

4. 10 ms: Assign auf ein TImage (imgBild: TImage) ---> imgBild.Picture.Assign(jpgBild);

- Das Laden aus der Datei (0) spielt also mit 30ms fast keine Rolle, ich habe nicht den Eindruck, daß dabei schon eine Umcodierung in ein Bitmap stattfindet.

- Die tatsächliche Umwandlung des JPEG in eine Bitmap dauert mit 950ms bzw. 1400ms sehr lang (1-3). (1) und (2) scheinen nur unterschiedliche Schreibweisen für dieselbe Sache zu sein.

- Verblüffend ist zunächst (4): Die Zuweisung auf das TImage ist blitzschnell, die eigentliche Umwandlung scheint aber erst stattzufinden, wenn das Bild dann angezeigt werden soll (= wenn das Bitmap gebraucht wird ?): Es dauert dann wieder ca. eine Sekunde, bis das Bild erscheint.

- Man kann nicht ein JPEG-File direkt in ein Bitmap laden.

- Die merkwürdige Beobachtung von Dani kann ich bestätigen: Variante 2. gelingt nur, wenn man vorher eine neue Klasse (TJPEGImage2) definiert hat, die aber in der Art völlig identisch mit Delphis TJPEGImage ist.


Die Frage bleibt: Gibt es keine schnelleren Funktionen / keinen schnelleren Weg ?
Wie kann man überhaupt Echtzeitverarbeitung von Kamerabildern machen, wenn schon die Umwandlung in ein Bitmap (das man ja wohl zur sinnvollen Verarbeitung braucht) so lange dauert. Die meisten Kameras liefern JPEG-komprimierte Bilder. (n.b.: CPU mit 3 GHz, 1 GB RAM)

Vielen Dank für Eure Antworten,
wenn jemand noch eine Idee in Bezug auf die Frage oben hat ...

Klaus-Peter

Lossy eX 11. Okt 2007 09:06

Re: Umwandlung jpeg --> Bitmap hier: Zeitbedarf
 
Ja. Das LoadFrom* lädt noch nicht das komplette Bild sondern holt sich erst einmal die Informationen über das Bild. Die Methode DIBNeeded konvertiert die Bilddaten in ein DIB. Das passiert beim Zuweisen zu einem TBitmap.

Du solltest beim Laden des JPEGs auch folgendes aktivieren. Das reduziert die Zeit schon mal beträchtlich.
Delphi-Quellcode:
JPEG.Performance := jpBestSpeed;
Wenn du deine Bilder nicht in dieser monströsen Auflösung benötigst kannst du auch nach LoadFrom* schauen wie groß ist das Bild und entsprechend vor dem Assign die Eigenschaft Scale setzen. Dadurch kannst du ein Bild vollautoamtisch in der halben Größe laden lassen. Da es nicht nachträglich runtergerechnet wird sondern schon so geladen wird sparrt das massiv Zeit. Gibt noch die Möglichkeit 1/4 oder auch 1/8tel einzustellen.

Und ansonsten habe ich vor ein paar Tagen auch meine Umsetzung von dem Header der libjpeg zum Laufen bekommen. Diese Bibliothek dient auch als Grundlage für die Delphiimplementation und noch mal etwas schneller als diese. Ein 1280x1024 JPEG kann ich mit ihr in ~61ms in voller Auflösung laden. Die Implementation von Delphi benötigt da noch ~86ms. Ohne Performance ist das Verhältniss ~80 ms zu ~220ms. Mit der Bibliothek könnte man sich aber auch das Zuweisen zu einem TBitmap sparen, da man die Bibliothek die Scanlines reinreicht in der sie ihre Bilddaten ablegen soll.

Allerdings erhöht sich dadurch der Programmaufwand ziemlich und ich kann nicht mit Gewissheit sagen, dass die Umsetzung des Headers so 100%tig funktioniert. Bei Bedarf kann ich aber heute abend mal die Bibliothek + Sample hochladen. Wollte ich zwar sowieso irgendwann veröffentlichen aber eigentlich noch nicht so überstürzt. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:19 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-2025 by Thomas Breitkreuz