Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi TImage EAccessViolation (https://www.delphipraxis.net/119456-timage-eaccessviolation.html)

Schwedenbitter 26. Aug 2008 22:34


TImage EAccessViolation
 
Hallo,

ich versuche mich grad am Scannen mehrerer Seiten mit TTwain. Das Scannen klappt, wenn ich schon beim Erstellen des Formulars ein TImage anlege, dem dann das Scanresultat zugewiesen wird. Mein Ziel ist es aber, mehrere Dokumente einzuscannen und da ich nicht weiß, wieviel der User auf den Scanner gepackt hat, muss ich die TImages zur Laufzeit anlegen. Ich will die später dann mittels Thread komprimieren und Speichern.

Hier klappt es dann leider nicht mehr:
Delphi-Quellcode:
procedure TForm1.DelphiTwain1TwainAcquire(Sender: TObject;
   const Index: Integer; Image: TBitmap; var Cancel: Boolean);
Var
   T1   : TImage;
begin
   // Und wieder eine Seite...
   Inc(Zaehler);
   // Image im Formular anlegen
   If T1=nil Then
   Begin
      T1:=TImage.Create(Form1);
      //T1:=TImage.Create(Form1);
      T1.Left:=8;
      T1.Top:=8;
      T1.Width:=73;
      T1.Height:=105;
      T1.Stretch:=True;
      T1.AutoSize:=False;
   End;
   //Copies the Image parameter to the TImage
   T1.Picture.Assign(Image);            -> Zugrissverletzung
   //Image1.Picture.Assign(Image);      -> So lief es
   //We only want the first image
   Cancel:=True;
end;
Ich bekomme immer eine EAccessViolation. Wer kann mir sagen warum?

Gruß und Danke im Voraus, Alex

mkinzler 26. Aug 2008 22:46

Re: TImage EAccessViolation
 
Delphi-Quellcode:
T1.Parent := Form1;

Schwedenbitter 27. Aug 2008 07:41

Re: TImage EAccessViolation
 
Danke erstmal für die Antwort.
Zitat:

Zitat von mkinzler
Delphi-Quellcode:
T1.Parent := Form1;

Hat leider nichts gebracht. Die Fehlermeldung kommt wie eh und je. Vielleicht habe ich es auch an der falschen Stelle:
Delphi-Quellcode:
   Inc(Zaehler);
   // Image im Formular anlegen
   If T1=nil Then
   Begin
      T1:=TImage.Create(Form1);
      T1.Parent:=Form1;
      T1.Left:=8;
      T1.Top:=8;
      T1.Width:=73;
      T1.Height:=105;
      T1.Stretch:=True;
      T1.AutoSize:=False;
   End;
   //Copies the Image parameter to the TImage
   T1.Picture.Assign(Image);
Ich glaube auch, dass das keine Rolle spielen sollte, da ich dem TImage mit TImage.Create(Form1); explizit sage, dass er zu Form1 gehört...

DeddyH 27. Aug 2008 07:43

Re: TImage EAccessViolation
 
Und bei
Delphi-Quellcode:
T1.Picture.Bitmap.Assign(Image);
?

Schwedenbitter 27. Aug 2008 08:15

Re: TImage EAccessViolation
 
Hallo DeddyH
Zitat:

Zitat von DeddyH
Und bei
Delphi-Quellcode:
T1.Picture.Bitmap.Assign(Image);
?

Das hat leider auch nichts gebracht. Es sollte letztlich auch ohne .Bitmap klappen. Denn wenn ich das TImage bei der Erstellung anlege, dann klappt es mit dem Befehl
Delphi-Quellcode:
Image1.Picture.Assign(Image);
schließlich auch ohne .Bitmap.
Nur weil ich TImage zur Laufzeit anlege, dürften doch keine anderen Befehle notwendig werden, oder? :gruebel:

DeddyH 27. Aug 2008 08:19

Re: TImage EAccessViolation
 
Kann es evtl. sein, dass das Image gar nicht erzeugt wird? Ich verstehe eh nicht, wieso Du eine lokale Variable auf nil prüfst, es muss ja sowieso erzeugt werden.

Schwedenbitter 27. Aug 2008 08:29

Re: TImage EAccessViolation
 
Zitat:

Zitat von DeddyH
Kann es evtl. sein, dass das Image gar nicht erzeugt wird? Ich verstehe eh nicht, wieso Du eine lokale Variable auf nil prüfst, es muss ja sowieso erzeugt werden.

Ich dachte (<>Wissen), dass man mittels der Abfrage auf nil prüfen kann, ob das Object bereits auf dem Formular existiert; also erzeugt ist. Denn ich brauche die TImage nur, weil als Zwischenspeicher für die Scannerresultate. So stelle ich mir meinen Programmcode vor:

Thread 1
- Neues TImage anlegen
- Ergebnis des Scanners reinschreiben
Ende

Thread 2
- Schauen ob TImage(s) vorhanden sind
- Nach png wandeln
- Abspeichern
- betreffendes TImage löschen
Ende

Dazu muss ich zur Laufzeit TImage anlegen, weil ich nicht wissen kann, wieviel Seiten der Benutzer auf den Scanner gepackt hat.

DeddyH 27. Aug 2008 08:32

Re: TImage EAccessViolation
 
Aber dann ist der Ansatz mit einer lokalen Variablen falsch. Falls Du ggf. mehrere dynamisch erzeugt Images brauchst, könntest Du ja beispielsweise eine TObjectList verwenden.

Schwedenbitter 27. Aug 2008 09:59

Re: TImage EAccessViolation
 
Danke!
Zitat:

Zitat von DeddyH
Aber dann ist der Ansatz mit einer lokalen Variablen falsch.

Das ist mir jetzt auch aufgefallen. Ich komme sonst von den Threads nicht an die TImage(s) ran. Blöder Fehler von mir!

Zitat:

Zitat von DeddyH
Falls Du ggf. mehrere dynamisch erzeugt Images brauchst, könntest Du ja beispielsweise eine TObjectList verwenden.

Ich habe mir mal das hier angesehen und es liest sich vielversprechend. Bin (leider) grad auf Arbeit und kann es nicht ausprobieren. Es scheint nur ein Problem zu geben: Gibt es das unter Delphi 6 auch schon? Es sieht leider nicht danach aus :cry:

Gruß, Alex

DeddyH 27. Aug 2008 10:01

Re: TImage EAccessViolation
 
Ich habe gerade unter Delphi 5 nachgesehen, da gibt es TObjectlist bereits.

Neutral General 27. Aug 2008 10:19

Re: TImage EAccessViolation
 
Hi,

Dazu sollte man erwähnen, dass er die Unit "contnrs" einbinden muss.

Gruß
Neutral General

DeddyH 27. Aug 2008 10:33

Re: TImage EAccessViolation
 
Das steht aber in der Hilfe (und die ist unter Delphi 6 ja noch zu gebrauchen ;)).

Schwedenbitter 27. Aug 2008 18:00

Re: TImage EAccessViolation
 
Das mit der TObjectList habe ich jetzt eingebaut. Leider aber nicht richtig. Denn ich bekomme jetzt eine Zugriffsverletzung. Syntaxfehler kann ich nicht ausmachen. Der Code wird ohne zu murren kompiliert.

So funktionierte es ...
Delphi-Quellcode:
Procedure Speichern;
Var
   PNG :TPNGObject;
Begin
   // Vom Scanner holen
   // Image1 ist vom Typ TImage
   // Image ist vom Typ TBitmap
   Image1.Picture.Assign(Image);
   // Speichern
   PNG.Assign(Image1.Picture.Graphic);
End;
und so funktioniert es nicht mehr ...
Delphi-Quellcode:
Procedure Speichern;
Var
   PNG :TPNGObject;
Begin
   // Bilder ist vom Typ TObjectList und wurde zuvor mit
   // Bilder:=TObjectList.Create;  sowie
   // Bilder.OwnsObjects:=True;    angelegt.
   // Image ist wieder vom Typ TBitmap
   Bilder.Add(Image);
   // Erstes Bild Speichern
   PNG.Assign(TBitmap(Bilder.Items[0]));
End;
Kleine Erklärung:
Ich wollte mit dem zweiten Beispiel nicht den Weg über TImage gehen. Zum einen ist das Bild sowieso vom Typ Bitmap. Zum anderen muss ich das Bild dann verstecken, weil TImage.Create(X); in X immer ein Argument z.B. Form1 haben will und es dort dann auch anzeigt.

Zusätzliche Frage:
Ich vermute, dass das übergeben Image nur ein Pointer ist. Es ist daher nicht auszuschließen, dass es beim nächsten Aufruf des Ereignisses durch die TWAIN den Inhalt überschreibt. Wenn ich TObjectList richtig verstehe, ist das selbst auch wieder nur eine Liste von Pointern. Wie kann ich sicher stellen, dass ich auch wirklich den Inhalt in der Liste gespeichert habe.

Wie komme ich an den Inhalt der TObjectList ran?

Gruß, Alex

DeddyH 27. Aug 2008 18:07

Re: TImage EAccessViolation
 
Außer, dass Du das TPngObject nicht anlegst, kann ich auch nichts entdecken. Und TObjectlist enthält eine Liste mit Instanzen, welche ja auch nur Pointer sind. Heran kommst Du ganz normal über den Index, ggf. musst Du halt casten.

Schwedenbitter 27. Aug 2008 18:11

Re: TImage EAccessViolation
 
Zitat:

Zitat von DeddyH
Außer, dass Du das TPngObject nicht anlegst, kann ich auch nichts entdecken.

Das mache ich schon. Ich wollte nur nicht den ganzen Code hier posten. Sind zwar nur 117 Zeilen. Aber ich will das nicht überfrachten...

DeddyH 27. Aug 2008 18:20

Re: TImage EAccessViolation
 
In welcher Zeile knallt es denn genau?

Schwedenbitter 27. Aug 2008 18:23

Re: TImage EAccessViolation
 
@DeddyH
Bei dem Code-Schnipsel in Zeile 10, weil das Object zwar da aber leer war (Siehe unten).
:cheers: Ich habe es geschafft. Mein Denkfehler (mal wieder).

Es reicht nicht, ein Object anzulegen, sondern ich muss es auch füllen! Richtig muss also so heißen:

Delphi-Quellcode:
Procedure Speichern;
Var
   PNG :TPNGObject;
Begin
   // Typen wie vor
   Bilder.Add(TBitmap.Create);
   // Und jetzt der Inhalt ...
   TBitmap(Bilder.Last).Assign(Image);
   // Erstes Bild Speichern
   PNG.Assign(TBitmap(Bilder.Items[0]));
End;
P.S.
Zitat:

10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
Ich wäre auch nach 10 Stunden ohne probieren nicht drauf gekommen.

DANKE an ALLE


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:15 Uhr.

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