In gezoomtes TImage pasten



  • Ich paste in ein PasteImage (MarkBase), das äquavilent zum TImage gezoomt wird. Das verschieb ich dann an die Zielposition und will dessen Picture dort ins TImage einfügen.

    TRect DRect;
        DRect.Left = MarkBase->Left-Image->Left;
        DRect.Top = MarkBase->Top-Image->Top;
        DRect.Right = MarkBase->Left+MarkBase->Width-Image->Left;
        DRect.Bottom = MarkBase->Top+MarkBase->Height-Image->Top;
        Image->Canvas->CopyRect(DRect, MarkBase->Canvas, MarkBase->ClientRect);
    

    Der Fehler ist, ich hab die Koordinaten nicht umgerechnet, das Einfügen erfolgt an der falschen Position.

    Seh ich den Wald nicht oder hab ich wirklich ein Problem? Das DRect liegt mit seinen Koordinaten auf dem TImage. Picture->Grapgic hat keine Positionskoordinaten, nur Höhe und Breite. Die Positionsberechnung bezieht sich auf die Form. Wenn es da nichts besonderes gibt, bring ich das nie zusammen. Mit dem Vergrößerungsfaktor kann ich hier erst mal keinen Blumentopf gewinnen - muß ihn aber auf jeden Fall mit einbeziehen.

    Hide() setzen, auf 100% zoomen, pasten, zurückzoomen, sichtbar machen erscheint mir sehr unelegant - und ist auch nicht üblich. Wie ließe sich die Nuß knacken?



  • hallo,

    kollege tut mir leid aber ich weiß nicht was du meinst. du mußt dir immer vor augen halten, das unbeteiligte lange nicht so gut in deinem projekt eigearbeitet sind wie du selber und wenn man dann deinen beitrag nach dem zweiten durchlesen immer noch nicht so recht verstanden hat, dann scheißt man halt drauf...

    mfg
    murphy



  • Sorry @murhpy, danke für dein offenes Wort. Ich versuchte, die Situation so anschaulich wie möglich zu beschreiben. Ist also nicht gelungen.

    Der Fehler ist, ich hab die Koordinaten nicht umgerechnet, das Einfügen erfolgt an der falschen Position.

    Das sagt, ich zoome das TImage, passe aber dessen Picture->Graphic nicht an die neue Größe des TImage an. Wenn ich nun an der Mausposition zeichne oder wie hier in einem logischen TRect einfüge, erfolgt die Operation im Bild an einer entfernten Position. Je höher der Zoomfaktor, desto größer die Abweichung.

    Zeichenkoordinaten beziehen sich auf das TImage, man kann sie physikalisch umrechnen. Die Kordinaten eines TRect beziehen sich aber auf die Form. Das TImage liegt in unterschiedlicher Position zu den Außenkanten der Form (in einer ScrollBox gezoomt und zentriert). Ich darf aber nur die Koordinaten innerhalb des TImage umrechnen. Außerhalb stimmen sie ja.

    Klar, der Code funktioniert nur bei 100% wie gewünscht. Ich möchte nun die Koordinaten des TRect so umrechnen, daß das Pasten auch bei Zoomfaktoren physikalisch richtig erfolgt. Ist jetzt klar, was ich meine oder braucht es noch Infos?



  • Hi Omega-X 🙂

    Freut mich, dass Du noch mit dem ImageScroller arbeitest. 🙂

    Nenn 'mal genauer, was Du vorhast:
    - Eine Graphic vom Clipboard in das FImage an spezielle Position kopieren?

    - Was ist PastImage genau, was enthaelt das??

    (Villeicht ist das hinzubekommen.) 😃



  • Hi DerAltenburger,

    klar bau ich weiter :p . Im vorhandenen Projekt optimier ich die Functionen, dann kann ich sie in den ImageScroller integrieren. Direkt in der Klasse bring ich die Übersicht noch nicht zusammen.

    Das Paste-Image ist ein TImage. Das leg ich Top/Left auf FImage ab, füg das Bild der Zwischenablage ein, dann zoom ich es mit dem gleichen Faktor wie das FImage.

    void __fastcall TPixi::PasteClick(TObject *Sender)
    {
        if(Clipboard()->HasFormat(CF_BITMAP))
        {
            MarkBase->Left = Image->Canvas->ClipRect.Left;
            MarkBase->Top = Image->Canvas->ClipRect.Top;
            MarkBase->AutoSize = true;
            MarkBase->Stretch = false;
            MarkBase->Show();
            MarkBase->Picture->Assign(Clipboard());
            MarkBase->AutoSize = false;
            MarkBase->Stretch = true;
            MarkBase->Width = MarkBase->Width*VFac;
            MarkBase->Height = MarkBase->Height*VFac;
        }
    }
    

    Dann wird es an die gewünschte Position verschoben, das TRect dort festgelegt und das Bild an der Stelle ins FImage eingefügt. (Also genau das, was man in einem Malprogramm braucht, verschieb- und positionierbares Pasten. 🙂 ).

    Jetzt knobel ich an der Koordinatenumrechnung für das TRect, mit welchem ich festleg, wo im FImage das Bild aus MarkBase eingefügt werden soll. Noch kein brauchbarer Ansatz.



  • Original erstellt von <Omega-X>:
    Ist jetzt klar, was ich meine oder braucht es noch Infos?

    Sorry Omega, aber du drückst dich derart aus, dass dich einfach kein Mensch versteht. Versuch mal, dich so auszudrücken, wie es ein kleines Kind machen würde - ohne hochtrabende Worte. Vielleicht geht es dann besser. Und: Gehe auf den Helfenden ein! Zum Beispiel wären Infos, wo sich die beiden Images befinden nicht übel.



  • ...also die Wortwahl isses. Da muß ich drauf achten. Danke, @WebFritzi.

    Eine TScrollBox nimmt den gesamten freien Clientbereich der Form ein. Darauf liegt zentriert das TImage, in dem gemalt (und eingefügt) wird. Bei kleineren Bildern nimmt das Image nie den ganzen Raum der ScrollBox ein und wird darin zentriert.

    Beim Pasten wird ein TImage Top/Left auf dem Arbeits-Image plaziert. Dahin paste ich von der zwischenablage. Dann kann das Paste-Image via Drag&Drop verschoben werden. Verschieben teilweise oder ganz über das Arbeits-Image hinaus ist möglich.

    Befindet sich das Paste-Image am gewünschten Platz, wird an dessen Platz ein TRect positioniert. Vom Paste-Image aus wird das Bild via CopyRect in das TRect im Arbeits-Image eingefügt.

    Da sowohl Arbeits-Image als auch paste-Image mit dem gleichen Faktor gezoomt sind, befindet sich das TRect am logischen Platz der Erstellung. Benötigt wird es aber am physikalischen Platz in der Picture->Graphic. Ich muß die Koordinaten umrechnen. Ich finde aber keinen Algor, der in jeder Situation richtig arbeitet. Das einzufügende Bild gelangt also nicht an den Platz, an den es soll.



  • Bis zum letzten Absatz ist dein Beitrag und deine Beschreibung völlig OK. So wünscht man es sich. Super, dachte ich. Nur dann der letzte Absatz. Was ist der "logische Platz" und der "physikalische Platz"??? Versuche, auf solche Blödsinns-Ausdrücke zu verzichten. Der Helfer hat so keine andere Wahl, als die Ausdrücke zu deuten und zu interpretieren. Ich interpretiere das mal so: Das Paste-Image befindet sich über dem Image genau dort, wo es sein soll. Nun soll der Inhalt des Paste-Images in das Image genau an dieser Stelle kopiert werden. Ist das so richtig?? Wenn ja, dann verstehe ich nicht, warum dein "Algorithmus" von oben (erster Beitrag) nicht funktioniert. Er muss funktionieren!
    Mir ist da noch was aufgefallen:

    Die Positionsberechnung bezieht sich auf die Form.

    Das Image befindet sich in einer ScrollBox, richtig? D.h., die Eigenschaften Left und Top beziehen sich auf die ScrollBox und nicht auf die Form.

    [EDIT] Jau, das muss der Fehler sein! Du musst darauf achten, dass das PasteImage und das Image das gleiche Parent haben - in diesem Falle die ScrollBox. [/EDIT]

    [ Dieser Beitrag wurde am 09.03.2003 um 13:21 Uhr von WebFritzi editiert. ]



  • Hi Omega-X

    Folgende Ueberlegung:

    Dein FImage wird z.B. mit VFac=0.5 angezeigt.
      Das 'gepastete' Image skalierst Du gleich.
      ->In Scrollbox (Am Bildschirm erscheinen beide in halber Groesse!!!
    
      Das 'gepastet' Image positioniers Du z.B. 50 Pixel weiter rechts (DX)
      und 100 Pixel tiefer (DY).
      ->Auf FImage- Inhalt bezogen macht das das Doppelte (VFac!!!) ;) 
        ->DRect->Left muss 2x50 =100 sein
        ->DRect->Top  muss 2x100=200 sein.
    
    :::Positionsdifferenzen muessen DURCH VFac DIVIDIERT werden!!!(typecast nach double nehmen!!! :D 
    
    :::Die Groessenskalierung muesste mit 1:1 OK sein (das machen die gezoomten Images!)
    


  • Ja, hab inzwischen auch gemerxt, die ScrollBox liefert als fensterorientierter Parent den Koordinatenbezug. Wußte ich noch nicht, das stört hier aber zT. kollossal. Die Berechnungen beziehen sich auf den sichtbaren Bereich der ScrollBox. Mit den Zeilen

    MarkBase->Left = Image->Canvas->ClipRect.Left;
    MarkBase->Top = Image->Canvas->ClipRect.Top;

    wird MarkBase Top/Left in der ScrollBox positioniert, nicht Top/Left über dem Image (versteh aber nicht, warum, die Anweisung scheint klar zu sein). Usw. Ich bekomm nie einen immer richtig arbeitenden Algor. Probs hab ich auch, die Strecken außerhalb und innerhalb des Image zu berechnen. Beim Wechsel der Vergrößerung kann ich ua. die Position den MarkBase-Image nicht halten.

    @WebFritzi, die Begriffe "logisch" und "physikalisch" hab ich aus dem Buch "C++ Builder3 im Team, C&L". Muß ich akzeptieren, daß die Begriffe nicht allgemein gebräuchlich sind, sorry.

    @DerAltenburger, die Methode, mit festen Werten je Faktor zu arbeiten, muß ich probieren. Das ist immer genau, eine Division nicht unbedingt. ... Hey, erst beim 2. Lesen seh ich, daß mit (DX) und (DY) alles fein normierbar aufgebaut werden kann. Ein Bedingungssatz statt der Division, das wird exakt. 🕶

    Du schlägst sogar double vor, nicht float? float sollte weit mehr können, als ich in einem (größeren) Bild benötige. Aber einfach mal checken... Aber s.O., ich seh so aus, als ob mir das viiieel besser gefällt. :p

    Bei 1:1 hab ich keine Probs.

    Ole, war dann auf eine andere Basislösung gekommen, bei der die Probs vermieden werden. Ich leg die beiden TImage's Image und MarkBase auf einem Panel ab. Das Panel paßt sich bei jeder ändernden Operation dem Image an. Damit hab ich einen eindeutigen Bezug für alle Operationen. Jetzt kann ich so scalieren, wie es auch beim Malen klappt. - Muß aber noch den Code gründlich durchgehen und alles anpassen. Ich denk, damit sollte ich aus dem Schneider sein, ich sag dann bescheid.

    <edit>Es wird wirklich interessant sein, wenn alles stimmt, aus dem Aufbaukomplex eine Kompo zu machen. Aber Operationen würde ich nicht mit reinnehmen. Nur die Methoden wie zB. Canvas->LineTo..., aber auch zB. die Synchronschaltung von FImage und FPanel, die wahlfreie Zentrierung/Positionierung in der Scrollbox, ZoomHandling usw.</edit>



  • MarkBase->Parent = ScrollBox;
    


  • @Webfritzi

    Tust Du ueberhaupt wissen tun ueber was fuerne Komponente hier diskutiert wird? 😃



  • Ja. Über deine tolle Komponente, du Angeber. 😉



  • Dann haeteste Dir Dein' vorletzten Beitrag sparen koennen! 😃

    PS: Den letzten auch! :p

    [ Dieser Beitrag wurde am 09.03.2003 um 22:44 Uhr von DerAltenburger editiert. ]



  • Wir hätten uns beide die letzten Beiträge sparen können, wenn du hier nicht so geheimnisvoll darüber reden würdest. Nun mal raus damit.



  • @WebFritzi

    Fuer Dich blinden Uhu nochmal langsaaaaaaaaam!:

    Lies den Beitrag 'Bild- Viewer Problem' von <GOMEZ> vom 2.3.2003 nochmal genau durch! Dann kannste vieleicht mitreden, was hier gebastelt wird. 😃

    DAS WIRD DIE FORTSETZUNG!!!

    War das langsaaaaaam genug? 😃

    PS: Haettest Du damals mitgelesen und nicht nur 'Reingequatscht, gaeb's nun kein Problem! 🕶

    [ Dieser Beitrag wurde am 09.03.2003 um 23:10 Uhr von DerAltenburger editiert. ]



  • Original erstellt von DerAltenburger:
    Haettest Du damals mitgelesen und nicht nur 'Reingequatscht, gaeb's nun kein Problem! 🕶

    *vogelzeig* Du tust ja gerade so, als wäre deine blöde Kompo diejenige, zu der man sich jeden Thread anschauen muss. Ich hab anderes zu tun und bastel lieber an guten Kompos.



  • Verwarnung an DerAltenburger und WebFritzi, bitte sachlich und beim Thema bleiben!



  • :p ... Wer haut sich denn schon um gute Kompos?. Das lohnt sich höchstens um die goooilste Kopmo. Und das kann daauuuern. 😃

    Schluß mit Peter Lustig 😉 , Image liegt also zentriert in der ScrollBox auf einem identisch justierten Panel. Parent von MarkBase ist auch das Panel. Das Bild von MarkBase wird jetzt richtig ins Image eingefügt.

    void __fastcall TPixi::MarkBaseImageMouseDown(TObject *Sender, TMouseButton Button,
                TShiftState Shift, int X, int Y)
    {
        FDragging = false;
        // double wäre gar nicht nötig, hab keinen Unterschied entdeckt
        MarkBase->Left = (int)((double)MarkBase->Left/VFac);  
        MarkBase->Top = (int)((double)MarkBase->Top/VFac);
        DRect.Left = MarkBase->Left;
        DRect.Top = MarkBase->Top;
        DRect.Right = MarkBase->Left+MarkBase->Width;
        DRect.Bottom = MarkBase->Top+MarkBase->Height;
        Image->Canvas->CopyRect(DRect, MarkBase->Canvas, MarkBase->ClientRect);
        MarkBase->Hide();
        MarkBase->Picture = NULL;
        MarkBase->Width = 1;
        MarkBase->Height = 1;
        DRect = Rect(0,0,0,0);
    }
    

    Bei +Zoom klappt es, bei -Zoom wird das eingefügte Bild proportional kleiner. Klar, Bildinfos gehen verloren. Pasten wird also erst ab 100% Sinn machen, darunter werd ich die Function sperren.

    Vorher wurde MarkBase verschoben:

    /* Im MarkBaseMouseDown:
    (int - global) markleft = X, marktop = Y;
    void __fastcall TPixi::MarkBaseMouseMove(TObject *Sender,
                TShiftState Shift, int X, int Y)
    {
        Screen->Cursor = crHand;
        if(Shift.Contains(ssLeft))
        {
            MarkBase->Left = MarkBase->Left + X - markleft;
            MarkBase->Top = MarkBase->Top + Y - marktop;
            /* Zu brutal, bin mit einem Schlag an der Scrollgrenze.
               Suche was besseres */
            // ScrollBox->ScrollInView(MarkBase);
        }
    }
    

    Bei Vergrößerungen wird weiterhin nach Canvas-Pixeln verschoben. Die Bild-Pixel sind größer, ich kann also auch auf Zwischenpositionen verschieben. Beim Einfügen wird dann auf das nächstgelegene Pixel in Top/Left-Richtung korrigiert. Ob sich das noch verbessern läßt? Ich wollte im jeweils aktuellen Bildpixelraster verschieben können. Mir fällt im Moment kein Algor ein. Hat jemand 'ne Idee?



  • *Bin geleidigt* Der BCB3 kennt kein DoubleBuffered. Aber ich verschieb hier ein gezoomtes TImage in einem gezoomten TImage. Da hat der das zu kennen! :o 😃 Oder auf hochdeutsch: Je gezoomt, desto langsamere Refreshrate. Das Flickert wie'd Sau.

    Genügend Threads, einiges probiert, es will nicht besser werden. Hab trotzdem eine Lösung:

    if(Shift.Contains(ssLeft))
        {
            MarkBase->Refresh();
            MarkBase->Left = MarkBase->Left + X - markleft;
            MarkBase->Top = MarkBase->Top + Y - marktop;
            MarkBase->Refresh();
        }
    

    MarkBase läuft jetzt schön glatt. Der Preis: Image refresht während dem Verschieben des MarkBase nicht, das Bild wird total zugeschmiert, bis ich das Verschieben kurz unterbreche.

    Gibt es da noch einen Trick? Bzw, wäre ggf. für das DoubleBuffering eine Bibliothek einzubinden, die man irgendwo bekommen kann - BCB3-kompatibel natürlich?


Anmelden zum Antworten