Bildübertragung incl. neuer Bildveränderungen



  • <edit>Der Grafiker-Hartriegelcheck war *köstlich*. Die würden ja nicht mal der Oma ihre Geheimnisse verraten. :p - Aber wer fragt schon die Oma, wenn es um Algors geht? 😃

    Trotzdem steh ich vor einem Rätsel. Beim Zoomen bezieh ich mich immer auf ein SaveImage (Graphics::TBitmap) und aktualisier nach dem Zoomen das TImage von der Speicherbitmap. Der Vorgang klappt UFB, auch Canvas-Pen->Widt wird (an anderer Stelle) umgerechnet.

    Nun hab ich vor dem Zoomen aber ggf. das Bild verändert. Das muß mitberücksichtigt werden. Also StretchDraw'e ich das Bild aus dem TImage vor dem Vergrößern ins SavePict. Nach dem Vergrößern hol ich entsprechend mit StretchDraw das Bild vom SavePict wieder zum TImage.

    Eigentlich sollte das größenveränderte Bild im TImage die aktuellen Änderungen enthalten. Hat es aber nicht. Es ist, als hätte ich nicht gezeichnet. Kann jemand den Denkfehler erkennen?

    // VergrBox (TCombobox auf Style=csDropDownList)
    Graphics::TBitmap *SavePict = new Graphics::TBitmap();
    // wird im OnCreate vorbereitet und ggf. im OnShow 
    // (später in der Open-Routine) überschrieben, wenn ein Bild geladen wird
    ...
    int VergrFaktor; // Vergrößerungsfaktor
    void __fastcall TPixi::ZoomOutBtnClick(TObject *Sender)
    {
        //if (VergrFaktor >= 1 && BildModified == true)
            // Bild vom TImage ins SavePict stretchen
            SavePict->Canvas->StretchDraw(Canvas->ClipRect,
                    Image->Picture->Graphic);     
        // Vergrößerungsfaktor-ComboBox aktualisieren
        if (VergrFaktor >= 1 && VergrFaktor <= 8)
            VergrBox->ItemIndex += 1;
        else if (VergrFaktor == 0.25 || VergrFaktor == 0.50)
            VergrBox->ItemIndex -= 1;
        else if (VergrFaktor == 0.75)
            VergrBox->ItemIndex = 0;
        // Wenn nicht weiter vergrößert wird,
        // die Arbeiten nicht ausführen
        else return;
        // neuen Vergrößerungsfaktor berechnen lassen
        VergrFaktorChange(Sender);
        // Bild im TImage aus der Speicherbitmap aktualisieren
        Image->Width = SavePict->Width*VergrFaktor;
        Image->Height = SavePict->Height*VergrFaktor;
        Image->Picture->Graphic->Width = Image->Width;
        Image->Picture->Graphic->Height = Image->Height;
        Image->Canvas->StretchDraw(Image->ClientRect,SavePict);
        // Bild in der ScrollBox zentrieren
        FormResize(Sender);
    }
    

    Hmmm..., spätestens jetzt beim Schreiben hätte mir der Fehler auffallen sollen. Für mich sieht es fehlerfrei aus.



  • ORIGINAL OMEGA-X:

    //if (VergrFaktor >= 1 && BildModified == true)
    // Bild vom TImage ins SavePict stretchen
    SavePict->Canvas->StretchDraw(Canvas->ClipRect,
    Image->Picture->Graphic);

    kann es sein, dass sich (Canvas->Cliprect, auf Button oder Form bezieht???

    Ich würde 'mal (SavePict->Canvas->ClipRect, probieren!?

    Hoffe es hilft.



  • Aaaaa, daß man sowas manchmal einfach nicht sieht. Dank dir, @DerAltenburger. Code muß eindeutig sein, sonst gibt's Probleme. Hab den Code inzwischen weiteroptimiert und in Functionen aufgeteilt. Brauchte jetzt nur an einem Punkt korrigieren. Das Zusammenspiel zwischen In- und Out-Button und der Direktzuweisung in der Combobox klappt einwandfrei.

    Nur noch definieren, daß unter 100% nicht gezeichnet wird, dann stimmt der Bereich mal. Ich überschreib auch unter 100% das SavePict nicht.

    Ich wollte wirklich mal wissen, wie das die Profis machen. Die zeichnen die Pixel immer genau im Raster. Das klappt bei jeder Vergrößerung, auch bei winzig kleinen. Bei mir ist alles Zufall. Hab erst mal keine Vorstellung, wie man so ein Rastermalen realisieren könnte. Wenn jemand was weiß oder eine Idee hat, ich wär da unglaublich dankbar.



  • Ich weis nicht recht was Du bastelst!?

    Ich denke, Du willst in Bild zeichnen; dabei soll das Bild in verschiedenen Groessen angezeigt werden?

    dazu nehm ich ein TImage,lade darein eine leere Bitmat gewünschter Originalgroesse.

    mit AUTOSIZE=false
    und STRETCH=true stell ich die Anzeigegroese (TImage- Masse) proportional ein
    (Zoomfaktor berechnen und mit Bitmap Breite/ Hoehe multiplizieren)

    Im Canvas von TImage mal' ich dann in Original- Pixelgroesse!

    Bei Malen nach Maus muss dann Mausposition mit Faktor korrigiert werden.

    Ich tu Timage in 'ne ScrollBox (mit Rollbalken, wenn's Bild zu gross wird), dann muss Scrollposition auch mit eingerechnet werden!

    Probier's mal, oder nich 😉



  • *wein*, ich seh nach "oder nicht" aus, leider. Dein Weg wär mir der liebste, weil unkompliziert, und man kann bei jeder Vergrößerung arbeiten.

    Das Prob, ich bekomm die Malposition in der Scalierung nicht hin. Trotz guter Hilfe gelang es nicht. Da fehlt etwas, was ich noch tun sollte. ZB:

    Image->Canvas->PenPos = Image->Canvas->PenPos * VergrFaktor;

    oder

    Origin = Origin * VergrFaktor;
    MovePt = MovePt* VergrFaktor;

    zeigen keine Wirkung. Nur darum kam ich auf die Idee mit der Speichergraphic incl aller Nachteile.

    Wie muß ich richtig scalieren? Die Scrollposition kann ich auch nicht beeinflussen. Dabei wär das AutoScroll zB. auch beim Aufziehen eines rechtecks wichtig. Hab bisher noch nicht rausgefunden, wie es geht.



  • Omega-X,
    Kuck mal unter 'Bild- Viewer- Problem', da hab' ich 'ne Antwort fuer Dich gelassen 😉



  • Hab's gesehen, danke. War natürlich nicht beabsichtigt, den Thread kaputt zu machen. Aber das Thema war verlockend, und die Fortführung ist nicht OT. 🙄



  • Die Zeilen in

    void __fastcall TImagePaintScroller::MouseMove(Classes::TShiftState Shift, int X, int Y)
    {
      if (ControlAtPos(Point(X,Y),true)==FImage)
        FImage->Canvas->MoveTo(PenPos.x,PenPos.y);
        FPenPos=Point(float(X-FImage->Left) / Dimension->ImageZoom,float(Y-FImage->Top) / Dimension->ImageZoom);
    

    ( Bild-Viewer Probleme )
    schienen ein wichtiger Hinweis zu sein. PenPos im OnMouseMove ständig in Abhängigkeit vom Zoomfaktor korrigieren. Hat in meinem Proggy leider genauso wenig geholfen wie ähnliche, aber nicht so klare Versuche.

    // Image ist ein TImage
    // SavePict ist Graphics::TBitmap
    // int VergrFaktor ist der Vergrößerungsfaktor
    void __fastcall TPixi::Zoom(TObject *Sender)
    {
        BRectCheck(Sender); // ggf. MarkRect entfernen
        VergrFaktorChange(Sender); // Zoomfaktor-Steuerfunktion
        Image->Width = SavePict->Width * VergrFaktor;
        Image->Height = SavePict->Height * VergrFaktor;
        //Image->Picture->Graphic->Width = Image->Width;
        //Image->Picture->Graphic->Height = Image->Height;   
        Image->Canvas->StretchDraw(Image->ClientRect,SavePict); 
        FormResize(Sender); // TImagenach dem Zoomen in ScrollBox zentrieren
    }
    

    Die auskommentierten Zeilen sind trotz der im OnMouseMove eingefügten Ergänzung nötig, um wirklich an der Mausposition zu zeichnen und nicht in relativer Abweichung.

    Hier noch der Weg im OnMouseMove des TImage:

    if(Drawing)
        {
            Image->Canvas->Pen->Mode = pmNotXor;        // XOR-Modus zum Zeichnen/Löschen verwenden.
            // Diese Zeile
            Image->Canvas->PenPos=Point(float(X-Image->Left) / VergrFaktor,
                    float(Y-Image->Top) / VergrFaktor);
            // anstatt der auskommentierten
            //Image->Canvas->MoveTo(Origin.x, Origin.y);  // Stift auf Ausgangspunkt zurücksetzen.
    ...
        }
    

    Ein Weg, ggf. ohne Zuhilfenahme einer Speicherbitmap, aber auf jeden Fall sauber malen zu können, scheint also immer noch unentdeckbar. Zeigen sich ggf. schon Hinweise darauf, was ich noch oder anders zu tun hätte?


Anmelden zum Antworten