StretchDraw() total lahm
-
Hi, ich benutze die Canvas-Methode StretchDraw() um eine Graphik zu skalieren. Es wird immer um einen Zoomfaktor skaliert (Zoom ist natürliche Zahl). Leider ist die Funktion total langsam. Wenn ich z.b. eine 100x100 große Grafik auf eine 14x vergrößerte (d.h. Zoom=14, 1400x1400 große Image) 'StretchDraw'en möchte, wird das voll langsam.
Gibts eine schnelle alternative zu der Funktion? Oder andere Lösungen?
-
Hi,
wenn ich recht informiert bin, gibt es einige API Funktionen. Diese könnten etwas effizienter sein. Such mal nach "StretchBlt" und verwandten Themen
Gruß
Martin
-
das macht nciht viel. Schließlich ruft Canvas die Methode wahrscheinlich auch auf.
Stichwort Double Buffering. Das Bitmapo erst in ein anderes Bitmap stretchen und dann ein Image zuweisen. Dann ist während des Strech- Vorganges das alte Bild noch im Image (oder im hdc, wenn man das Bitmap direkt auf den Gerätekontext schriebt).
Such mal nach Offscreen Bitmap oder Double Buffering in der FAQ und hier im Forum. Wurde schon oft diskutiert.
-
Ich glaube nicht, dass das Zeichnen der Flaschenhals ist, DoubleBuffering hier also etwas bringen würde.
Das Problem dürfte schlicht das Berechnen der neuen Pixeldaten sein. Und da ist StretchDraw noch vergleichsweise schnell, weil es einen sehr einfachen Algorithmus verwendet (nearest neighbor, soweit ich weiss). Dementsprechend ist das Ergebnis qualitativ meist auch nicht allzu berauschend.
Andere Algorithmen (bilinear/bicubic interpolation etc.) liefern eine bessere Qualität, benötigen aber entsprechend (noch) mehr Rechenzeit.
-
Also ich benutze DoubleBuffering. Aber mir ist gerade eben was eingefallen, kam aber noch nicht dazu es auszuprobieren.
Also, ich benutze ja riesen große Bilder dann (z.b. 1400x1400), und dachte vielleicht den Befehl CopyRect() nur den Teil zu stretchen und zu "zeichnen" würde mir vielleicht etwas Speed bringen, und ich könnte auch mal den Befehl ClipRect() von Canvas probieren. Ich glaub das stand in der Hilfe, dass das etwas Performance bringt. Also meint ihr, das würd was bringen?
-
Na logisch bringt das etwas, wenn du statt des gesamten Bildes nur einen Ausschnitt bearbeitest.
Leider fehlt bei deiner ursprünglichen Frage ja eine Erläuterung, was dein Programm eigentlich machen soll, sonst hätte dir bestimmt schon jemand einen entsprechenden Vorschlag gemacht.
-
Tja jetzt gibts ein kleines Problem. Bei StretchDraw gibt man ja so schön die Graphik an, die die Transparenz mit sich trägt (bei mir die Farbe RGB(0,1,0)), aber bei CopyRect() von Canvas gibt man ja nur die Canvas an - und damit ist die Transparenz nicht mit drin. Wie lös ich das Problem?.
-
Siehe TBitmap die Eigenschaften:
__property bool Transparent;
__property Color TransparentColor;sowie TransparentMode, wo sogar ein Beispiel bei ist
-
@AndreasW: du hast meinen Eintrag wohl nicht ganz richtig gelesen. Ich meinte die Canvas Funktion CopyRect(). Da gibt es kein Transparent Color oder so.
-
ähm,
mal etwas anzeiz:
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Graphics::TBitmap* Bitmap1=new Graphics::TBitmap; // erst ein mal ein Bild schaffen. Du wirst je ein Bild aus einer Datei nehmen Bitmap1->Height=100; Bitmap1->Width=100; Bitmap1->Canvas->Brush->Color=clRed; Bitmap1->Canvas->FillRect(Rect(0,0,100,100)); // Hintergrundfarbe auf rot setzen Bitmap1->Canvas->Brush->Color=clBlue; Bitmap1->Canvas->FillRect(Rect(25,25,75,75));// nun ein blaues Quadrat auf den roten hintergrund. // das Blaue Quadrat soll durchsichtig sein. // nimm an, das du nicht gezeichnet hast, sondern das Bild aus eine Datei geladen hast Bitmap1->TransparentColor=clBlue;// transparente Farbe setzen Bitmap1->Transparent=true; // jetzt willst du das Bitmap stretchen: // nun ein Bitmap Graphics::TBitmap* Bitmap2=new Graphics::TBitmap; Bitmap2->Height=200; Bitmap2->Width=200; Bitmap2->Canvas->Brush->Color=clGreen; Bitmap2->Canvas->FillRect(Rect(0,0,200,200)); Bitmap2->Canvas->StretchDraw(Rect(0,0,200,200),Bitmap1); // mit Draw Canvas->Draw(0,0,Bitmap1) ; Canvas->Draw(110,0,Bitmap2); //oder oder mit CopyRect Canvas->CopyRect(Rect(0,210,400,610),Bitmap2->Canvas,Rect(0,0,200,200)); delete Bitmap1; delete Bitmap2; } //---------------------------------------------------------------------------
Vielleicht solltest du zwei TImage in Erwägung ziehen, die du übernanderliegend abwechselnd nach vorne holst, nachdem das Image das Bild geladen hat. Dabei DoubleBuffering des Forumlars auf true setzen. Ich hab aber nicht ausprobiert, ob das besser ist.
-
Du hast es falsch verstanden.
Also ich habe sagen wir mal Bitmap1 (100x100) und die EndBitmap im Zoomstatus 5 (500x500). Aber der Client Rect ist nur die linkere obere hälfte, also z.b. 50x50px. Also möchte ich den links oberen Berreich von Bitmap1 in die EndBitmap kopieren.
Das mach ich eigentlich mit EndBitmap->Canvas->CopyRect(ZielBerreich, Bitmap1, QuellBerreich);
-
Ich meinte die Canvas Funktion CopyRect(). Da gibt es kein Transparent Color oder so.
Problem gelöst.
ich wollte dir keine Komplettlösung geben. Nur ein Beispiel wie man es machen kann. Und das hab ich. Welchen Bereich du wohin haben willst spielt dabei für mich keine Rolle.