Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Linien auf Canvas unterschiedlich breit dargestellt? (https://www.delphipraxis.net/170846-linien-auf-canvas-unterschiedlich-breit-dargestellt.html)

loirad 5. Okt 2012 12:18

Linien auf Canvas unterschiedlich breit dargestellt?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo liebe Community,

ich hab ein kleines Problem mit dem Canvas auf Images. Ich berechne die Breite der Linie, bzw. wie oft die Linie nebeneinander dargestellt werden soll (in einer for Schleife) so:

Delphi-Quellcode:
breite:=round((Bild.Picture.Bitmap.Width*Bild.Picture.Bitmap.Height)*2*0.0000001);
Das wird dann so gezeichnet:

Sekrechte Linien
Delphi-Quellcode:
 for i:=(<Ein bestimmter Wert>) to ((<Ein bestimmter Wert>)+breite) do
  begin
   Bild.Picture.Bitmap.Canvas.MoveTo(i,0);
   Bild.Picture.Bitmap.Canvas.LineTo(i,Bild.Picture.Bitmap.Height);
  end;
Waagerechte Linien
Delphi-Quellcode:
 for i:=(<Ein bestimmter Wert>) to ((<Ein bestimmter Wert>)+breite) do
  begin
   Bild.Picture.Bitmap.Canvas.MoveTo(0,i);
   Bild.Picture.Bitmap.Canvas.LineTo(Bild.Picture.Bitmap.Width,i);
  end;
Das Resultat ist im Anhang!

Jetzt habe ich versucht zu der Breite eine bestimmte Zahl zu addieren (z.B. 5) dann sieht es so aus, wie in dem 2. Bild im Anhang!

Wo liegt der Fehler?

Liebe Grüße
loirad

PS.: lasst euch nicht von dem roten Quadrat irritieren, das ist für dieses Problem unwichtig!

Edit: Vielleicht sollte ich noch erwähnen, dass alle 4 Linien mit der gleichen Breite aufgerufen wurden!

Helmi 5. Okt 2012 12:21

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Hallo,

ich versteh jetzt noch nicht ganz dein Problem.

Du hast die Breite um 5 Pixel erweitert und die Striche schauen dementsprechend aus - ich seh jetzt noch keinen Fehler

loirad 5. Okt 2012 12:22

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Der untere waagerechte Strich ist dünner dargestellt, als alle anderen Striche!
(Oder habe ich irgendwie einen Knick in der Optik :?:)

DeddyH 5. Okt 2012 12:25

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Wo ist denn dieser Strich im ersten Bild? Ich verstehe nicht ganz, was Du vorhast, scheint mir.

loirad 5. Okt 2012 12:28

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Er ist nicht dargestellt! Das ist ja das Problem! Vielleicht noch was zum Programm an sich:

Es ist ein Image im Formular mit der Größe 500*500. Das Bild ist größer als 500*500 und wird deshalb proportional verkleinert (über den Objektinspektor).

Helmi 5. Okt 2012 12:31

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Zitat:

Zitat von DeddyH (Beitrag 1185884)
Wo ist denn dieser Strich im ersten Bild? Ich verstehe nicht ganz, was Du vorhast, scheint mir.

Ich glaub wir brauchen beide nen Augenarzt-Termin - ich seh den nämlich auch nicht. (Brille putzen half auch nicht)

Kann es sein, dass die Breite für den unteren Strich falsch berechnet wird?
Sprich - wenn die vorgebene Breite kleiner deiner 5 z. B. ist, dann kommt als berechneter Wert ein Wert null oder kleiner raus und bei einem drauf gerechneten Wert von 5 kommt ein berechneter Wert von 3 oder was raus?

Helmi 5. Okt 2012 12:33

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Zitat:

Zitat von loirad (Beitrag 1185886)
Er ist nicht dargestellt! Das ist ja das Problem! Vielleicht noch was zum Programm an sich:

Lass dir doch mal den Wert von deiner Variablen "breite" einfach mal ausgeben (Label, ShowMessage, ...)
Vielleicht wird der ja mal null

loirad 5. Okt 2012 12:38

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Ich pack mal n Stückchen vom originalen Quelltext ran:

Delphi-Quellcode:
breite1:=round((Bild1.Picture.Bitmap.Width*Bild1.Picture.Bitmap.Height)*2*0.0000001)+5;
breite2:=round((Bild2.Picture.Bitmap.Width*Bild2.Picture.Bitmap.Height)*2*0.0000001)+5;
  if x1<x2 then
   begin
    for i:=(x2-x1) to ((x2-x1)+breite2) do
     begin
      Bild2.Picture.Bitmap.Canvas.MoveTo(i,0);
      Bild2.Picture.Bitmap.Canvas.LineTo(i,Bild2.Picture.Bitmap.Height);
     end;
   end;
  if x1>x2 then
   begin
    for i:=(x1-x2) to ((x1-x2)+breite1) do
     begin
      Bild1.Picture.Bitmap.Canvas.MoveTo(i,0);
      Bild1.Picture.Bitmap.Canvas.LineTo(i,Bild1.Picture.Bitmap.Height);
     end;
   end;
  if Bild1.Picture.Bitmap.Width-x1<Bild2.Picture.Bitmap.Width-x2 then
   begin
    for i:=(x2+(Bild1.Picture.Bitmap.Width-x1)) to ((x2+(Bild1.Picture.Bitmap.Width-x1))+breite2) do
     begin
      Bild2.Picture.Bitmap.Canvas.MoveTo(i,0);
      Bild2.Picture.Bitmap.Canvas.LineTo(i,Bild2.Picture.Bitmap.Height);
     end;
   end;
  if Bild1.Picture.Bitmap.Width-x1>Bild2.Picture.Bitmap.Width-x2 then
   begin
    for i:=(x1+(Bild2.Picture.Bitmap.Width-x2)) to ((x1+(Bild2.Picture.Bitmap.Width-x2))+breite1) do
     begin
      Bild1.Picture.Bitmap.Canvas.MoveTo(i,0);
      Bild1.Picture.Bitmap.Canvas.LineTo(i,Bild1.Picture.Bitmap.Height);
     end;
   end;


  if y1<y2 then
   begin
    for i:=(y2-y1) to (y2-y1+breite2) do
     begin
      Bild2.Picture.Bitmap.Canvas.MoveTo(0,i);
      Bild2.Picture.Bitmap.Canvas.LineTo(Bild2.Picture.Bitmap.Width,i);
     end;
   end;
  if y1>y2 then
   begin
    for i:=(y1-y2) to (y1-y2+breite1) do
     begin
      Bild1.Picture.Bitmap.Canvas.MoveTo(0,i);
      Bild1.Picture.Bitmap.Canvas.LineTo(Bild1.Picture.Bitmap.Width,i);
     end;
   end;
  if Bild1.Picture.Bitmap.Height-y1<Bild2.Picture.Bitmap.Height-y2 then
   begin
    for i:=(y2+(Bild1.Picture.Bitmap.Height-y1)) to ((y2+(Bild1.Picture.Bitmap.Height-y1))+breite2) do
     begin
      Bild2.Picture.Bitmap.Canvas.MoveTo(0,i);
      Bild2.Picture.Bitmap.Canvas.LineTo(Bild2.Picture.Bitmap.Width,i);
     end;
   end;
  if Bild1.Picture.Bitmap.Height-y1>Bild2.Picture.Bitmap.Height-y2 then
   begin
    for i:=(y1+(Bild2.Picture.Bitmap.Height-y2)) to ((y1+(Bild2.Picture.Bitmap.Height-y2))+breite1) do
     begin
      Bild1.Picture.Bitmap.Canvas.MoveTo(0,i);
      Bild1.Picture.Bitmap.Canvas.LineTo(Bild1.Picture.Bitmap.Width,i);
     end;
   end;
x1,x2,y1,y2 sind die Koordinaten von 2 Punkten (jeweils einer in einem Bild).
Und dann soll von diesen Punkten aus in alle 4 Richtungen der kleinste Abstand zur Wand gemessen werden und diese Wand in das größere Bild als Strich gemalt werden.

Helmi 5. Okt 2012 12:40

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Hast du dich durch deinen Code schon mal durchgedebuggt?
Und dir auch mal die Werte angeschaut?

loirad 5. Okt 2012 12:42

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Eigentlich schon ...
Auch rein vom Logischen her - die Breite ist ja immer gleich breit...

himitsu 5. Okt 2012 12:47

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Und dir ist dabei noch nicht aufgefallen, daß alle Linien 1 Pixel zu breit sind?

Denn richtig wäre ja wohl
Delphi-Quellcode:
for i := x to x + breite - 1 do
und nicht
Delphi-Quellcode:
for i := x to x + breite do
.

10 bis 10+2 = 10 bis 12 = 10, 11 und 12 = 3



Wenn du mal direkt auf ein TPaintBox.Canvas (oder Dergleichen) zeichnen würdest, dann die Form und die IDE nebeneinander legst, dann kannst du den Code Zeile für Zeile debuggen und siehst direkt was da genau passiert.

p80286 5. Okt 2012 12:48

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Ich denke mal, daß Du durchaus richtig siehst, nur wenn man Dein Bild (das zweite) vergrößert, dann sieht man einen Farbverlauf, der u.U. ein Strich sein könnte.
Wenn Du also die Ergebnisse Deines Programms beurteilen willst, solltest Du mit BMP arbeiten. JPG ist ganz klar nicht zu empfehlen.
(vielleicht ist ja auch die komprimierung zu hoch gewählt....)

Gruß
K-H

Helmi 5. Okt 2012 12:50

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Was für Werte bekommst du denn für "breite1" und "breite2", einmal ohne und einmal mit den 5?

Wo wird eigentlich die Breite für Canvas gesetzt?

loirad 5. Okt 2012 13:02

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Zitat:

Wenn du mal direkt auf ein TPaintBox.Canvas (oder Dergleichen) zeichnen würdest, dann die Form und die IDE nebeneinander legst, dann kannst du den Code Zeile für Zeile debuggen und siehst direkt was da genau passiert.
Jup werd ich gleich mal machen!

Edit: Er läuft jede for-Schleife genau 7 Mal (in dem Beispielbild) durch! Jedoch erscheint die untere horizontale Linie erst beim 3. Durchlauf, die anderen schon beim 2.! Ein Anzeigefehler?

Zitat:

Ich denke mal, daß Du durchaus richtig siehst, nur wenn man Dein Bild (das zweite) vergrößert, dann sieht man einen Farbverlauf, der u.U. ein Strich sein könnte.
Das ist nur ein Bildschirmfoto! Ich seh es hier aber auf meinem Bildschirm sehr deutlich, dass es einen Dickenunterschied gibt!

Zitat:

Was für Werte bekommst du denn für "breite1" und "breite2", einmal ohne und einmal mit den 5?
Das ist von Bild zu Bild unterschiedlich -
in diesem Fall bekomme ich für breite1: 6 bzw 1 und für breite2: 5 bzw 0

Zitat:

Wo wird eigentlich die Breite für Canvas gesetzt?
Welche Breite? Was meinst du?

Helmi 5. Okt 2012 13:12

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Zitat:

Zitat von loirad (Beitrag 1185905)
Zitat:

Wenn du mal direkt auf ein TPaintBox.Canvas (oder Dergleichen) zeichnen würdest, dann die Form und die IDE nebeneinander legst, dann kannst du den Code Zeile für Zeile debuggen und siehst direkt was da genau passiert.
Jup werd ich gleich mal machen!

Edit: Er läuft jede for-Schleife genau 7 Mal (in dem Beispielbild) durch! Jedoch erscheint die untere horizontale Linie erst beim 3. Durchlauf, die anderen schon beim 2.! Ein Anzeigefehler?


Auf welche Position(en) wird denn beim 1. und 2. Durchlauf gezeichnet?

Zitat:

Zitat von loirad (Beitrag 1185905)
Zitat:

Was für Werte bekommst du denn für "breite1" und "breite2", einmal ohne und einmal mit den 5?
Das ist von Bild zu Bild unterschiedlich -
in diesem Fall bekomme ich für breite1: 6 bzw 1 und für breite2: 5 bzw 0

Was ist wenn null rauskommt?


Zitat:

Zitat von loirad (Beitrag 1185905)
Zitat:

Wo wird eigentlich die Breite für Canvas gesetzt?
Welche Breite? Was meinst du?

Ich vermiss irgendwo die Angabe:
Delphi-Quellcode:
Bild.Picture.Bitmap.Canvas.Pen.Width := 1;
Sprich dein Malstift malt 1 Pixel breit

himitsu 5. Okt 2012 13:14

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Ist das Bild skaliert?

Die Skalierung im TImage ist schnell, aber "schlechter".
Beim vergrößern werden ganze Zeilen doppelt gemalt und beim Verkleinern einfach weggelassen.

loirad 5. Okt 2012 13:28

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Zitat:

Auf welche Position(en) wird denn beim 1. und 2. Durchlauf gezeichnet?
Das wird nicht angezeigt, da das Bild skaliert ist.

Zitat:

Was ist wenn null rauskommt?
Dann wird es, wie im 1. Bild nicht gemalt!

Zitat:

Ich vermiss irgendwo die Angabe:
Bild.Picture.Bitmap.Canvas.Pen.Width := 1; Sprich dein Malstift malt 1 Pixel breit
Das kannte ich noch garnicht:oops: - ich male dicker mit der for-Schleife

Zitat:

Ist das Bild skaliert?

Die Skalierung im TImage ist schnell, aber "schlechter".
Beim vergrößern werden ganze Zeilen doppelt gemalt und beim Verkleinern einfach weggelassen.
Ja das Bild ist skaliert - wie umgehe ich das mit dem Weglassen? - Das wird wohl der Fehler sein, dass wichtige markierte Linien weggelassen werden!

DeddyH 5. Okt 2012 13:39

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Dann skalier die Grafik doch selbst mit StretchBlt, setz vorher den Mode auf HALFTONE und setz Stretch im Image auf false. Das wird noch mein Lieblinkslink: StretchGraphic :lol:

loirad 5. Okt 2012 13:48

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
@DeddyH: Das ist mir zu hoch.

@all: Kann man auch direkt auf die Imagekomponente malen (also so, dass bei einer 500*500 Komponente ein Punkt in (250,250) bei jedem Bild in der Mitte der Komponente ist? Wenn ja wie?

DeddyH 5. Okt 2012 13:52

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Du brauchst doch nur 4 Parameter: Quell- und Zielgrafik (kann auch dieselbe sein) sowie maximale Breite und Höhe, Smooth ist per default true. Was ist daran zu hoch?

[edit] Ich habe mal eine Demo erstellt, die eine Bitmap erzeugt und im Speicher hält, zum Zeichnen eine Kopie dieser Bitmap erstellt, auf dieser herummalt, das dann skaliert und in einem Image darstellt. Der Code ist nicht frei von DRY, aber darauf kam es mir jetzt nicht an. [/edit]

Popov 5. Okt 2012 15:13

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
@loirad

Jetzt mal unabhängig des Fehlers, JPG Bilder sind das schlechteste Format das man zu Darstellung einer dünnen Linie wählen kann. JPG verfälschen Pixel, bzw. stellen sie nicht korrekt dar. Besser ist GIF (aber nur bis 256 Farben) oder PNG. Bei einer JPG kann eine 1 Pixel dicke Line schn mal paar Pixel dick sein.

Das nur so nebenbei.

Popov 5. Okt 2012 16:56

AW: Linien auf Canvas unterschiedlich breit dargestellt?
 
Ich hab mir jetzt noch mal die ersten Bilder genauer angesehen (hätte ich gleich machen sollen) und kann dir sagen, dass das normal ist und kein Fehler.

Dieser Effekt kommt bei "harter" Skalierung vor, vor allem wenn ungerade skaliert wird. Du mußt dir das so vorstellen

####000####000####000####000 //volle Zeichen

##0#0#0##0 //jedes dritte Zeichen wird beachtet

Du hast oben ein Muster, vier Rauten, drei Nullen usw. Stell dir vor die Rauten sind schwarze Pixel einer Grafik. Jetzt soll das auf 1/3 skaliert werden. Also macht sich die Skalierfunktion das Ganze sehr einfach - es beachtet nur jeden dritten Pixel. Das führt dazu, dass durch die ungerade Skalierung das gleichmäßige Muster ungleichmäßig wird.

Genauso ist es bei "harter" Skalierung von Bildern, einige Pixel werden einfach nicht beachtet, dh. sie werden unterschlagen.

Lösung: DeddyH hat dir den Tipp mit der weichen Skalierung genannt. Die funktioniert etwas anders. Hier werden die Pixel nicht unterschlagen, sondern aus allem Pixeln wird eine Art Mittelwert gebildet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:11 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