Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Eigene Objekte -> PaintBox (https://www.delphipraxis.net/51530-eigene-objekte-paintbox.html)

mimi 14. Aug 2005 13:44


Eigene Objekte -> PaintBox
 
Hallo,
ich habe lange gesucht und leider nichts gefunden was mir wirklich weiter geholfen hätte :(

Ich möchte gerne eigene Delphi Zeichen objekte erstellen wie z.b. ein Kreis oder ein Stern.
Dazu habe ich mir ein kleines Paint geschrieben.
Das speichern geht schon nur das vergrößern der objekte geht leider nicht.

Das vergrößern wollte ich so machen
(hier etwas code denn ich heute geschrieben habe)
Delphi-Quellcode:
procedure FillPixel(sx,sy,zx,zy:Integer; PaintBox:TPaintBox);
var
  x,y:Integer;
begin
  for y:=sy to zy do begin
    for x:=sx to zx do begin
      PaintBox.Canvas.Pixels[x,y]:=clBlack;
    end;
  end;

end;

procedure TForm1.ObenObj(F:TFileName);
var
  i,x,y,fx,fy,ox,oy:Integer;
  l:TStringList;
begin
  ox:=-1; oy:=-1;
  if FileExists(f) = True then begin
    l:=TStringList.Create;
    l.LoadFromFile(f);
    fx:=2;
    fy:=2;

    for i:=0 to l.Count-1 do begin
      x:=StrToInt(GetToken(l.Strings[i],':',1));
      y:=StrToInt(GetToken(l.Strings[i],':',2));
//      PaintBox2.Canvas.Pixels[x,y]:=clBlack;

      if (ox > -1) and (oy > -1) then
        FillPixel(ox,oy,x *fx,y *fy,PaintBox2);
      ox:=x *fx;
      oy:=y *fy;
    end;
  end
  else
    ShowMessage('Dateinamen gibt es nicht !');
end;
doch leider geht FillPixel nicht so wie ich es mir vorgestellt habe. hier ein Bild ich würde gerne nur die umrahmung und nicht das Innere, das lieg an in der FillPixl funktion und zwar bei den For y schleifen.

turboPASCAL 14. Aug 2005 14:30

Re: Eigene Objekte -> PaintBox
 
Zitat:

Zitat von mimi
...doch leider geht FillPixel nicht so wie ich es mir vorgestellt habe. hier ein Bild ich würde gerne nur die umrahmung und nicht das Innere, das lieg an in der FillPixl funktion und zwar bei den For y schleifen.

:gruebel: Das habe ich jetzt nicht Verstanden, möchtest du nur einen Rahmen zeichnen ? Bild, was wo ?

Delphi-Quellcode:
procedure FillPixel(sx, sy, zx, zy: Integer; PaintBox: TPaintBox; Fill: Boolean);
begin
  PaintBox.Canvas.Pen.Color := clRed;
  PaintBox.Canvas.Brush.Color := clBlack;

  if Fill = True
    then PaintBox.Canvas.Brush.Style := bsSolid // ausmalen
    else PaintBox.Canvas.Brush.Style := bsClear; // nicht ausmalen

  PaintBox.Canvas.Rectangle( Rect(sx, sy, zx - sy, zy - sx) );
end;

mimi 14. Aug 2005 16:37

Re: Eigene Objekte -> PaintBox
 
Liste der Anhänge anzeigen (Anzahl: 1)
ich möchte folgendes:
ich male jetzt ein object z.b. ein Dreieck(sowas gibt es ja nicht als standart) und nun speichere ich dieses object ab und verkleire das das geht auch soweit.
Nun möchte ich es wieder öffnen aber vergrößert. und das geht leider nicht.
um deine frage zu beantworten:
Ja ich möchte nur die umrahmung selbst zeichnen bzw. was der user vorgeben hat.

das bild kommt hier

edit:
deine funktion macht leider nicht das was ich wollte: ich möchte kein rechtect oder sowas zeichnen sonder selbst ein eignes objekt schreiben bzw. zeichnen.

mimi 20. Aug 2005 21:04

Re: Eigene Objekte -> PaintBox
 
ich habe mich weiter mit dem problem befasst aber noch keine passende lösung finden können.
Egal was ich versucht habe: nichts hat funkitoniert. es wahren immer lücken zwischen den einzelen pixel was letzendlich auch logisch ist: wenn ich das bild doppelt so groß haben möchte wie es voher wahr muss ich ja jeden pixel ersteinmal * 2 nehmen(oder nicht?) und dann entstehen lücken die genau zwei pixel groß sind zwischen den einzelen pixel und das problem ist jetzt diese lücken zu füllen.

Es handelt sich dabei nur um Schwartzt weis Bilder

mimi 21. Aug 2005 11:23

Re: Eigene Objekte -> PaintBox
 
ich habe es heute mit diese porcedure versucht:
Delphi-Quellcode:
procedure SetPixel(x,y:Integer; Canvas1:TCanvas);
begin
  Canvas1.Pixels[x,y]:=clBlack;
end;

procedure TForm1.ObenObj(F:TFileName);
var
  i,x,y:Integer;
  l:TStringList;
  bild:TCanvas;
begin
  ox:=-1; oy:=-1;
  Bild:=TCanvas.Create;
  Bild.Brush:=TBrush.Create;

  if FileExists(f) = True then begin
    l:=TStringList.Create;
    l.LoadFromFile(f);

    for i:=0 to l.Count-1 do begin
      x:=StrToInt(GetToken(l.Strings[i],':',1));
      y:=StrToInt(GetToken(l.Strings[i],':',2));
      SetPixel(x,y,bild);
    end; // for
   PaintBox1.Canvas.StretchDraw(Rect(2,2,2,2),Bild.Brush.Bitmap);

  end // If
  else
    ShowMessage('Dateinamen gibt es nicht !');
end;
aber leider gibt er einen fehler:
Zitat:

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt CreateObject.exe ist eine Exception der Klasse EInvalidOperation aufgetreten. Meldung: 'Leinwand/Bild erlaubt kein Zeichnen'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------
den kann ich nicht nachvollziehen.
Meinziel ist es später das ich das bild mit der Maus vergrößern und Verkleinern kann.

Die bilder die ich damit vergrößern möchte enhalten nur kleine objekte wie z.b. Dreiece, Häuser, und soweiter. Das was bei delphi nicht dabei ist neben.

turboPASCAL 21. Aug 2005 11:41

Re: Eigene Objekte -> PaintBox
 
Besteht noch ein Zugriff auf die Zeichenfläche (Canvas) von einer anderen Routine ?

Verwende Delphi-Referenz durchsuchenTCanvas.Lock und Delphi-Referenz durchsuchenTCanvas.Unlock vor bzw. nach dem Zeichnen.

mimi 21. Aug 2005 13:51

Re: Eigene Objekte -> PaintBox
 
nein ! es besteht kein zugrief von einer andren zeichen funktion auser von setPixel !
du meisnt ich sollte vor dem aufruf von setpixel lock und danach wieder unlock machen ?

mimi 27. Aug 2005 19:14

Re: Eigene Objekte -> PaintBox
 
Liste der Anhänge anzeigen (Anzahl: 1)
ich habs in der lezten woche versucht und wier nicht hinbekommen der code sieht jetzt so aus:
Delphi-Quellcode:

procedure FillPixel(sx,sy,zx,zy:Integer; PaintBox:TPaintBox);
var
  x,y:Integer;
begin

 { for x:=sx to zx do begin
    for y:=sy to zy do begin
      PaintBox.Canvas.Pixels[x,y]:=clBlack;
    end;
  end;}

  x:=sx; y:=sy;
  while (x <= zx) or (y <= zy) do begin
    inc(x);
    inc(y);

    PaintBox.Canvas.Pixels[x,y]:=clBlack;
  end;
//  ShowMessage('OK');
end;

rocedure TForm1.ObenObj(F:TFileName);
var
  i,x1,y1,x2,y2,fx,fy,m:Integer;
  l:TStringList;
begin
  ox:=-1; oy:=-1; m:=0;

  if FileExists(f) = True then begin
    l:=TStringList.Create;
    l.LoadFromFile(f);
    fx:=2; fy:=2;

    for i:=0 to l.Count-1 do begin
      x1:=StrToInt(GetToken(l.Strings[i],':',1));
      y1:=StrToInt(GetToken(l.Strings[i],':',2));
      SetPixel(x1,y1,paintbox2);

      SetPixel(x1*fx,y1*fy,paintbox2);

      if i+1 <= l.Count-1 then m:=+1 else m:=0;

      if m = +1 then begin
        x2:=StrToInt(GetToken(l.Strings[i+m],':',1));
        y2:=StrToInt(GetToken(l.Strings[i+m],':',2));
        SetPixel(x2*fx,y2*fy,paintbox2);
        FillPixel(x1*fx,y1*fy,x2*fx,y2*fy,PaintBox3);
      end;
    end; // for

  end // If
  else
    ShowMessage('Dateinamen gibt es nicht !');
end;
der code sollte folgendes machen:
Wenn ich die pixle vergrößer ändert sich auch die Pos von den pixel, richtig ?
also der abstant wird größer und fillpixel sollt die lücken füllen. aber genau das passiert nicht er zeichnet ein komische 3D gebilde siehe anhang.

das schwarzte objekt ist das orgnial objekt(verkleinert da gestellt) das ganz rechte ist das neue objekte so sollte es aber nicht aussehen.

Khabarakh 27. Aug 2005 19:39

Re: Eigene Objekte -> PaintBox
 
Du musst für jedes Pixel auf der Paintbox aus den Daten der Stringlist errechnen, ob es gefärbt werden soll, oder du zeichnest für jeden Eintrag der Stringlist ein Rechteck:
Delphi-Quellcode:
//SetPixel(x1*fx,y1*fy,paintbox2);
FillPixel(x1 * fx, y1 * fy, (x1 + 1) * fx, (y1 + 1) * fx, Paintbox2);
Aber warum speicherst du die Pixel in einer Textdatei :gruebel: ? Warum nicht gleich das Bitmap speichern, oder noch besser (wenn ich mir deinen Screenshot mit deinen Funktionen ansehe): vektorbasiert?

mimi 27. Aug 2005 19:50

Re: Eigene Objekte -> PaintBox
 
es sind leider immer noch lücken zwischen den pixeln.
der hauptgrund warum ich keine bmp's nehme ist der das ich es mir so schön zurecht gedachte hatte das
und texttateien sind schön klein und können problemlos kompiermiert werden *G*
ist eigentlich kein problem dastellen sollte, aber leider gibt es unerwartet probleme.

vektorbasiert:
wo ist da der genaue unterschied zu pixelbasieren ?

tigerman33 28. Aug 2005 10:10

Re: Eigene Objekte -> PaintBox
 
Vektorbasiert heißt, du gibst nur noch Startpunkt und Richtung+Länge vor. Das spart vor allem bei einfachen Bildern, die hauptsächlich aus langen, geraden Linien bestehen bannig Speicherplatz.

Apropos Speicherplatz: Durch das Speichern in einer Textdatei verschenkst du im Vergleich zu z.B. einer bmp letztendlich mehr Platz, als du anschließend mit dem Komprimieren wieder herausholen kannst. Erst recht, wenn die Bitmap auch komprimiert ist. Momentan schreibst du ja trotz allem einfach Zahlen in die Datei, nur halt über den Umweg mit ASCII-Zeichen. Zum Vergleich: Ein Byte braucht normalerweise (Überraschung) 1 Byte Speicherplatz :shock: , in ASCII-Zeichen schon bis zu 3.

Khabarakh 28. Aug 2005 10:36

Re: Eigene Objekte -> PaintBox
 
Das ist wirklich gut :mrgreen: .
Code:
Speicherverbrauch für ein Pixel

Monochrombitmap:
1 Bit                                                                                   = 0,125 Byte
 
Textdatei:
(Koordinaten mit 1 bis 4 Stellen)
X-Koordinate + Doppelpunkt + Y-Koordinate + CRLF = 1-4 Byte + 1 Byte + 1-4 Byte + 2 Byte = 5-11 Byte
Da in der Textdatei nur die schwarzen Pixel gespeichert werden, teilen wir fairerweise noch durch 2, somit kommen wir auf ein Verhältnis von 1 : 20 oder 1 : 44 :zwinker: .

Wenn du ein Format mit hoher verlustfreier Komprimierung suchst, nimm PNG, oder speicher es wie gesagt vektorbasiert.

GuenterS 28. Aug 2005 11:15

Re: Eigene Objekte -> PaintBox
 
Zitat:

Zitat von tigerman33
Zum Vergleich: Ein Byte braucht normalerweise (Überraschung) 1 Byte Speicherplatz :shock: , in ASCII-Zeichen schon bis zu 3.

Nur mal so als Anmerkung, wenn Du das Ascii Zeichen "A" speichern möchtest hat das den Byte Wert 65, du speicherst damit auch nur 1 Byte und keine 3... Wie kommst du auf 3? Jedes Zeichen des Ascii Zeichensatzes besteht aus einem einzigen Byte. Wenn Du 3 speicherst dann hast Du auch 3 zugehörige Ascii Zeichen.

Khabarakh 28. Aug 2005 11:30

Re: Eigene Objekte -> PaintBox
 
Zitat:

[...] in ASCII-Zeichen [...]
Code:
"255" = "2" + "5" + "5" = 3 Byte
Gut, nicht sehr eindeutig :wink: .

GuenterS 28. Aug 2005 13:13

Re: Eigene Objekte -> PaintBox
 
Zitat:

Zitat von Khabarakh
Zitat:

[...] in ASCII-Zeichen [...]
Code:
"255" = "2" + "5" + "5" = 3 Byte
Gut, nicht sehr eindeutig :wink: .

Aja, ich würde dazu sagen, wenn man eine Zahl als String abspeichert, weil deine vorherige Aussage den Schluß zuließ, dass Du sagen wolltest ein Ascii Zeichen würde 3 Bytes brauchen.

tigerman33 28. Aug 2005 15:36

Re: Eigene Objekte -> PaintBox
 
Tschuldigung. War ein bisschen mies ausgedrückt. Ich gelobe Besserung! :angel2:

mimi 28. Aug 2005 15:56

Re: Eigene Objekte -> PaintBox
 
naja mir ging es eigentlich nicht um den speicherverbrauch sondern darum das die größe unbekannt bleiben sollte, weil sonst müsste ich ja vohrer die größe festlegen.

Aber evtl. habt ihr recht und ich sollte mein vorhaben mit einer BMP verzuchen. Dann könnte ich die objekte auch mit Paint zeichnen *G* und in das Programm einbinden.
aber ich wollte schon gerne wissen warum meine funktion nicht geht... hat da einer eine kleine idee ?


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