Besser als Pixmap.Paste
Übersicht

![]() |
BlitzMoritzBetreff: Besser als Pixmap.Paste |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich war mit der Methode Paste von TPixmap nicht zufrieden, und zwar vor allem deshalb, weil transparente Stellen der Quell-Pixmap ebenfalls transparente "Löcher" in die darunterliegende Ziel-Pixmap "gebrannt" haben, was wohl keiner will. Darum habe ich die Function PixmapPaste() gebastelt, die fast gar nicht langsamer ist als das "Original" und zwei Vorteile hat:
1.) Es besteht keine Absturzgefahr durch "Randprobleme": Pixmaps können auch über die Maße des Ziel-Pixmaps hinaus bzw. komplett "daneben" gepastet werden. 2.) Transparente Stellen der Quell-Pixmaps zerstören die darunterliegende Zielpixmap nicht: Alpha-Werte bzw. Farben werden gemischt. Code: [AUSKLAPPEN] Graphics 800,600,0
SetBlend ALPHABLEND Local Ziel:TPixmap = LoadPixmap("GrossesBildmitTransparenz.png") Local Quelle:TPixmap = LoadPixmap("KleinesBildmitTransparenz.png") Local Ergebnis:TImage = LoadImage(Ziel) Repeat Cls DrawText "Zufalls-PixmapPaste() durch Mausklick!", 10,10 DrawImage Ergebnis, MouseX()-ImageWidth(Ergebnis)/2, MouseY()-ImageHeight(Ergebnis)/2 Flip If MouseHit(1) Then Local x:Int = Rand(-PixmapWidth(Quelle), PixmapWidth(Ziel) + PixmapWidth(Quelle)) Local y:Int = Rand(-PixmapHeight(Quelle), PixmapHeight(Ziel) + PixmapHeight(Quelle)) PixmapPaste(Ziel,Quelle,x,y) 'Ziel.Paste(Quelle,x,y) '(zum Vergleich) Ergebnis = LoadImage(Ziel) End If Until KeyDown(KEY_ESCAPE) End '######################################################## Function PixmapPaste(PMZ:TPixmap, PMQ:TPixmap, x:Int, y:Int) '######################################################## Local Breite_Z:Int = PixmapWidth(PMZ), Tiefe_Z:Int = PixmapHeight(PMZ) Local Breite_Q:Int = PixmapWidth(PMQ), Tiefe_Q:Int = PixmapHeight(PMQ) 'Komplett daneben?: If x >= Breite_Z Or x+Breite_Q <= 0 Or y >= Tiefe_Z Or y+Tiefe_Q <= 0 Then Return 'Alle Ränder abchecken: Local x_Start_Z:Int = Max(0,x), x_Start_Q:Int = Max(0,-x) Local x_End_Q:Int = Breite_Q - 1 If x + Breite_Q > Breite_Z Then x_End_Q = Breite_Z - x - 1 Local y_Start_Z:Int = Max(0,y), y_Start_Q:Int = Max(0,-y) Local y_End_Q:Int = Tiefe_Q - 1 If y + Tiefe_Q > Tiefe_Z Then y_End_Q = Tiefe_Z - y - 1 Local A_Q:Int, R_Q:Int, G_Q:Int, B_Q:Int, A_Z:Int, R_Z:Int, G_Z:Int, B_Z:Int Local ARGB_Q:Int, ARGB_Z:Int, xq:Int, yq:Int, xz:Int = x_Start_Z, yz:Int '---------------------------------------- For xq = x_Start_Q To x_End_Q 'den nötigen Bereich durchlaufen yz = y_Start_z For yq = y_Start_Q To y_End_Q ARGB_Q = ReadPixel(PMQ, xq, yq) 'Farbe Quell-Pixmap A_Q = Byte((ARGB_Q & $FF000000) / $1000000) R_Q = Byte((ARGB_Q & $00FF0000) / $10000) G_Q = Byte((ARGB_Q & $0000FF00) / $100) B_Q = Byte(ARGB_Q & $000000FF) ARGB_Z = ReadPixel(PMZ, xz, yz) 'Farbe Ziel-Pixmap A_Z = Byte((ARGB_Z & $FF000000) / $1000000) R_Z = Byte((ARGB_Z & $00FF0000) / $10000) G_Z = Byte((ARGB_Z & $0000FF00) / $100) B_Z = Byte(ARGB_Z & $000000FF) '- - - - - - - - - - - - - - - - Mischen: A_Z = A_Q + (255-A_Q) * A_Z / 255 R_Z = A_Q * R_Q / 255 + (255 - A_Q) * R_Z / 255 G_Z = A_Q * G_Q / 255 + (255 - A_Q) * G_Z / 255 B_Z = A_Q * B_Q / 255 + (255 - A_Q) * B_Z / 255 ARGB_Z = A_Z*$1000000+R_Z*$10000+G_Z*$100+B_Z WritePixel(PMZ, xz, yz, ARGB_Z) '------------------------------- yz = yz + 1 Next xz = xz + 1 Next '############################ End Function '(PixmapPaste) '############################ Edit: Ich möchte obige Function ergänzen durch die folgende Function "ImagePaste()", deren Hauptmotivation es war, Bilder auch gedreht und transparent ineinander zu kleben. Wäre die Transparenz als weiterer Parameter ohne viel Aufwand auch in die PixmapPaste-Function einzubauen gewesen, so stieß ich bezüglich der Rotation an Grenzen: Es tauchten stets kleine Pixel-Schönheitsfehler auf, die mich an die alte RotateImage-Function von BlitzBasic2D erinnerte. Darum wählte ich einen anderen, einfacheren Weg, und zwar über das Grabben. Die graphischen Ergebnisse waren nun aber perfekt. Und was die Geschwindigkeit angeht: Echtzeit-Realisierung ist eh für keine der beiden Funktionen ein Thema. Noch einmal kurz zusammengefasst: Vorteile: 1.) Images können gedreht gepastet werden (Voraussetzung: MidHandleImage(Quell-Image) ) 2.) Images können transparent gepastet werden (Voraussetzung: SetBlend ALPHABLEND) 3.) Die Funktionalität ist von der Größe des Graphics-Fensters unabhängig! D.h. beliebig große Images können gepastet werden. (Ist das Fenster zu klein, wird in mehreren Teilen gegrabbt und die Teile mit obiger PixmapPaste-Function zusammengeklebt.) Nachteile: 1.) Für das Grabben wird der BackBuffer zwischenzeitlich bemalt. Soll dies nicht sichtbar werden, muss er durch ein Cls o.a. erneut übermalt werden. 2.) Transparenz bzw. Alpha-Informationen des Zielbildes gehen durch das Grabben zumindest an den gepasteten Stellen verloren. Mit den letzten drei Parametern der Function kann daher optional die RGB-Farbe bestimmt werden, die dort anstelle der Transparenz erscheinen soll. Code: [AUSKLAPPEN] AppTitle = "ImagePaste-Demo: Zum Einkleben bitte linke Maustaste drücken!"
Graphics 800,600 SetBlend ALPHABLEND Local Ziel:TImage = LoadImage("Ziel.png") Local Quelle:TImage = LoadImage("Quelle.png") MidHandleImage(Quelle) Local Drehwinkel:Float = 30.0 Local Alpha:Float = 0.75 '------------------------------------------------------------------------------------ Repeat If MouseHit(1) Then Local PM:TPixmap = ImagePaste(Ziel, Quelle, MouseX(), MouseY(), Drehwinkel, Alpha) Ziel = LoadImage(PM) End If Cls SetColor 255,255,255 SetRotation 0 SetAlpha 1.0 DrawImage Ziel,0, 0 SetRotation Drehwinkel SetAlpha Alpha DrawImage Quelle, MouseX(), MouseY() Flip Until KeyDown(KEY_ESCAPE) '------------------------------------------------------------------------------------ '========================================== Function ImagePaste:TPixmap(Ziel:TImage, Quelle:TImage, x:Int, y:Int, Drehung:Float, Alpha:Float, ClsRed:Int = 0, ClsGreen:Int = 0, ClsBlue:Int = 0) '========================================== If Ziel = Null Then Return Null If Quelle = Null Then Return LockImage(Ziel) '----------------------------------------------------------------------------- Local Komposition:TPixmap = LockImage(Ziel) '----------------------------------------------------------------------------- Local Breite:Int = ImageWidth(Quelle) * Abs(Cos(Drehung)) + ImageHeight(Quelle) * Abs(Sin(Drehung)) Local Tiefe:Int = ImageWidth(Quelle) * Abs(Sin(Drehung)) + ImageHeight(Quelle) * Abs(Cos(Drehung)) Local Links:Int = x - 0.5*Breite, Oben:Int = y - 0.5*Tiefe '----------------------------------------------------------------------------- Local Schirmbreite:Int = GraphicsWidth(), Schirmtiefe:Int = GraphicsHeight() '----------------------------------------------------------------------------- Local Horizontal_Wiederholung:Int = Breite / Schirmbreite Local Vertikal_Wiederholung:Int = Tiefe / Schirmtiefe Local Teil_Breite:Int = Breite / (Horizontal_Wiederholung+1) Local Teil_Tiefe:Int = Tiefe / (Vertikal_Wiederholung+1) '----------------------------------------------------------------------------- For Local i:Int = 0 To Horizontal_Wiederholung For Local j:Int = 0 To Vertikal_Wiederholung SetRotation 0 SetAlpha 1.0 SetColor ClsRed, ClsGreen, ClsBlue DrawRect 0, 0, Teil_Breite, Teil_Tiefe SetColor 255,255,255 DrawImage Ziel, -Links-i*Teil_Breite, -Oben-j*Teil_Tiefe SetRotation Drehung SetAlpha Alpha DrawImage Quelle, -Links+x-i*Teil_Breite, -Oben+y-j*Teil_Tiefe Local Teil_Pixmap:TPixmap = GrabPixmap(0, 0, Teil_Breite, Teil_Tiefe) PixmapPaste(Komposition, Teil_Pixmap, Links + i * Teil_Breite, Oben + j * Teil_Tiefe) Next Next UnlockImage Ziel SetRotation 0 SetAlpha 1.0 Return Komposition '========================================== End Function 'ImagePaste '========================================== '(PixmapPaste-Function nicht vergessen!) |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group