Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#4

Re: Bereich eines Images zoomen

  Alt 14. Okt 2006, 21:53
Hi,
ich muss nochmals Kritik üben. Bitte nicht falsch verstehen, man erkennt ja deutlich den Fortschritt! Aber es soll ja immer noch ein Tutorial sein oder gar in die Codelib kommen, deshalb sollte die Qualität des Beitrags entsprechend hoch sein.

Also erstmal ist die Rechtschreibung an einigen Stellen etwas, nun ja (z.B. Fläsche). Wichtiger sind aber die konzeptuell nicht ganz stimmigen Punkte:

Zitat von Neutral General:
Delphi-Quellcode:
TForm1 = class(TForm)
   ...
  public
   IsDown: Boolean;
   P: TPoint;
end;
Wer möchte kann die Variablen natürlich auch global deklarieren und die Benennung ist natürlich auch nur ein Vorschlag
P als Variablenname? P ist in Delphi eigentlich ein Standardpräfix für Zeiger. Aber an sich solltest du schon darauf achten, dass Namen für sich sprechen sollten. Wenn jmd. P liest kann das doch nun wirklich für alles stehen.... Das damit die Koordinaten eines Markierungsrechtecks (oder wie du es nanntest) gemeint ist, ich würde nicht darauf kommen.

Dann noch das mit den globalen Variablen, ganz böse. Du solltest dir ein Konzept überlegen, wenn du den Rest in einer Klasse kapselst, dann sollte die Variable auch zur Klasse gehören (das ist dann nämlich der Sinn einer Klasse) oder du verzichtest komplett auf die OOP und dann hast du natürlich auch keine Alternative zur globalen Variable.

Zitat von Neutral General:
Delphi-Quellcode:
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  IsDown := false;
  Image1.Picture.Bitmap.Canvas.Rectangle(Old.Left,Old.Top,Old.Right,Old.Bottom); // Das letzte gemalte Rechteck wegradieren
  Old := Rect(0,0,0,0); // Das alte Rechteck zerstören (wir haben brauchen keins zu diesem Zeitpunkt)
end;
Wie kommst du denn bitte auf die Idee, dass Rect(0, 0, 0, 0) irgendwas zerstört? Die Variable Old speichert jetzt nur ein Rechteck mit diesen Koordinaten, im Speicher liegt die immer noch und verbraucht auch genau so viel Speicher, wie sie mit anderen Werten belegen würde.

Zitat von Neutral General:
Also ich denke mal ich habe das meiste schon durch die Kommentare erklärt... Wer will kann ja die letze Zeile mal weglassen und gucken was passiert
Sag ich mal nicht viel zu...

Zitat von Neutral General:
Zuerst brauchen wir noch eine Variable vom Typ TRect. Nennt sie wie ihr wollt, ich nenne sie Rec

Erstmal wie auch eben brauchen wir die Koordinaten des Anfangspunktes wo der Benutzer die Maustaste runterdrückt.
Einfach im OnMouseDown Ereignise folgende beiden Zeilen ergänzen:
Ok, hatten wir die Koordinaten nicht so ganz am Anfang mal gehabt, mit dem P zusammen? Da wird doch irgendwann das Markierungsrechteck gezeichnet, wozu genau jetzt die zweite Variable?


Zitat von Neutral General:
Delphi-Quellcode:
  Rec.Bottom := y;
  Rec.Right := x;
  CorrectRect(Rec); // Rechteck korrigieren (procedure folgt)

  tmp := TBitmap.Create; // 'tmp' lokal als TBitmap deklarieren
  with tmp do
  begin
    Width := Image1.Picture.Bitmap.Width; // Niiiiemals vergessen *g*
    Height := Image1.Picture.Bitmap.Height;
    Canvas.CopyRect(Rect(0,0,Width,Height), // Hier erfolgt das eigentliche vergrößern
                    Image1.Picture.Bitmap.Canvas,
                    Rec);
    Image1.Picture.Bitmap := tmp; // Dem Bitmap von Image1 unser tmp Bitmap zuweisen.
    Free; // fertig (+ freigeben ;) )
  end;
Ok, du hast auch am Anfang gesagt, man könnte es mit einem Bitmap machen, hier setzt du aber wieder sehr statisch auf Image1, ginge alles schöner, wenn du Parameter verwenden würdest...
Dann noch das mit dem CopyRect, ich weiß nicht genau was passiert, wenn du hier mit falschem Pixelformat arbeitest. Wird das von CopyRect berücksichtigt? Immerhin übernimmst du nur die Größe der Quellbitmap, nicht deren PixelFormat.

Zitat von Neutral General:
Am besten ist es wenn man die Procedure als Methode von TForm1 deklariert aber eine herrenlose procedure geht natürlich auch
Na ja, am Besten ist hier sehr weit hergeholt. Schau dir mal dein eigentliches Ziel an, du möchtest etwas, was dir den Ausschnitt einer Bitmap vergrößert und anzeigt. An sich lässt sich das schon in mindestens zwei Probleme zerlegen. Das eine ist es einfach nur einen Ausschnitt einer Bitmap zu kopieren und zu vergrößern. Das andere wäre dann noch, wie man das ganze visualisiert. Wie man eine Bitmap anzeigt sollte soweit klar sein (Image), wie man mit einem Image dann noch einen Rahmen zeichnet ist ja Teil deines Tuts.

Aber wichtig ist hier, dass du für den ersten Teil (Vergrößerung eines Ausschnitts) nur den Ausschnitt (z.B. als Rechteck), eine Quell- und ggf. eine Zielbitmap brauchst. Die Zielbitmap kann natürlich auch erst in deine Prozedur erzeugt werden, aber auch das ist weniger wichtig. Wichtig ist, dass es an der Stelle egal ist, ob das Rechteck per Maus gezogen wurde oder Editfeld eingegeben.
Nebenbei hast du hier ein Problem völlig ignoriert. So kann deine Bitmap theoretisch um einiges größer sein als dein TImage. Dann stellst du einfach proportional und stretched auf True und siehe da, das Image zeigt eine gestauchte Bitmap an (alles wie gewünscht!). Wenn du jetzt aber einen Ausschnitt betrachten möchtest, dann solltest du die sehr viel größere Bitmap verwenden, da du hier natürlich auch viel mehr Details hast, allerdings musst du dann auch die Mauskoordinaten auf dem Image in Koordinaten auf der Bitmap umrechnen.

Ja, was die Anzeige angeht, so sehe ich dort nicht, warum man sich ernsthaft an ein Form1 binden muss? Auch hier gilt wieder, dass alles was benötigt wird ein Image ist. Nur mit diesem arbeist du weiter. Also wäre der richtige Schritt hier, dass du einen Nachfahren von TImage anlegst und dort alle nötige Implementierst. Dass dabei die Variablen public sind ist natürlich auch komplett sinnfrei, denn ausserhalb dieser Instanz wird sich keiner für diese Werte interessieren. Private wäre also angebracht und würde auch keine Einschränkung bedeuten (Nebenbei sollten alle Variablen immer private sein und ggf. öffentliche Properties den Zugriff regeln).

Das war's dann erstmal wieder.

Gruß Der Unwissende
  Mit Zitat antworten Zitat