Bilder drehen mit DrawBlockRect...

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Holzchopf

Meisterpacker

Betreff: Bilder drehen mit DrawBlockRect...

BeitragDi, Mai 03, 2005 21:28
Antworten mit Zitat
Benutzer-Profile anzeigen
... und DrawImageRect, tausenden Mathefunktionen und - ach seht selbst: (Nicht vergessen: Ein Bild müsst ihr selbst angeben, dabei ist darauf zu achten, dass es quadratisch ist, sonst wirds evtl. beschnitten.)

Include (Als "DRI Include.bb" abzuspeichern):
Code: [AUSKLAPPEN]

;*************************************************
;
;   DrawRotatedImage
;
;========================
;
;   Funktionen zum Drehen von Bildern
;      von Holzchopf
;
;*************************************************

Type DRI_Image_Type
   Field Image
   Field Size
   Field SizeB
   Field SizeBH
   Field SizeH
   Field T_Img
   Field T_Img2
   Field T_Buffer
   Field T_Buffer2
   Field TransR, TransG, TransB
End Type

Global DRI_B_Buffer
Global DRI_Image.DRI_Image_Type
   
;*************************************************

; Lädt ein Bild, damit es mit den DRI-Funktionen
;   kompatibel wird.
Function DRI_LoadImage( DRI_Path$ )
   
   ; Dateiladen, bei Ladefehler 0 zurückgeben und Funktion abbrechen
   DRI_Img = LoadImage( DRI_Path )
   If Not DRI_Img Then Return 0
   
   ; Bildinfos speichern
   DRI_Image = New DRI_Image_Type
   DRI_Image\Image = DRI_Img
   DRI_Image\Size = ImageWidth( DRI_Img )
   DRI_Image\SizeB = DRI_Image\Size /2.0 *5.0
   DRI_Image\SizeBH = DRI_Image\SizeB /2.0
   DRI_Image\SizeH = DRI_Image\Size /2.0
   DRI_Image\T_Img = CreateImage( DRI_Image\SizeB, DRI_Image\SizeB )
   DRI_Image\T_Img2 = CreateImage( DRI_Image\SizeB, DRI_Image\SizeB )
   DRI_Image\T_Buffer = ImageBuffer( DRI_Image\T_Img )
   DRI_Image\T_Buffer2 = ImageBuffer( DRI_Image\T_Img2 )

   ; Backbuffer speichern
   DRI_B_Buffer = BackBuffer()
   
   ; Handle des Bilds zurückgeben
   Return Handle( DRI_Image )

End Function

; Lädt ein animiertes Bild, damit es mit den
;   DRI-Funktionen kompatibel wird.
Function DRI_LoadAnimImage( DRI_Path$, DRI_w, DRI_h, DRI_s, DRI_frames )
   
   ; Dateiladen, bei Ladefehler 0 zurückgeben und Funktion abbrechen
   DRI_Img = LoadAnimImage( DRI_Path, DRI_w, DRI_h, DRI_s, DRI_frames )
   If Not DRI_Img Then Return 0
   
   ; Bildinfos speichern
   DRI_Image = New DRI_Image_Type
   DRI_Image\Image = DRI_Img
   DRI_Image\Size = ImageWidth( DRI_Img )
   DRI_Image\SizeB = DRI_Image\Size /2.0 *5.0
   DRI_Image\SizeBH = DRI_Image\SizeB /2.0
   DRI_Image\SizeH = DRI_Image\Size /2.0
   DRI_Image\T_Img = CreateImage( DRI_Image\SizeB, DRI_Image\SizeB )
   DRI_Image\T_Img2 = CreateImage( DRI_Image\SizeB, DRI_Image\SizeB )
   DRI_Image\T_Buffer = ImageBuffer( DRI_Image\T_Img )
   DRI_Image\T_Buffer2 = ImageBuffer( DRI_Image\T_Img2 )

   ; Backbuffer speichern
   DRI_B_Buffer = BackBuffer()
   
   ; Handle des Bilds zurückgeben
   Return Handle( DRI_Image )

End Function

; Setzt MaskColor für ein DRI-Bild
Function DRI_MaskImage( DRI_Img, DRI_R, DRI_G, DRI_B )   ; Direkte Übergabe der Parameter
                                          ;  an die Globals ist leider nicht möglich.
   DRI_Image = Object.DRI_Image_Type( DRI_Img )
   DRI_Image\TransR = DRI_R   
   DRI_Image\TransG = DRI_G
   DRI_Image\TransB = DRI_B
   MaskImage DRI_Image\Image, DRI_R, DRI_G, DRI_B
   MaskImage DRI_Image\T_Img, DRI_R, DRI_G, DRI_B
   MaskImage DRI_Image\T_Img2, DRI_R, DRI_G, DRI_B

End Function

; Zeichnet ein rotiertes Bild, Parameter:
;   Bildhandle, X-Position, Y-Position, Drehwinkel, Frame, zu bemalender Buffer (standard Backbuffer)
Function DRI_DrawImage( DRI_Img, DRI_Xpos, DRI_Ypos, DRI_Angle, DRI_Frame = 0, DRI_DrawBuffer = 0 )

   DRI_Image = Object.DRI_Image_Type( DRI_Img )
   
   If DRI_DrawBuffer = 0
      DRI_DrawBuffer = DRI_B_Buffer
   EndIf

   ; Den zu zeichnenden Frame zwischenlagern
   SetBuffer DRI_Image\T_Buffer
      ClsColor DRI_Image\TransR, DRI_Image\TransG, DRI_Image\TransB
      Cls
      DrawImage DRI_Image\Image, 0,0, DRI_Frame
   SetBuffer DRI_DrawBuffer

   ; Da es zu Anzeigefehlern bei 315°+ kommt, jedoch nicht bei -45° .. 0°
   DRI_Angle = ( DRI_Angle + 405 ) Mod 360 - 45

   ; Bestimmen, welche Korrekturfaktoren genutzt werden sollen
   If DRI_Angle <= 45 Or DRI_Angle => 315
      DRI_Corr180 = 1
   ElseIf DRI_Angle => 135 And DRI_Angle <= 225
      DRI_Corr180 = -1
      DRI_Angle = 360 - DRI_Angle - 180
   ElseIf DRI_Angle > 45 And DRI_Angle < 135
      DRI_Corr180 = 1
      DRI_Angle = DRI_Angle - 90
      DRI_90Deg()
   ElseIf DRI_Angle > 225 And DRI_Angle < 315
      DRI_Corr180 = -1
      DRI_Angle = 360 - DRI_Angle - 90
      DRI_90Deg()
   EndIf

   ; Höhendifferenz
   DRI_HDif# = ( Tan( DRI_Angle ) * DRI_Image\SizeH )
   ; Breite des gedrehten Quadrates
   DRI_Width# = 2 * ( DRI_Image\SizeH / Cos( DRI_Angle ) )

   ;H_Hoehe# = Hoehe / 2.0
   DRI_Width_H# = DRI_Width / 2.0

   SetBuffer DRI_Image\T_Buffer2
      ClsColor DRI_Image\TransR, DRI_Image\TransG, DRI_Image\TransB
      Cls

      For DRI_x = -DRI_Width_H To DRI_Width_H
         DrawImageRect DRI_Image\T_Img, DRI_Image\SizeBH + DRI_x, ( DRI_Image\SizeBH - DRI_Image\SizeH ) + ( DRI_HDif * DRI_x / DRI_Width_H ), DRI_Image\SizeH + ( DRI_Image\Size * DRI_x / DRI_Width ) * DRI_Corr180, 0, 1, DRI_Image\Size
      Next

   SetBuffer DRI_DrawBuffer
      ; Grösse der umfassenden Hülle
      DRI_Cover# = Cos( 45 - Abs( DRI_Angle ) ) * ( DRI_Image\Size * Sqr(2) )
      DRI_Cover_H# = DRI_Cover / 2.0
      ; Breitendifferenz
      DRI_WDif# = Tan( DRI_Angle ) * DRI_Cover_H

      For DRI_y = -DRI_Cover_H To DRI_Cover_H
         DrawImageRect DRI_Image\T_Img2, ( DRI_XPos - DRI_Image\SizeBH) - ( DRI_WDif / DRI_Cover_H * DRI_y ), DRI_YPos + DRI_y * DRI_Corr180, 0, DRI_Image\SizeBH + ( ( DRI_Image\SizeH + Abs( DRI_HDif ) ) / DRI_Cover_H * DRI_y ), DRI_Image\SizeB, 1
      Next

End Function

; Dreht ein Bild um 90°, interne Funktion
Function DRI_90Deg()

   ClsColor DRI_Image\TransR, DRI_Image\TransG, DRI_Image\TransB

   SetBuffer DRI_Image\T_Buffer2
      Cls
      For DRI_x = -DRI_Image\SizeH To DRI_Image\SizeH
         DrawImageRect DRI_Image\T_Img, DRI_Image\SizeBH + DRI_x, DRI_Image\SizeBH - DRI_Image\SizeH + DRI_x, DRI_Image\SizeH + DRI_x, 0, 1, DRI_Image\SizeB
      Next

   SetBuffer DRI_Image\T_Buffer
      Cls
      For DRI_y = -DRI_Image\SizeBH To DRI_Image\SizeBH
         DrawImageRect DRI_Image\T_Img2, DRI_Image\SizeBH - DRI_Image\SizeBH - DRI_y, DRI_Image\SizeBH + DRI_y, 0, DRI_Image\SizeBH + DRI_y, DRI_Image\SizeB, 1
      Next

   SetBuffer DRI_Image\T_Buffer2
      Cls
      For DRI_x = -DRI_Image\SizeH To DRI_Image\SizeH
         DrawImageRect DRI_Image\T_Img, DRI_Image\SizeH + DRI_x, DRI_Image\SizeH - DRI_Image\SizeBH + DRI_x, DRI_Image\SizeBH + DRI_x, 0, 1, DRI_Image\SizeB
      Next
   
   SetBuffer DRI_Image\T_Buffer
      Cls
      DrawImage DRI_Image\T_Img2,0,0

End Function

; Gibt ein Bild und damit seinen Speicherverbrauch
;   wieder frei
Function DRI_FreeImage( DRI_Img )
   
   DRI_Image = Object.DRI_Image_Type( DRI_Img )
   
   FreeImage DRI_Image\Image
   
   Delete DRI_Image
   
End Function

; Gibt das Imagehandle eines DRI-Bildes zurück,
;   um von standard Image-Funktionen verwendet
;   werden zu können.
Function DRI_ImageHandle( DRI_Img )

   DRI_Image = Object.DRI_Image_Type( DRI_Img )
   
   Return DRI_Image\Image
   
End Function


Beispiel (Bildpfad berücksichtigen Wink ):
Code: [AUSKLAPPEN]

;*************************************************
;
;   DrawRotatedImage
;
;========================
;
;   Funktionsbeispiel
;      von Holzchopf
;
;*************************************************

; Funktionen einbinden
Include "DRI Include.bb"

Graphics 800, 600, 0, 2

SetBuffer BackBuffer()

; DRI-Kompatible Bilder laden (alle quadratischen
;   Bilder sind DRI-Kompatibel, wenn mit dieser
;   Funktion geladen.)
figur = DRI_LoadImage( "figur.bmp" )
animation = DRI_LoadAnimImage( "figur.bmp", 32, 32, 0, 4 )

; DRI-Bilder müssen mit DRI_MaskImage maskiert werden
DRI_MaskImage figur, 255,0,255
DRI_MaskImage animation, 255,0,255

While Not KeyDown(1)

   ; ClsColor neu setzen, weil die DRI-Funktionen auch ClsColor setzen
   ClsColor 64,64,64
   Cls

   my = MouseY()
   mx = MouseX()

   If MilliSecs() > nextframe
      frame = ( frame + 1 ) Mod 4
      nextframe = MilliSecs() + 1000
   EndIf

   start = MilliSecs()

   ; Gedrehtes Bild
   DRI_DrawImage figur, 400, 150, my
   ; Ungedrehtes Bild, DRI_ImageHandle() liefert Bild-Handle
   DrawImage DRI_ImageHandle( figur ), 600, 150

   ; Gedrehte Animation
   DRI_DrawImage animation, 400, 300, my, frame
   ; Ungedrehte Animation
   DrawImage DRI_ImageHandle( animation ), 600, 300, frame

   time = MilliSecs() - start

   Color 255,255,255

   ; Winkel und benötigte "Rendertime" 8)
   Text 0,0, "Drehwinkel: " + my + "°"
   Text 0,50, "Benötigte Zeit: " + time + "ms"


   Flip

Wend

End



Hach Rolling Eyes eigentlich wollt' ich den Code erst beim nächsten DACH-BB-Usertreffen vorstellen Wink aber was solls, die Skizzen dazu sind auch nicht ohne Razz

MfG
  • Zuletzt bearbeitet von Holzchopf am Fr, Dez 29, 2006 13:34, insgesamt einmal bearbeitet

Holzchopf

Meisterpacker

BeitragMi, Mai 04, 2005 18:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Kekskiller hat Folgendes geschrieben:
Oh, yeah, ich wollte schon immer Codes studieren, in denen jede Variablen mit DRI_ anfängt Laughing


Das hat einen ganz einfachen (und in meinen Augen überaus korrekten) Grund: So wird es i.d.R. NIE konfrontationen mit anderen Globals geben. Stell dir vor, die variable DRI_Size würde nur Size heissen, und du möchtest nun diese Funktion in ein grösseres Projekt einbauen, in dem es dummerweise schon eine globale Variable namens Size gibt... viel Spass Wink
(Keine Regel ohne Ausnahme: Wenn man natürlich aus irgend nem anderen Grund das Präfix DRI_ schon benutzt ist, hat man wieder die selben Prrobleme)

Das mach ich bei Funktionen, die ich in anderen Codes einsetzen werde (oder auch nicht, aber solange die Möglichkeit besteht) immer so. Ist nur von Vorteil, glaub mir Rolling Eyes

Ausserdem fängt nicht jede Variable mit DRI_ an Razz eigentlich sogar nur die, die man in Includes packt und später nie wieder zu Gesicht bekommen wird Smile
(Oder habt ihr etwa bei grossen Projekten alle Funktionen und Definitionen in EINER Datei Laughing wohl kaum - und auch da macht sich das mit den Präfixen wieder bezahlt Rolling Eyes )

Aber danke fürs Interesse Smile

MfG

Edit: Ach ja, fast vergessen: Dass es zu Fehlern kommt, wenn man Func = 0 ausprobiert ist Absicht, nur quasi so als letzte Warnung, dass der PC bei Erfolg abstürzen wird Very Happy

Edit²: Geht natürlich auch ohne Absturz, aber nur, wenn man schon auf ESC klickt, bevor die erste Sekunde durch ist Wink und auch dann wird BB noch einige Sekunden rumlamen...
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Thoem

BeitragMi, Mai 04, 2005 19:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Lass Dich nicht anmachen. Ich handhabe dieses Verfahren schon lange. Alle Globals und Funktionen beginnen mit dem Präfix des Includes.

Was Dein Programm angeht: Gute Arbeit Smile
Thoem...

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group