Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher? (https://www.delphipraxis.net/48823-bildaendern-stretchdraw-stretchblt-nicht-thread-sicher.html)

axelf98 30. Jun 2005 22:35


Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher?
 
Hallo!
Ich programmiere grad ein FotoShow-Programm, das mit Hilfe eine Threads die Thumbnails erstellt. Dabei kann man in einer Liste scrollen, und sehen, wo das Programm grad ist mit den Thumbs. Das klappt auch ganz gut, nur bei 100 Bildern sind sporadisch 1-2 dabei die er nicht anzeigt, weiß bleiben.
Als Routine nehme ich Canvas.StretchDraw(..). Auch StretchBlt zeigt neben reduzierter Farbtiefe dieses Verhalten. Nehme ich dagegen Canvas.Draw, sind alle Bilder da und zeigen einen Ausschnitt vom Bild (Sinnigerweise nicht das ganze).

Mir scheint, dass die Stretch-Befehle nicht Thread-sicher sind. Habt ihr Ideen?

Sanchez 1. Jul 2005 07:26

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Hallo,
Eine brauchbare Qualität erreichst du mit StretchBlt indem du vorher den StretchBlt-Modus setzt:
Delphi-Quellcode:
  SetStretchBltMode(Canvas.Handle, STRETCH_HALFTONE);
  SetBrushOrgEx(Canvas.Handle, 0, 0, nil);
Zur Threadsicherheit dieser Funktionen kann ich dir leider nichts sagen.
Könnte evtl. nicht eher das Problem sein, dass deine Threads irgendwas auf die Oberfläche pinseln?

grüße, daniel

SirThornberry 1. Jul 2005 07:40

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Threadsicher wirst du das ganze selbst machen müssen. Also die Thumbs im Thread erzeugen und dann um das Thumb anzuzeigen (die Anzeigekomponente gehört ja dann zum Hauptthread) musst du wohl mit Syncronize arbeiten.
Also Thumb in Thread erzeugen -> Bild syncron mit Hauptthread zuweisen

axelf98 1. Jul 2005 11:14

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Zitat:

Zitat von SirThornberry
Also Thumb in Thread erzeugen -> Bild syncron mit Hauptthread zuweisen

Ich werds versuchen.. Mal schaun, was daraus wird.
Die Qualität ist mit StretchBlt und
Delphi-Quellcode:
SetStretchBltMode(Canvas.Handle, STRETCH_HALFTONE);
SetBrushOrgEx(Canvas.Handle, 0, 0, nil);
wesentlich besser als mit StretchDraw!

axelf98 3. Jul 2005 17:41

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Hallo nochmal! Leider konnte ich keine Möglichkeit finden, die beiden genannten Prozeduren threadsicher zu machen. Selbst die Kapselung in dem Thread, der Schutz vor Zugriffen durch ein extra-Array (erst erstellen, dann ins Hauptprogramm kopieren) hat nichts gebracht. Mir ist aufgefallen dass StretchBlt hier mehr Aussetzer hat als StretchDraw.
Ich suche nach einer alternativen Prozedur oder Funktion, die Bilder verkleinert zeichen kann. Ich überlege grade, die G32-Lib zu benutzen, möchte aber eigentlich auf Fremdkomponenten verzichten.

Wer weiß Rat?

SirThornberry 3. Jul 2005 17:56

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
@axelf98: Wie hast du das ganze umgesetzt? Arbeitest du mit der Delphiklasse TThread?
auf folgende Art und weise sollte es eigentlich ohne Probleme möglich sein
Delphi-Quellcode:
type
  TMyThead = class(TThread)
  private
    procedure MethodForSync;
  protected
    procedure Execute; override;
  end;

[...]
procedure TMyThead.MethodForSync;
begin
  //Dem TImage aus dem Hauptform das ganze zuweisen
  DeinHauptForm.Image1.Picture.Bitmap.Assign(ThumbPicAusThread)
end;

procedure TMyThead.Execute;
begin
  //Thumb zerugen
  Synchronize(MethodForSync);
end;

axelf98 3. Jul 2005 18:12

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Zitat:

Zitat von SirThornberry
@axelf98: Wie hast du das ganze umgesetzt? Arbeitest du mit der Delphiklasse TThread?

Ja genau, meine Record:

Delphi-Quellcode:
Type TFoto = record     // Was alles drin sein kann
 FileScr: String;
 Vorschau: TBitmap;
end;
Type pTFoto = ^TFoto;   // Pointer für den Record
Mein Thread:
Delphi-Quellcode:
type
  Vorschaubildererstellen = class(TThread)

  public
    constructor INIT(Daten: TFotoShow; Gaug: TGauge; Gri: TStringgrid; Pane: TPanel);
  private
    { Private-Deklarationen }
    mFotos: TFotoShow; // Für den Daten Zugriff aufs Form Übergabe der Pointer
    Gauge: TGauge;
    Grid: TStringgrid;
    Panel: TPanel;
  protected
    procedure Vorschauerstelleneinzeln(Nr,Gr: integer; Fot: pTFoto);
    procedure Execute; override;
  end;

implementation
uses main;

constructor Vorschaubildererstellen.INIT(Daten: TFotoShow; Gaug: TGauge; Gri: TStringgrid; Pane: TPanel);
begin
 mFotos := Daten;
 Gauge := Gaug;
 Grid := Gri;
 Panel := Pane;
 inherited create(false);
end;

procedure Vorschaubildererstellen.Execute; // Thread
var i: integer;
  tmp : pTFoto;
begin

 for i := 0 to mFotos.AnzahlFotos-1 do
 begin
  tmp := mFotos.Elemente.Items[i];
  if tmp^.Vorschau = nil then
  begin
  Vorschauerstelleneinzeln(i,mFotos.VorschauGr,tmp);
  end;
 end;
end;

procedure Vorschaubildererstellen.Vorschauerstelleneinzeln(Nr,Gr: integer; Fot: pTFoto);
var LadImage: Timage;
    Verh: Double;
    hoehe, weite,x: integer;
    Extention: String;
    LadBitmap: TBitmap;
    jpg: TJPEGImage;
    MegaP: Real;
    Verk: TBildverkleiner;
begin

 try
 Extention := Ansilowercase(Extractfileext(Fot^.FileScr));

  if Fot^.Vorschau = nil then
  Fot^.Vorschau := TBitmap.Create;

 if (Extention = '.jpg') OR (Extention = '.jpeg') then
 begin    ///  JPGS schnell!!!!  ---------------------------------
  LadBitmap := TBitmap.Create;
  jpg := TJPEGImage.create;
  jpg.LoadFromFile(Fot^.FileScr);

   MegaP := (JPG.Width*JPG.Height)/1000000;
   if MegaP > 1 then
    JPG.Scale := jsEighth  ELSE   // schnell!!
   if MegaP > 0.3 then
    JPG.Scale := jshalf ELSE
    JPG.Scale := jsFullSize;

  LadBitmap.Assign(jpg);

 if (LadBitmap.Width > 0) AND (LadBitmap.Height > 0)then
  begin
   Verh := LadBitmap.Width/LadBitmap.Height;
   Fot^.Vorschau.Width := Gr;
    Fot^.Vorschau.Height := Gr;
   if Verh >= 1 then
   begin
   hoehe := Round(Gr/Verh);
   x := round((Gr-hoehe)/2);
  Fot^.Vorschau.Canvas.StretchDraw(Rect(0,x,Gr,hoehe+x),LadBitmap); // HIER wird gemalt
   end ELSE
   begin
   weite := Round(Gr*Verh);
   x := round((Gr-weite)/2);
   Fot^.Vorschau.Canvas.StretchDraw(Rect(x,0,weite+x,gr),LadBitmap);  // HIER wird gemalt
   end;
   end;
  jpg.Free;
  LadBitmap.Free;
 end ELSE
 begin    

 ///  BMPS oder anderes
 
  end ELSE
  begin
   Fot^.Vorschau := nil;
  end;
  LadImage.Free;
 end;
 except
    Fot^.Vorschau := nil;
  end;
 end;
Ich schreibe nochmals, dass jede andere Prozedur, sei es Canvas.Draw(..), Canvas.Rectangle oder ähnliches anstelle des StretchDraw wunderbar funktioniert und jedes Mal gezeichnet wird!

BlackJack 3. Jul 2005 20:43

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
die stellen mit "//HIER wird gemalt" müsstest du in eine extra procedure packen, und diese dann mit
Code:
Syncronize(Proc);
aufrufen.
informier dich ansonsten nochmal in der Hlife über die funktionsweise von TThread.Syncronize().

axelf98 3. Jul 2005 23:57

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Zitat:

Zitat von BlackJack
die stellen mit "//HIER wird gemalt" müsstest du in eine extra procedure packen, und diese dann mit
Code:
Syncronize(Proc);
aufrufen.

Die Lösung ist zwar programmiertechnisch (nicht ganz OOP) etwas umständlich, aber die funtioniert! DANKE

Gandalfus 4. Jul 2005 01:11

Re: Bildändern (StretchDraw, StretchBlt) nicht Thread-sicher
 
Delphi-Quellcode:
canvas.lock
canvas.unlock


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:36 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz