[gelöst] Suche Bild-Kopierbefehl, der Bild direkt kopiert

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

[gelöst] Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von Erwin »

Hallo Zusammen.

Hoffe es gehört hierher. Da vieles generell überschneidet, ...

Habe folgendes Problem: Ich will aus einem Image, das bereit beim Entwurf eine Bilddatei geladen bekommt, bzw. hat, direkt aus dem Image etwas kopieren, und es in ein anderes Image einfügen.
Leider fand ich bei Lazarus/FPC bis jetzt nicht den passenden Befehl. Ich fand bis jetzt nur

Code: Alles auswählen

 
Image1.Canvas.CopyRect(rect(0,0,100,100),Image2.Canvas,rect(0,0,100,100));
 

(Und dann gibt es so einen ähnlichen, der aber leider das gleiche macht.)

Was ich suche, ist ein Befehl, der auch wirklich das macht, was dort steht:
Nämlich ein Teil des Bildes aus dem Image (Canvas) heraus zu kopieren. Und nicht das, was es dann an dem Ort auf dem Bildschirm vorfindet. Sondern es soll ungeachtet dessen, ob die Imagedatei Unsichtbar, verkleinert, versteckt ist, etc., den Inhalt kopieren. Aber statt dessen kopiert es sogar . den Panel, hinter dem man das Image aus Verzweiflung versteckt hat. Oder gar nichts, wenn es unsichtbar ist, oder außerhalb des Bildes, oder zu klein ist etc..
Also ich habe da wirklich schon vorher sogar vieles anderes ausprobiert, um dennoch zum gewünschten Ergebnis zu kommen. Aber ohne Erfolg.
Fand bis jetzt leider nur eine Möglichkeit, um das gewünschte Ergebnis zu erreichen: Per 1-2 Timer die Image voll darzustellen, kopieren, wieder verschwinden lassen. Aber das ist mir zu Unangenehm und zu verwirrend, und auch fraglich, ob da nicht vieles ausgebremst wird, wenn man erst mal oft/viel hin und her kopiert.

Wenn ich selber vorher etwas im Canvas zeichne, dann macht er es richtig. Allerdings auch nur was den selbst gezeichneten Teil betrifft. Während Geladenen Bilder scheinbar ignoriert werden. Egal ob die beim Entwurf, oder während des Programm läuft, geladen wird.

Danke.
Zuletzt geändert von Erwin am Mo 18. Jun 2018, 20:08, insgesamt 2-mal geändert.
Lazarus 2.2.0 / FP 3.2.4

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von MacWomble »

Mir scheint, du müsstets das was du willst auf Dateiebene machen. Dass canvas.copyrect alles was auf der Zeichenfläche (canvas) ist kopiert, sagt ja schon die Logik.

Image <> Canvas!

Du kannst das Image auf den Canvas zeichnen lassen ...
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von Erwin »

Hallo Macwomble.

Dies würde es einerseits einiges erklären. Anderseits klappt es mit Delphi ganz wunderbar so, wie ich es brauchen würde. Dort spielt es keine Rolle, ob das Image(Komponente) sichtbar, versteckt, zu klein etc. ist.

Also zumindest muss es doch auch bei Lazarus einen einfachen Befehl geben, der das auch kann? Oder handelt sich bei der Anpassung (FPC und TP) doch nicht nur um die Verwechslung eines Befehls? Hinzu kommt, dass wenn man etwas per Hand zeichnet, dass diesem Teil dann egal ist, ob das Image unsichtbar, zu klein, etc. ist.
Lazarus 2.2.0 / FP 3.2.4

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von pluto »

Versuch mal bevor du das Bild kopiert das Ziel Canvas mit FillRect zu "Füllen"...
Unter Lazarus/Linux muss man das aufjedenfall machen, bevor man Zeichnen kann.

Also einfach "ZielCanvas.Fillrect(...) und vorher eine Farbe setzten.

Mit den Parametern die du gesetzt hast, kopiert du "ALLES" und nicht nur ein Teil vom Bild.
MFG
Michael Springwald

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von Erwin »

pluto hat geschrieben:Mit den Parametern die du gesetzt hast, kopiert du "ALLES" und nicht nur ein Teil vom Bild.

Dann liegt irgendwo anders ein Fehler vor? Oder vielleicht hätte ich auch einfach mehr Daten dazu nennen sollen? Also das Image/Bild, von dem ich kopieren will, ist in meiner Testversion ca. 4000x4000 groß. Die Image-Komponente wo es rein kopiert werden soll, ist nur 100x100 groß. Wenn ich die Größe der Quelle-Image auf 200x200 einstelle, und so, dass man es sehen kann, kopiert es nur den Oberen Rechten Ausschnitt. Also ... eben nicht Alles, sondern nur ein Teil, wie gewollt. Leider. Wäre schön gewesen, wenn dies der Fehler gewesen wäre.

pluto hat geschrieben:Versuch mal bevor du das Bild kopiert das Ziel Canvas mit FillRect zu "Füllen"...
Unter Lazarus/Linux muss man das aufjedenfall machen, bevor man Zeichnen kann.

Also einfach "ZielCanvas.Fillrect(...) und vorher eine Farbe setzten.

Ähnliche Idee hatte ich selber schon probiert: Ich habe in das Bild hineingezeichnet. In dem Fall (wenn Image Unsichtbar ist), kopiert es mir das selbst gezeichnete, ignoriert aber das Bild dahinter.
Wenn ich vorher eine Art Leinwand mit FillRect mache, kopiert er wieder dennoch nur das, was er sieht.
Und noch was: Also ich kann bei mir unter Lazarus und Linux auch ohne zuerst FillRect zu machen, los zeichnen. Ist dann halt alles drum herum Schwarz, wo noch nicht gezeichnet wurde.
Edit: Wenn der 'Stift', also Pen, selber clBlack (also Schwarz) ist, sieht man natürlich nichts vom gezeichneten Strichen etc.
Lazarus 2.2.0 / FP 3.2.4

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von pluto »

Sagt das doch gleich, dass du von einem Großen Bild in ein kleineres Bild kopieren möchtest: Probiere mal die Methode von Canvas:
StretchDraw
Die sollte das Bild entsprechend anpassen.
MFG
Michael Springwald

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von Erwin »

pluto hat geschrieben:Sagt das doch gleich, dass du von einem Großen Bild in ein kleineres Bild kopieren möchtest: Probiere mal die Methode von Canvas:
StretchDraw
Die sollte das Bild entsprechend anpassen.

Mir geht es NICHT um das anpassen! Sorry für die heftige Klarstellung, aber sonst gibt es, ehe ich mich versehe, nur noch Vorschläge dazu. Sondern um das Kopieren geht es mir. Später will ich auch umgekehrt kopieren, bzw. kleine Teile aus großem Bild in andere große Bild usw. usf.
Da man aber damit auch 1 zu 1 kopieren kann, habe ich bereits schon selber diese Alternative versucht.

Code: Alles auswählen

 
  Image1.Canvas.StretchDraw(rect(0,0,100,100),Image2.Canvas);
 

Ohne Erfolg. Der mag komischerweise kein Canvas, was mich wundert. Weil ich kann mich erinnern, dass es schon mal woanders mit Erfolg mittels Canvas verwendet habe? Aber er meckert was davon, dass Canvas und Grafic nicht zusammen passt.
- Error:Incompatible type for arg no. 2: Got "TCanvas", expected "TGraphic"
Wen ich dann Grafik hernehme (Image2.Picture.PNG - glaube, war es dann), fügt er mir aber dann das Ganze Bild verkleinert ein.

Habe inzwischen eine andere, leider sehr Umständliche und langsame Möglichkeit gefunden, wozu man aber ein weiteres Image braucht.
Außerdem 3 Variablen:

Code: Alles auswählen

 
var i,j: Integer;
var FarbeMalen:TColor;
 

Und dann mittels diesen Codes das Bild neu direkt auf eine Canvas zeichnen:

Code: Alles auswählen

 
  for i:=0 to 399 do
  begin
    for j:=0 to 399 do
    begin
      FarbeMalen:=Image2.Picture.PNG.Canvas.Pixels[i,j];
      Image3.Canvas.Pixels[i,j]:=FarbeMalen;
    end;
  end;
 

Aber schon allein diese kleine Fläche dauerte 3-4 Sekunden, würde ich schätzen.
Das kann also auch nicht Weisheits letzter Schluss sein. Außerdem geht dies in die Falsche Richtung. Statt hie und da auch Bilder und Platz zu sparen, wird es mehr.
Und ja, ich habe auch versucht, wie im letztem Beispiel, die Graphic zu kopieren, was aber nicht nicht ging. Irgendeine Fehlermeldung, wenn ich mich recht erinnere.
Lazarus 2.2.0 / FP 3.2.4

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Suche Bild-Kopierbefehl, der Bild direkt kopiert

Beitrag von Erwin »

Habe es jetzt noch mal probiert.
Diesmal auch etwas, was ich gar nicht versucht hatte, weil es bei StretchDraw nicht ging (Canvas vs. Grafik):

Code: Alles auswählen

 
 Image1.Canvas.CopyRect(rect(0,0,100,100),Image2.Picture.PNG.Canvas,rect(0,0,100,100));
 

Dies funktioniert. Braucht aber recht lange. Würde sagen, sogar länger als wenn man es extra vorher noch mal per Pixel kopiert.
Während bei "Image1.Picture.PNG.Canvas.CopyRect(rect(0,0,100,100),Image2.Picture.PNG.Canvas,rect(0,0,100,100));" scheinbar gar nichts passiert.
Hm... anderseits ... doch, dachte ich hätte auch dies schon mal probiert? Aber da ich viele Varianten probiert habe, bin ich vielleicht durcheinander gekommen.

Aber es ist leider viel langsamer als wenn ich das ganze vorher per Pixel kopiere, und dann dies wiederum vom 3. Image ins Ziel-Image kopiere.
Also das kann so auch nicht bleiben.
Lazarus 2.2.0 / FP 3.2.4

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: [gelöst?] Suche Bild-Kopierbefehl, der Bild direkt kopie

Beitrag von pluto »

Wen ich dann Grafik hernehme (Image2.Picture.PNG - glaube, war es dann), fügt er mir aber dann das Ganze Bild verkleinert ein.

Ohne Erfolg. Der mag komischerweise kein Canvas, was mich wundert. Weil ich kann mich erinnern, dass es schon mal woanders mit Erfolg mittels Canvas verwendet habe? Aber er meckert was davon, dass Canvas und Grafic nicht zusammen passt.

Du musst einfach Image2.Picture bzw. image2.picture.bitmap (habe ich jetzt nicht ausprobiert).

Mir geht es NICHT um das anpassen! Sorry für die heftige Klarstellung, aber sonst gibt es, ehe ich mich versehe, nur noch Vorschläge dazu. Sondern um das Kopieren geht es mir. Später will ich auch umgekehrt kopieren, bzw. kleine Teile aus großem Bild in andere große Bild usw. usf.

nun das wundert mich aber:

Dann liegt irgendwo anders ein Fehler vor? Oder vielleicht hätte ich auch einfach mehr Daten dazu nennen sollen? Also das Image/Bild, von dem ich kopieren will, ist in meiner Testversion ca. 4000x4000 groß. Die Image-Komponente wo es rein kopiert werden soll, ist nur 100x100 groß

Das schreibtst du ein Post weiter oben.
Also möchtest du es doch verkleinern, oder verstehe ich hier was völlig falsch?

Image1.Canvas.CopyRect(rect(0,0,100,100),Image2.Picture.PNG.Canvas,rect(0,0,100,100));

Probiere mal statt png.canvas bitmap.canvas....
MFG
Michael Springwald

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: [gelöst?] Suche Bild-Kopierbefehl, der Bild direkt kopie

Beitrag von Erwin »

Habe alle Formate jetzt durchprobiert. Es scheint, dass das PNG-Format, welches auch mein eingefügtes Bild hat, am besten geeignet ist. Zum einen Stimmt dies überein, und zum anderem dauert es mit anderen Formaten noch etwas länger. Leider.

Nein, das gefällt mir alles gar nicht. Das dauert einfach zu lange.
Lazarus 2.2.0 / FP 3.2.4

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [gelöst?] Suche Bild-Kopierbefehl, der Bild direkt kopie

Beitrag von Mathias »

Nein, das gefällt mir alles gar nicht. Das dauert einfach zu lange.

Wieso wurde dann der Thread als gelöst markiert ?

Ich habe folgenden Code getestet, hier wird von Image1 --> Image2 kopiert.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  r0:TRect;
begin
  r0 := Rect(10, 10, 100, 100);
  Image2.Canvas.CopyRect(r0, Image1.Canvas, r0);
end


Noch eine Variante:

Code: Alles auswählen

uses
  LCLIntf, LCLType
....
 
  StretchBlt(
    Image2.Canvas.Handle, 10, 10, 90, 90,
    Image1.Canvas.Handle, 10, 10, 90, 90, SRCCOPY);

CopyRect ruft intern auch StretchBlt auf.

Eigentlich müsste es doch auch eine Funktion geben, welche ohne Stretch/skalieren funktioniert. Eine Skalierung braucht doch sehr viel Zeit oder ?
Oder ist StetchBlt etwa Hardware beschleunigt ?
Es kann ja nicht sein, das man auf RawImage.Data ausweichen muss. :roll:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: [gelöst?] Suche Bild-Kopierbefehl, der Bild direkt kopie

Beitrag von pluto »

Eigentlich müsste es doch auch eine Funktion geben, welche ohne Stretch/skalieren funktioniert. Eine Skalierung braucht doch sehr viel Zeit oder ?

Würde ich auch behaupten, wobei um eine Skalierung geht es ja scheinbar nicht, obwohl er davon geschrieben hatte....
*Verwirrt*....

Oder ist StetchBlt etwa Hardware beschleunigt ?

Ich glaube, dass ist nur eine System Funktion. Könnte aber sein, dass es unter Windows so ist, wer weiß was GDI bzw. GDI+ davon macht?

Du kannst auch direkt Bitblt aufrufen(ich glaube so hieß die Funktion) ist in der Unit "LCLIntf" drin.
Vielleicht ist das besser? Der Aufruf ist aber nicht ganz so leicht...
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [gelöst?] Suche Bild-Kopierbefehl, der Bild direkt kopie

Beitrag von Mathias »

Du kannst auch direkt Bitblt aufrufen


Dies könnte dies schnellste Methode sein, da nicht skaliert wird.

Code: Alles auswählen

  BitBlt(
    Image2.Canvas.Handle, 10, 10, 90, 90,
    Image1.Canvas.Handle, 10, 10, SRCCOPY);


ist in der Unit "LCLIntf" drin.
Ist am gleiche Ort versteckt wie StrechBlt.

Der Aufruf ist aber nicht ganz so leicht...
Ein wenig einfacher als StrechBlt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: [gelöst?] Suche Bild-Kopierbefehl, der Bild direkt kopie

Beitrag von Erwin »

@ Pluto, das mit dem Verkleinern und Vergrößeren bezog sich auf die Quell-Image-Komponente. Diese enthält ein Bild von 4000x4000, sehen tut man von der Image/Bild selbst nur 50x50 (also Breite mal Höhe - ohne Anpassung/Stretch). Später, wenn alles klappt, soll es auch unsichtbar werden. Weil es sonst nur stört.

@ Mathias, ob direkt mit 'Rect(0,0,100,100)' oder als Variable r0 mit gleichen Inhalt spielt keine Rolle. Beides geht nicht.
Nur mit Picture und Bildformat zwischen Image und Canvas geht. Und dort spielt es leider keine Rolle, ob die Koordinaten direkt oder per Variable eingetragen werden.
Das mit dem BltBlt war das andere, was mir beim erstellen nicht so im Detail mehr einfallen wollte, und klappt (wie bereits erwähnt) ebenfalls nicht. Bzw. nicht so ohne weiteres, also nicht ohne Picture.PNG.


Gelöst (mit Fragezeichen) deshalb: Weil inzwischen wir ja heraus bekommen haben, wie es geht. In dem man eben von der Quell-Image direkt das Picture inklusive Bildformat anspricht.
Anderseits dauert es aber 1-2 Sekunden lang. Zumindest kommt es mir, je öfter ich es teste, doch nicht mehr so lange wie zuvor vor.
Ist mir aber dennoch noch zu langsam, weil dann immer wieder eben diese Zeit lang auf das Programm dann warten müsste.


MacWomble hat geschrieben:Mir scheint, du müsstets das was du willst auf Dateiebene machen. Dass canvas.copyrect alles was auf der Zeichenfläche (canvas) ist kopiert, sagt ja schon die Logik.

Image <> Canvas!

Du kannst das Image auf den Canvas zeichnen lassen ...

Was sehr lange dauert, und auf ein und demselben nicht so ohne weiteres geht.
Gibt es eine Möglichkeit, Bilder direkt auf Canvas zu laden (beim erstellen des Programms)?
Lazarus 2.2.0 / FP 3.2.4

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: [gelöst] Suche Bild-Kopierbefehl, der Bild direkt kopier

Beitrag von pluto »

Ist mir aber dennoch noch zu langsam, weil dann immer wieder eben diese Zeit lang auf das Programm dann warten müsste.

Du könntest das Bild innerhalb von einem extra Thread kopieren, dann kann man das Programm weiter nutzen und es würde nicht so auffallen.

Gibt es eine Möglichkeit, Bilder direkt auf Canvas zu laden (beim erstellen des Programms)?

Klar, lade das Bild direkt in das TImage rein.... dann dauert aber das kompilieren länger(nehme ich an).
MFG
Michael Springwald

Antworten