Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Grafik drehen, Klappe die x. ....

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 26.05.2013, 11:24    Titel: Grafik drehen, Klappe die x. .... Antworten mit Zitat

Ich will mir meine eigene Bitmaprotation schreiben und hab dabei mal versucht Multiput zu zerlegen...
naja... nicht so einfach
Letztendlich hab ich mich für diese Vorgehensweise entschieden.
Dafür hab ich mal eine kleine Visualisierung geschrieben:
(Frage kommt hinterher)

Code:

'******************************************************************************
type vector
  x as double
  y as double
end type
'******************************************************************************

'Koordinatenursprung
const as integer Xo=400
const as integer Yo=300
'Pi
const as double pi =atn (1) * 4
const as double doublepi=pi*2
'Globaler Punkte/Vektor Speicher
dim shared as vector Points(63)' so! das sollten genug Punkte sein

'Zeichenroutinen, sollen nur den Code lesbarer machen
sub DrawCartesian
  line (0,Yo)-(799,Yo),&H007F00
  line (Xo,0)-(Xo,599),&H7F0000
end sub

sub DrawPolygon(fi as integer, li as integer,col as uinteger=&H000000)
  pset(Xo+Points(li).x,Yo-Points(li).y),col
  for i as integer=fi to li
    line -(Xo+Points(i).x,Yo-Points(i).y),col
  next i
end sub

sub DrawPoint(i as integer,col as uinteger=&H000000)
  line (Xo+Points(i).x-5,Yo-Points(i).y)-(Xo+Points(i).x+5,Yo-Points(i).y),col
  line (Xo+Points(i).x,Yo-Points(i).y-5)-(Xo+Points(i).x,Yo-Points(i).y+5),col
  circle(Xo+Points(i).x,Yo-Points(i).y),5,&H000000
end sub

sub DrawVector(l as integer,i as integer,col as uinteger=&H000000)
  line (Xo+Points(l).x,Yo-Points(l).y)-(Xo+Points(l).x + Points(i).x*15,Yo-Points(l).y - Points(i).y*15),col
  circle(Xo+Points(l).x,Yo-Points(l).y),2,&H000000
end sub


'******************************************************************************
'******************************************************************************
'******************************************************************************
'Hier gehts los....

screen 19,32
color &H000000,&HFFFFFF

dim as integer boxw,boxh
dim as double pivotx,pivoty
dim as double arcus,degree
dim as double x,y,xmin,xmax,ymin,ymax'Berechnungshilfen
dim as string junk
dim as uinteger gray,green
gray=&H7F7F7F
green=&H00DD22


'Boxgröße definieren
boxw=150                                    'diese stellt das ungedrehte Originalimage dar
boxh=200
'Drehwinkel in Grad festlegen
degree=100
arcus=doublepi/360 * degree                 'Grad --> Bogenmaß
'Drehpunkt festlegen
pivotx=30
pivoty=-30



'Zeichnen
cls
DrawCartesian                               'Zeichne Koordinatensystem
print "1.) Koordinatensystem"
sleep 15000                                 'Pause

'Berechnungen
Points(0).x=0                               'linke obere Ecke im Koordinatenursprung positionieren
Points(0).y=0
Points(1).x=Points(0).x                     'basierend auf ersten Punkt die drei anderen positionieren
Points(1).y=Points(0).y - boxh
Points(2).x=Points(0).x + boxw
Points(2).y=Points(0).y - boxh
Points(3).x=Points(0).x + boxw
Points(3).y=Points(0).y                     'Box befindet sich nun im IV. Quadranten
Points(4).x=pivotx                          'Drehpunkt in das Pointsarray übertragen
Points(4).y=pivoty

'Zeichnen
cls
DrawCartesian                               'Zeichne Koordinatensystem
DrawPolygon(0,3,green)                      'ungedrehte Box
DrawPoint(0,green)                          'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray)                           'ungedrehter Drehpunkt
print "2.) Originalgrafik linke obere Ecke ( Pixel(0,0) ) im Koordinatenursprung mit"
print " gewuenschtem Drehpunkt"
sleep 15000                                 'Pause

'Berechnungen
xmin=0                                      'mit Hilfe dieser vier Variablen wird die Größe und Lage(!) des temporären
xmax=0                                      'Images bestimmt, welches die gedrehte Grafik aufnimmt
ymin=0
ymax=0
Points(5)=Points(0)                         'da im Ursprung kann dieser einfach übernommen werden
for i as integer=1 to 4                     'nur 3 Punkte müssen gedreht werden
  x= Points(i).x * cos(arcus) - Points(i).y * sin(arcus)
  y= Points(i).x * sin(arcus) + Points(i).y * cos(arcus)
  Points(i+5).x=x
  Points(i+5).y=y
  if i<4 then                                'Drehpunkt bei min/max ausschließen
    if x<xmin then xmin=x                    'nach Berechnung auf max/min prüfen und "merken"
    if x>xmax then xmax=x
    if y<ymin then ymin=y
    if y>ymax then ymax=y
  end if
next i

'Zeichnen
cls
DrawCartesian                               'Zeichne Koordinatensystem
DrawPolygon(0,3,gray)                       'ungedrehte Box
DrawPoint(0,gray)                           'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray)                           'ungedrehter Drehpunkt
DrawPolygon(5,8,green)                      'gedrehte Box
DrawPoint(5,green)                          'gedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(9,green)                          'gedrehter Drehpunkt
print "3.) gedrehte Grafik mit gedrehten Drehpunkt *hust*"
sleep 15000                                 'Pause

'Berechnung
dim as integer box2w,box2h
box2w=xmax-xmin
box2h=ymax-ymin

Points(10).x=xmin
Points(10).y=ymax
Points(11).x=Points(10).x
Points(11).y=Points(10).y - box2h
Points(12).x=Points(10).x + box2w
Points(12).y=Points(10).y - box2h
Points(13).x=Points(10).x + box2w
Points(13).y=Points(10).y
Points(14).x=Points(10).x'2 Hilfspunkte für die Darstellung der Vektoren
Points(14).y=Points(10).y+15
Points(15).x=Points(10).x-15
Points(15).y=Points(10).y
Points(16).x=+1'Vektor
Points(16).y=0
Points(17).x=0
Points(17).y=-1
'Zeichnen
cls
DrawCartesian
DrawPolygon(0,3,gray)                       'ungedrehte Box
DrawPoint(0,gray)                           'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray)                           'ungedrehter Drehpunkt
DrawPolygon(5,8,gray)                       'gedrehte Box
DrawPoint(5,gray)                           'gedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(9,gray)                           'gedrehter Drehpunkt
DrawPolygon(10,13,green)                    'ungedrehte Box temporäres Image,
DrawPoint(10,green)                         'ungedrehte Box temporäres Image, linker oberer Punkt ( Pixel(0,0) )
DrawVector(14,16,green)                     'Vektor
DrawVector(15,17,green)                     'Vektor
print "4.) Lage und Groesse des temporaeren Images welches die gedrehte Grafik enthalten wird"
print "der linke obere Punkt des temp. Images ist gleichzeitig der noch"
print "ungedrehte Startpunkt des Scanvorgangs"

sleep 15000                                 'Pause

'Berechnung
'Drehung der Scanbox entgegengesetzt
for i as integer=10 to 17
  x= Points(i).x * cos(-arcus) - Points(i).y * sin(-arcus)
  y= Points(i).x * sin(-arcus) + Points(i).y * cos(-arcus)
  Points(i+8).x=x
  Points(i+8).y=y
next i

'Zeichnen
cls
DrawCartesian
DrawPolygon(0,3,gray)                       'ungedrehte Box
DrawPoint(0,gray)                           'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray)                           'ungedrehter Drehpunkt
DrawPolygon(5,8,gray)                       'gedrehte Box
DrawPoint(5,gray)                           'gedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(9,gray)                           'gedrehter Drehpunkt
DrawPolygon(10,13,gray)                     'ungedrehte Box temporäres Image,
DrawPoint(10,gray)                          'ungedrehte Box temporäres Image, linker oberer Punkt ( Pixel(0,0) )
DrawVector(14,16,gray)                      'Vektor
DrawVector(15,17,gray)                      'Vektor
DrawPolygon(18,21,green)                    'gedrehte Box temporäres Image,
DrawPoint(18,green)                         'gedrehte Box temporäres Image, linker oberer Punkt ( Pixel(0,0) )
DrawVector(22,24,green)                     'gedrehter Vektor
DrawVector(23,25,green)                     'gedrehter Vektor
print "5.) entgegengesetzt gedrehte Box des temp. Images. Scanstartpunkt ist"
print "nun an richtiger Position. Die beiden Richtungsvektoren sind ebenfalls"
print "gedreht."
print "Dies stellt nun die ScanBox dar, von der die Farbwerte ins temp. Image"
print "uebertragen werden."
sleep
end



um einen anderen Drehpunkt zu realisieren, habe ich einfach einen Punkt definiert und diesen virtuell mitgedreht.
Reicht es einfach aus, (nach Rotation und Scan) das temoräre Image so zu verschieben, daß sich der "gedrehte RotationsPunkt"
wieder über den "ungedrehten" befindet?

Ich weiß, das Ganze ist jetzt sehr unglückich formuliert, hoffe aber jemand steigt hinter mein Anliegen.
Ich bin auch schon reichlich loose deswegen lächeln

Mutton
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 26.05.2013, 12:55    Titel: Antworten mit Zitat

Ich hab vor ewigen Zeiten (auch mithilfe von multiput) mal eine eigene Rotations-Routine gebastelt gehabt (auch wenn ich sie (vermutlich) nicht mehr habe)

Aber um ehrlich zu sein, ich hab die Frage nicht wirklich verstanden...
Was genau ist nun das Problem?
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 26.05.2013, 14:35    Titel: Antworten mit Zitat

Also mal kurz eine (Er-)Klärung:
Da wie beim "normalen" PUT Pixel(0,0) der Originalgrafik als Referenz für die Verortung gilt, soll
dies auch bei meine Routine so bleiben.Deswegen liegt die linke obere Ecke im Koordinatenursprung.

Dann werden die restlichen 3 Eckpunkte gedreht. Dies dient eigentlich nur dazu, Die Größe und(!) die Lage eines
temporären Images festzustellen. Dieses temporäre Image enthält später (nach einem Scan) die gedrehte Grafik und kann
genau an der grade ermittelten Position "gePUTet" werden, WENN der Drehpunkt im Koordinatenursprung bzw Pixel(0,0) bleibt.

Was wenn der Drehpunkt wo anders sein soll? Grundsätzlich ist es natürlich möglich die Originalgrafik nicht in den Urprung zu setzen.
Für den Scanvorgang ist es meiner Meinung nach günstiger, die Originalgrafik mit Pixel(0,0) im Ursprung zu belassen.

Statt dessen hab ich mir etwas anderes ausgedacht.

Ich definiere ein Drehpunkt, nennen wir ihn "P". Diesen drehe ich genauso wie ich es mit der OriginalBox getan habe. dadurch entsteht
punkt "P'".

Oben ist Punkt PT. Dies ist der Punkt wo ich das temporäre Image PUTen würde, wenn der Drehpunkt im Koordinatenursprung ist.
Wenn ich diesen aber so verschiebe, das "P" und "P'" wieder übereinander liegen...

Entspricht das Ergebnis dann einer Drehung um den Punkt "P" ????



naja es wird wohl auch nicht deutlicher *lach*

Mutton
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 26.05.2013, 15:50    Titel: Antworten mit Zitat

Kann sein das ich heute auf der Leitung steh' aber wirklich verstanden habe ich es eigentlich immer noch nicht happy

Deine Rotationsfunktion ansich ist ok, einen drehpunkt zu definieren ist glaube auch kein problem, das man ein image das man original zB nach 100,100 geputtet hat rotiert dann aber nicht mehr bei 100,100 putten kann sollte klar sein (wo ich wieder die Frage habe was genau das Problem ist happy)

Code:

 tX = (X-rotationspunktX) * cos(winkel) - (Y-rotationspunktY) * sin(winkel)
 tY = (X-rotationspunktX) * sin(winkel) + (Y-rotationspunktY) * cos(winkel)


Das sollte eigentlich den 'schwerpunkt' der rotation lösen?!

wenn das dein Problem war???
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 26.05.2013, 18:09    Titel: Antworten mit Zitat

Zitat:
Deine Rotationsfunktion ansich ist ok, einen drehpunkt zu definieren ist glaube auch kein problem, das man ein image das man original zB nach 100,100 geputtet hat rotiert dann aber nicht mehr bei 100,100 putten kann sollte klar sein (wo ich wieder die Frage habe was genau das Problem ist )


Genau darum geht es ja! Die eigentliche Drehung erfolgt bei mir immer um Pixel(0,0) des Originals, der auch im Koordinatenursprung liegt.
Wohin in diesem Fall gePUTet wird, ist bekannt. Diesen Punkt (PT siehe vorherigen Post) berechne ich ja korrekt.

Ich will aber anschließend, durch PUTn mit einen bestimmten Offset von diesem Punkt das Rotationszentrum verlagern.

Und da war meine Idee halt diese: man nehme einen Punkt(P) der das neue Rotationszentrum sein soll, drehe diesen(P') und verschiebe dann das zu PUTende von TP soweit, das Punkte P und P' wieder übereinanderliegen.

Meine Frage ist halt: ob das Ergebnis dann mathematisch,trigonometrisch oder sonstwie einer korrekten Drehung um P entspricht... grinsen

Naja... davon geht die Welt nicht unter lachen
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 26.05.2013, 23:59    Titel: Antworten mit Zitat

Ich habs zwar auch nicht kappiert, aber ich versuche jetzt einfach mal auf irgend etwas zu antworten:

Um etwas zu drehen benötigst du grundlegend erstmal einen Rotationspunkt. Ohne diesen funktioniert das drehen generell nicht.
Anhand dieses Punktes kannst du dann berechnen, wo ein Sourcepixel nach der drehung platziert werden muss.

Du hast angenommen ein Bild mit 200x300. Legst auf 100x150 den drehpunkt fest und willst um 90° drehen. Dann landet der pixel von 1x1 bei 250x-50.

änderst du den drehpunkt entsprechend auf 1x1 dann landet pixel 1x1 bei 1x1.

die berechnung dieses ist, wie von @Eternal_pain schon beschrieben.

wenn du jetzt noch einen offset hinzufügen willst, sprich ... du drehst, udn willst das ergebniss dann nochmal linear verschieben, dann musst du natürlich diesen offset beim ergebniss setzen, da beim source du sonst outofboundary kommst.

sprich: tx = offsetX + (x-rotationspunktX) ....


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eukalyptus



Anmeldungsdatum: 17.05.2013
Beiträge: 11

BeitragVerfasst am: 27.05.2013, 22:49    Titel: Antworten mit Zitat

Verwende doch eine Matrix.

Damit kannst du dann gleichzeitig auch noch kippen und skalieren.
Genauso, wie man es in GDIPlus machen kann!

Ich hab mal versucht diese Beispiel zusammenzubasteln:

Code:
Type t_MATRIX2D
   Private:
   MX(9) As Double
   Declare Sub Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
   
   Public:
   Declare Sub GetElements(pMX As Double Ptr)
   Declare Sub Invert
   Declare Sub MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
   Declare Sub Reset(pMX As Double Ptr)
   Declare Sub Rotate(fAngle As Double, iOrder As Integer = 0)
   Declare Sub Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
   Declare Sub Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
   Declare Sub Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
   
   Declare Constructor
End Type



Sub t_MATRIX2D.GetElements(pMX As Double Ptr)
   For i As Integer = 0 To 8
      pMX[i] = MX(i)
   Next
End Sub


Sub t_MATRIX2D.Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
   Dim As Double fS
   For x As Integer = 0 To 2
      For y As Integer = 0 To 2
         fS = 0
         For z As Integer = 0 To 2
            fS += pMX1[x*3+z] * pMX2[z*3+y]
         Next
         MX(x*3+y) = fS
      Next
   Next
End Sub




Sub t_MATRIX2D.MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
   fTX = fX * MX(0) + fY * MX(3) + MX(6)
   fTY = fX * MX(1) + fY * MX(4) + MX(7)
End Sub




Sub t_MATRIX2D.Invert
   '[ a  b  0 ]
   '[ c  d  0 ]
   '[ x  y  1 ]
   
   't = a*d-b*c
   
   '[  d/t -b/t  0 ]
   '[ -c/t  a/t  0 ]
   '[(c*y-d*x)/t -(a*y-b*x)/t  1 ]
   
   Dim As Double fM(9), fT
   GetElements(@fM(0))
   fT = fM(0)*fM(4)-fM(1)*fM(3)
   
   MX(0) = fM(4)/fT
   MX(1) = -fM(1)/fT
   MX(3) = -fM(3)/fT
   MX(4) = fM(0)/fT
   MX(6) = (fM(3)*fM(7)-fM(4)*fM(6)) / fT
   MX(7) = -(fM(0)*fM(7)-fM(1)*fM(6)) / fT
End Sub



Sub t_MATRIX2D.Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
   '[ 1  0  0 ]
   '[ 0  1  0 ]
   '[TX TY  1 ]
   
   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   Reset(@MX1(0))
   MX1(6) = fTransX
   MX1(7) = fTransY

   Select Case iOrder
      Case 0
         Mul(@MX1(0), @MX2(0))
      Case Else
         Mul(@MX2(0), @MX1(0))      
   End Select
End Sub



Sub t_MATRIX2D.Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
   '[ 1 SY  0 ]
   '[SX  1  0 ]
   '[ 0  0  1 ]

   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   Reset(@MX1(0))
   MX1(1) = fSkewY * 0.0174532925199433
   MX1(3) = fSkewX * 0.0174532925199433

   Select Case iOrder
      Case 0
         Mul(@MX1(0), @MX2(0))
      Case Else
         Mul(@MX2(0), @MX1(0))      
   End Select
End Sub





Sub t_MATRIX2D.Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
   '[SX  0  0 ]
   '[ 0 SY  0 ]
   '[ 0  0  1 ]

   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   Reset(@MX1(0))
   MX1(0) = fScaleX
   MX1(4) = fScaleY

   Select Case iOrder
      Case 0
         Mul(@MX1(0), @MX2(0))
      Case Else
         Mul(@MX2(0), @MX1(0))      
   End Select
End Sub



Sub t_MATRIX2D.Rotate(fAngle As Double, iOrder As Integer = 0)
   '[ C  S  0 ]
   '[-S  C  0 ]
   '[ 0  0  1 ]
   If fAngle = 0 Then Return
   
   Dim As Double fR, fS, fC
   fR = fAngle * 0.0174532925199433
   fC = Cos(fR)
   fS = Sin(fR)
   
   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   Reset(@MX1(0))
   MX1(0) = fC
   MX1(1) = fS
   MX1(3) = -fS
   MX1(4) = fC

   Select Case iOrder
      Case 0
         Mul(@MX1(0), @MX2(0))
      Case Else
         Mul(@MX2(0), @MX1(0))      
   End Select
End Sub



Sub t_MATRIX2D.Reset(pMX As Double Ptr)
   '[ 1 0 0 ]
   '[ 0 1 0 ]
   '[ 0 0 1 ]
   For i As Integer = 0 To 8
      pMX[i] = 0
   Next
   pMX[0] = 1
   pMX[4] = 1
   pMX[8] = 1
End Sub

Constructor t_MATRIX2D
   Reset(@MX(0))
End Constructor





Screen 19,32
Dim As String sFileName = "Bild.bmp"
Dim As Integer iBmpW, iBmpH, iScreenW, iScreenH
ScreenInfo iScreenW, iScreenH, , , , ,

Dim As Integer iFile = FreeFile
Open sFileName For Input As #iFile
Get #iFile, 19, iBmpW
Get #iFile, 23, iBmpH
Close #iFile

Dim pPixel As UInteger Ptr
pPixel = ImageCreate(iBmpW, iBmpH)

Bload sFileName, pPixel

Dim As t_MATRIX2D tMX
tMX.Translate(-iBmpW/2, -iBmpH/2)'RotationsAchse in Bildmitte verschieben
tMX.Scale(0.5, 0.8, 1)'Skalieren
tMX.Rotate(30, 1)'Rotieren
'tMX.Skew(-45, 0)'Skew
tMX.Translate(iScreenW/2, iScreenH/2, 1)'BildMitte zu ScreenMitte verschieben


'Neue Bildeckpunkte berechnen
Dim As Double aPnt(4, 2)
tMX.MulVector(0, 0, aPnt(0,0), aPnt(0,1))
tMX.MulVector(iBmpW, 0, aPnt(1,0), aPnt(1,1))
tMX.MulVector(0, iBmpH, aPnt(2,0), aPnt(2,1))
tMX.MulVector(iBmpW, iBmpH, aPnt(3,0), aPnt(3,1))


Dim As Integer iX1, iY1, iX2, iY2
iX1 = 2147483647
iY1 = 2147483647
iX2 = -2147483648
iY2 = -2147483648
For i As Integer = 0 To 3
   If aPnt(i, 0) < iX1 Then iX1 = aPnt(i, 0)
   If aPnt(i, 0) > iX2 Then iX2 = aPnt(i, 0)
   If aPnt(i, 1) < iY1 Then iY1 = aPnt(i, 1)
   If aPnt(i, 1) > iY2 Then iY2 = aPnt(i, 1)
Next

tMX.Invert 'Matrix invertieren -> Reverse mapping
'Man könnte auch forward-mappen, jedoch bekommt man dann bei einer Vergrößerung Löcher und eine Interpolation lässt sich auch nicht realisieren
Dim As Double fX, fY
For x As Integer = iX1 To iX2
   For y As Integer = iY1 To iY2      
      tMX.MulVector(x, y, fX, fY)'Src - Pixelpos berechnen
      If (fX >= 0) And (fY >= 0) And (fX < iBmpW) And (fY < iBmpH) Then
         PSet (x, y), Point(fX, fY, pPixel)
      EndIf
   Next
Next


Circle(aPnt(0,0), aPnt(0,1)),4,&HFF00FF00,,,,F
Circle(aPnt(1,0), aPnt(1,1)),4,&HFF00FF00,,,,F
Circle(aPnt(2,0), aPnt(2,1)),4,&HFF00FF00,,,,F
Circle(aPnt(3,0), aPnt(3,1)),4,&HFF00FF00,,,,F


Sleep
If pPixel <> 0 Then ImageDestroy(pPixel)
End
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 28.05.2013, 09:20    Titel: Antworten mit Zitat

Matrix, ein 'Zauberwort' auf das ich wohl so schnell nicht gekommen wäre obwohl es doch eigentlich so nahe liegt... wenn mich mein Verständnis nicht trübt so müsste das ganze sogar schneller sein als die ursprüngliche Berechnung und zudem auch noch recht flexibel. (OpenGL Berechnungen sehr ähnlich)

Wenn es Dir vielleicht nicht zu viel Mühe bereiten würde, könntest Du dem Code ein paar zusätzliche als Hilfestellung dienende Kommentare hinzufügen um ein besseres Verständnis der Mathematik dahinter zu bekommen?

Mit etwas Googlen und dem Code könnte sich vielleicht meine Matrixphobie legen happy
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 28.05.2013, 09:49    Titel: Antworten mit Zitat

meine schulbildung, und die ist auch schon nen weilchen her, reicht leider nicht für matrizen aus... Und wiki ist bei fehlendem hintergrundwissen nicht wirklich hilfreich zwinkern
EDIT:

Trotzdem versuch ichs nochmal

Also dies hier ist eine Drehung um den Punkt P


Da anderenfalls Weltfrieden ausbrechen würde und der Sack Reis in China nicht umkippt
muß die Drehung in der oberen linken Ecke vonstatten gehen. Meinen gewünschten Drehpunkt A
habe ich mal mitgedreht. Und der bekommt als gedreht den Namen A'


Wenn ich jetzt mein gedrehtes Etwas so verschiebe, das A' wieder über A liegt...

Sind dann alle Bedingungen erfüllt das man behaupten kann:
Das Objekt wurde um A gedreht???

Ein einfaches Ja würde mir genügen lächeln
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 28.05.2013, 23:03    Titel: Antworten mit Zitat

Ja Zunge rausstrecken


Im Grunde hat es TPM ja schon genannt...

Code:

tX = offsetx + (X-rotationspunktX) * cos(winkel) - (Y-rotationspunktY) * sin(winkel)
tY = offsety + (X-rotationspunktX) * sin(winkel) + (Y-rotationspunktY) * cos(winkel)


den offset bekommst du durch die x und y verschiebung...

sowas wie
Code:

'pseudocode
offsetx = originalpunktx - gedrehterpunktx
offsety = originalpunkty - gedrehterpunkty

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Eukalyptus



Anmeldungsdatum: 17.05.2013
Beiträge: 11

BeitragVerfasst am: 29.05.2013, 11:38    Titel: Antworten mit Zitat

Wie eine Matrix genau funktioniert, kann ich auch nicht genau erklären.
Aber ich hab etwas Erfahrung, wie man sie benutzt.

Hier mal ein Bleipiel:

Vor dem ersten Sleep wird nur rotiert.
Der Drehpunkt befindet sich oben links.
Code:
tMX.Rotate(i)


Soll sich der Drehpunkt in der Objektmitte befinden, muss man die Matrix zuerst verschieben (Sleep 2)
Code:
tMX.Translate(-70, -40)
tMX.Rotate(i)



Dann kann man die Gewünschte Endposition bestimmen, indem man die Matrix nach dem rotieren nochmals verschiebt:
Code:
tMX.Translate(-70, -40)
tMX.Rotate(i)
tMX.Translate(iScreenW / 2, iScreenH / 2)

Nun wird das Objekt im Objektmittelpunkt gedreht und in der Mitte des Fensters platziert.

Hier der Code:
Code:
Type t_MATRIX2D
   Private:
   MX(9) As Double
   Declare Sub Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
   Declare Sub ResetP(pMX As Double Ptr)
   
   Public:
   Declare Sub GetElements(pMX As Double Ptr)
   Declare Sub Invert
   Declare Sub MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
   Declare Sub Reset
   Declare Sub Rotate(fAngle As Double, iOrder As Integer = 0)
   Declare Sub Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
   Declare Sub Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
   Declare Sub Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
   
   Declare Constructor
End Type



Sub t_MATRIX2D.GetElements(pMX As Double Ptr)
   For i As Integer = 0 To 8
      pMX[i] = MX(i)
   Next
End Sub


Sub t_MATRIX2D.Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
   Dim As Double fS
   For x As Integer = 0 To 2
      For y As Integer = 0 To 2
         fS = 0
         For z As Integer = 0 To 2
            fS += pMX1[x*3+z] * pMX2[z*3+y]
         Next
         MX(x*3+y) = fS
      Next
   Next
End Sub




Sub t_MATRIX2D.MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
   fTX = fX * MX(0) + fY * MX(3) + MX(6)
   fTY = fX * MX(1) + fY * MX(4) + MX(7)
End Sub




Sub t_MATRIX2D.Invert
   '[ a  b  0 ]
   '[ c  d  0 ]
   '[ x  y  1 ]
   
   't = a*d-b*c
   
   '[  d/t -b/t  0 ]
   '[ -c/t  a/t  0 ]
   '[(c*y-d*x)/t -(a*y-b*x)/t  1 ]
   
   Dim As Double fM(9), fT
   GetElements(@fM(0))
   fT = fM(0)*fM(4)-fM(1)*fM(3)
   
   MX(0) = fM(4)/fT
   MX(1) = -fM(1)/fT
   MX(3) = -fM(3)/fT
   MX(4) = fM(0)/fT
   MX(6) = (fM(3)*fM(7)-fM(4)*fM(6)) / fT
   MX(7) = -(fM(0)*fM(7)-fM(1)*fM(6)) / fT
End Sub



Sub t_MATRIX2D.Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
   '[ 1  0  0 ]
   '[ 0  1  0 ]
   '[TX TY  1 ]
   
   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(6) = fTransX
   MX1(7) = fTransY

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub



Sub t_MATRIX2D.Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
   '[ 1 SY  0 ]
   '[SX  1  0 ]
   '[ 0  0  1 ]

   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(1) = fSkewY * 0.0174532925199433
   MX1(3) = fSkewX * 0.0174532925199433

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub





Sub t_MATRIX2D.Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
   '[SX  0  0 ]
   '[ 0 SY  0 ]
   '[ 0  0  1 ]

   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(0) = fScaleX
   MX1(4) = fScaleY

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub



Sub t_MATRIX2D.Rotate(fAngle As Double, iOrder As Integer = 0)
   '[ C  S  0 ]
   '[-S  C  0 ]
   '[ 0  0  1 ]
   If fAngle = 0 Then Return
   
   Dim As Double fR, fS, fC
   fR = fAngle * 0.0174532925199433
   fC = Cos(fR)
   fS = Sin(fR)
   
   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(0) = fC
   MX1(1) = fS
   MX1(3) = -fS
   MX1(4) = fC

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub


Sub t_MATRIX2D.ResetP(pMX As Double Ptr)
   '[ 1 0 0 ]
   '[ 0 1 0 ]
   '[ 0 0 1 ]
   For i As Integer = 0 To 8
      pMX[i] = 0
   Next
   pMX[0] = 1
   pMX[4] = 1
   pMX[8] = 1
End Sub


Sub t_MATRIX2D.Reset
   ResetP(@MX(0))
End Sub

Constructor t_MATRIX2D
   ResetP(@MX(0))
End Constructor







Sub _Clear(iColor As UInteger, iX As Integer, iY As Integer, iW As Integer, iH As Integer, iP As Integer)
   Dim As Any Ptr pScreen = ScreenPtr
   If pScreen = 0 Then Return
   Dim As UInteger Ptr pPixel
   ScreenLock()
   For y As Integer = iY To iY + iH - 1
      pPixel = pScreen + (y * iP) + iX * 4
      For x As Integer = iX To iX + iW - 1
         *pPixel = iColor
         pPixel += 1
      Next
   Next
   ScreenUnlock()
End Sub



Sub _Draw(tMX As t_MATRIX2D, pPnt As Single Ptr, iCnt As Integer)
   Dim As Double fX, fY
   ScreenLock()
   For i As Integer = 0 To iCnt-1
      tMX.MulVector(pPnt[i*2], pPnt[i*2+1], fX, fY)
      Circle(fX, fY),4,&HFF00FF00,,,,F
   Next
   ScreenUnlock()
End Sub



Screen 14,32

Dim As Integer iScreenW, iScreenH, iPitch
ScreenInfo iScreenW, iScreenH, , , iPitch


Dim As Single aPnt(39, 1)
For y As Integer = 0 To 4
   For x As Integer = 0 To 7
      aPnt(y * 8 + x, 0) = x * 20
      aPnt(y * 8 + x, 1) = y * 20
   Next
Next

Dim As t_MATRIX2D tMX


For i As Integer = 0 To 360
   tMX.Reset
   tMX.Rotate(i)
   _Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
   _Draw(tMX, @aPnt(0, 0), 40)
   Sleep(10)
Next


Sleep


For i As Integer = 0 To 360
   tMX.Reset
   tMX.Translate(-70, -40)
   tMX.Rotate(i)
   _Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
   _Draw(tMX, @aPnt(0, 0), 40)
   Sleep(10)
Next


Sleep


For i As Integer = 0 To 360
   tMX.Reset
   tMX.Translate(-70, -40)
   tMX.Rotate(i)
   tMX.Translate(iScreenW / 2, iScreenH / 2)
   _Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
   _Draw(tMX, @aPnt(0, 0), 40)
   Sleep(10)
Next


Sleep
End



Bei den einzelnen Matrixberechnungen kann man noch den Parameter "Order" angeben - Damit legt man fest, ob die ursprüngliche Matrix bei der Matrixmultiplikation auf der linken, oder rechten Seite steht.
Was das genau bewirkt, muss man einfach ausprobieren.


Das obige Programm zeigt eine Forward-Transformation - d.h.: Aus den original Koordinaten werden ganz einfach die Zielkoordinaten berechnet.

Wenn man mit dieser Methode ein Bitmap dreht, dann bekommt man ein Moiré. Einfach deswegen, weil die Zielkoordinaten nie GENAU auf einen Pixel fallen.
Wenn man dann noch skaliert entstehen zusätzlich noch Löcher im Zielbild.

Deshalb muss man ein Bitmap reversemappen - d.h.: Die Matrix wird invertiert und aus einer Zielkoordinate wird die Position im Originalbid berechnet.
Man geht also alle Zielkoordinaten durch und berechnet, welchem Pixel im Originalbild diese entsprechen.
Damit vermeidet man dann das Moiré und die Löcher.


Vielleicht zeigt dieses Programm, was ich meine:
(Evtl. etwas umständlich programmiert, aber mit der FreeBasic-Grafik kenn ich mich noch nicht gut aus. Normalerweise verwende ich immer GDI+)
Als Beispielbild verwende ich ein Bitmap aus dem Example-Ordner und liegt bei mir hier: "C:\Programme\FreeBASIC\examples\libraries\GL\NeHe\data\BG.bmp"
Diesen Pfad vorher anpassen!

Zuerst wird das Bild nur gedreht - es entsteht ein leichtes Moiré
Dann wird das Bild dedreht und vergrößert = Löcher + Moiré
Dann die Reversemapping Methode = sieht schon ganz gut aus
Zuletzt Reverse + Interpolation

Code:
Type t_MATRIX2D
   Private:
   MX(9) As Double
   Declare Sub Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
   Declare Sub ResetP(pMX As Double Ptr)
   
   Public:
   Declare Sub GetElements(pMX As Double Ptr)
   Declare Sub Invert
   Declare Sub MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
   Declare Sub Reset
   Declare Sub Rotate(fAngle As Double, iOrder As Integer = 0)
   Declare Sub Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
   Declare Sub Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
   Declare Sub Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
   
   Declare Constructor
End Type



Sub t_MATRIX2D.GetElements(pMX As Double Ptr)
   For i As Integer = 0 To 8
      pMX[i] = MX(i)
   Next
End Sub


Sub t_MATRIX2D.Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
   Dim As Double fS
   For x As Integer = 0 To 2
      For y As Integer = 0 To 2
         fS = 0
         For z As Integer = 0 To 2
            fS += pMX1[x*3+z] * pMX2[z*3+y]
         Next
         MX(x*3+y) = fS
      Next
   Next
End Sub




Sub t_MATRIX2D.MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
   fTX = fX * MX(0) + fY * MX(3) + MX(6)
   fTY = fX * MX(1) + fY * MX(4) + MX(7)
End Sub




Sub t_MATRIX2D.Invert
   '[ a  b  0 ]
   '[ c  d  0 ]
   '[ x  y  1 ]
   
   't = a*d-b*c
   
   '[  d/t -b/t  0 ]
   '[ -c/t  a/t  0 ]
   '[(c*y-d*x)/t -(a*y-b*x)/t  1 ]
   
   Dim As Double fM(9), fT
   GetElements(@fM(0))
   fT = fM(0)*fM(4)-fM(1)*fM(3)
   
   MX(0) = fM(4)/fT
   MX(1) = -fM(1)/fT
   MX(3) = -fM(3)/fT
   MX(4) = fM(0)/fT
   MX(6) = (fM(3)*fM(7)-fM(4)*fM(6)) / fT
   MX(7) = -(fM(0)*fM(7)-fM(1)*fM(6)) / fT
End Sub



Sub t_MATRIX2D.Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
   '[ 1  0  0 ]
   '[ 0  1  0 ]
   '[TX TY  1 ]
   
   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(6) = fTransX
   MX1(7) = fTransY

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub



Sub t_MATRIX2D.Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
   '[ 1 SY  0 ]
   '[SX  1  0 ]
   '[ 0  0  1 ]

   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(1) = fSkewY * 0.0174532925199433
   MX1(3) = fSkewX * 0.0174532925199433

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub





Sub t_MATRIX2D.Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
   '[SX  0  0 ]
   '[ 0 SY  0 ]
   '[ 0  0  1 ]

   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(0) = fScaleX
   MX1(4) = fScaleY

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub



Sub t_MATRIX2D.Rotate(fAngle As Double, iOrder As Integer = 0)
   '[ C  S  0 ]
   '[-S  C  0 ]
   '[ 0  0  1 ]
   If fAngle = 0 Then Return
   
   Dim As Double fR, fS, fC
   fR = fAngle * 0.0174532925199433
   fC = Cos(fR)
   fS = Sin(fR)
   
   Dim As Double MX1(9), MX2(9)
   GetElements(@MX2(0))
   
   ResetP(@MX1(0))
   MX1(0) = fC
   MX1(1) = fS
   MX1(3) = -fS
   MX1(4) = fC

   Select Case iOrder
      Case 0
         Mul(@MX2(0), @MX1(0))
      Case Else
         Mul(@MX1(0), @MX2(0))
   End Select
End Sub


Sub t_MATRIX2D.ResetP(pMX As Double Ptr)
   '[ 1 0 0 ]
   '[ 0 1 0 ]
   '[ 0 0 1 ]
   For i As Integer = 0 To 8
      pMX[i] = 0
   Next
   pMX[0] = 1
   pMX[4] = 1
   pMX[8] = 1
End Sub


Sub t_MATRIX2D.Reset
   ResetP(@MX(0))
End Sub

Constructor t_MATRIX2D
   ResetP(@MX(0))
End Constructor



Sub _Clear(iColor As UInteger, iX As Integer, iY As Integer, iW As Integer, iH As Integer, iP As Integer)
   Dim As Any Ptr pScreen = ScreenPtr
   If pScreen = 0 Then Return
   Dim As UInteger Ptr pPixel
   ScreenLock()
   For y As Integer = iY To iY + iH - 1
      pPixel = pScreen + (y * iP) + iX * 4
      For x As Integer = iX To iX + iW - 1
         *pPixel = iColor
         pPixel += 1
      Next
   Next
   ScreenUnlock()
End Sub





Type t_IMAGE
   iHeader As UInteger
   iBPP As UInteger
   iWidth As UInteger
   iHeight As UInteger
   iPitch As UInteger
   aUnused(2) As UInteger
   pPixel As UInteger Ptr
End Type


Sub _ForwardMapping(tMX As t_MATRIX2D, pImage As t_IMAGE Ptr, iScreenW As Integer, iScreenH As Integer, iPitch As Integer)
   Dim As UInteger Ptr pScreen = ScreenPtr
   If pScreen = 0 Then Return
   
   Dim As UInteger Ptr pPixel = @pImage->pPixel
   Dim As Integer iBmpW = pImage->iWidth, iBmpH = pImage->iHeight, iBmpP = pImage->iPitch / 4
   iPitch /= 4
   
   Dim As Double fX, fY
   Dim As Integer iX, iY
   ScreenLock()
   For y As Integer = 0 To iBmpH-1
      For x As Integer = 0 To iBmpW-1
         tMX.MulVector(x, y, fX, fY)
         iX = fX
         iY = fY
         If (iX >= 0) And (iY >= 0) And (iX < iScreenW) And (iY < iScreenH) Then
            pScreen[iY * iPitch + iX] = pPixel[y * iBmpP + x]
         EndIf
      Next
   Next
   ScreenUnlock()
End Sub





Sub _ReverseMapping(tMX As t_MATRIX2D, pImage As t_IMAGE Ptr, iScreenW As Integer, iScreenH As Integer, iPitch As Integer)
   Dim As UInteger Ptr pScreen = ScreenPtr
   If pScreen = 0 Then Return
   
   Dim As UInteger Ptr pPixel = @pImage->pPixel
   Dim As Integer iBmpW = pImage->iWidth, iBmpH = pImage->iHeight, iBmpP = pImage->iPitch / 4
   iPitch /= 4
   
   Dim As Double aPnt(4, 2)
   tMX.MulVector(0, 0, aPnt(0,0), aPnt(0,1))
   tMX.MulVector(iBmpW, 0, aPnt(1,0), aPnt(1,1))
   tMX.MulVector(0, iBmpH, aPnt(2,0), aPnt(2,1))
   tMX.MulVector(iBmpW, iBmpH, aPnt(3,0), aPnt(3,1))


   Dim As Integer iX1, iY1, iX2, iY2
   iX1 = iScreenW
   iY1 = iScreenH
   iX2 = 0
   iY2 = 0
   For i As Integer = 0 To 3
      If aPnt(i, 0) < iX1 Then iX1 = aPnt(i, 0)
      If aPnt(i, 0) > iX2 Then iX2 = aPnt(i, 0)
      If aPnt(i, 1) < iY1 Then iY1 = aPnt(i, 1)
      If aPnt(i, 1) > iY2 Then iY2 = aPnt(i, 1)
   Next
   If iX1 < 0 Then
      iX1 = 0
   ElseIf iX1 >= iScreenW Then
      iX1 = iScreenW-1
   EndIf
   If iX2 < 0 Then
      iX2 = 0
   ElseIf iX2 >= iScreenW Then
      iX2 = iScreenW-1
   EndIf
   If iY1 < 0 Then
      iY1 = 0
   ElseIf iY1 >= iScreenH Then
      iY1 = iScreenH-1
   EndIf
   If iY2 < 0 Then
      iY2 = 0
   ElseIf iY2 >= iScreenH Then
      iY2 = iScreenH-1
   EndIf
   
   
   tMX.Invert
   Dim As Double fX, fY
   Dim As Integer iX, iY
   ScreenLock()
   For x As Integer = iX1 To iX2
      For y As Integer = iY1 To iY2      
         tMX.MulVector(x, y, fX, fY)
         iX = fX
         iY = fY
         If (iX >= 0) And (iY >= 0) And (iX < iBmpW) And (iY < iBmpH) Then
            pScreen[y * iPitch + x] = pPixel[iY * iBmpP + iX]
         EndIf
      Next
   Next
   ScreenUnlock()
End Sub




Type t_ARGB
   B As UByte
   G As UByte
   R As UByte
   A As UByte
End Type

Sub _ReverseMapping_Interpolate(tMX As t_MATRIX2D, pImage As t_IMAGE Ptr, iScreenW As Integer, iScreenH As Integer, iPitch As Integer)
   Dim As UInteger Ptr pScreen = ScreenPtr
   If pScreen = 0 Then Return
   
   Dim As UInteger Ptr pPixel = @pImage->pPixel
   Dim As Integer iBmpW = pImage->iWidth, iBmpH = pImage->iHeight, iBmpP = pImage->iPitch / 4
   iPitch /= 4
   
   Dim As Double aPnt(4, 2)
   tMX.MulVector(0, 0, aPnt(0,0), aPnt(0,1))
   tMX.MulVector(iBmpW, 0, aPnt(1,0), aPnt(1,1))
   tMX.MulVector(0, iBmpH, aPnt(2,0), aPnt(2,1))
   tMX.MulVector(iBmpW, iBmpH, aPnt(3,0), aPnt(3,1))


   Dim As Integer iX1, iY1, iX2, iY2
   iX1 = iScreenW
   iY1 = iScreenH
   iX2 = 0
   iY2 = 0
   For i As Integer = 0 To 3
      If aPnt(i, 0) < iX1 Then iX1 = aPnt(i, 0)
      If aPnt(i, 0) > iX2 Then iX2 = aPnt(i, 0)
      If aPnt(i, 1) < iY1 Then iY1 = aPnt(i, 1)
      If aPnt(i, 1) > iY2 Then iY2 = aPnt(i, 1)
   Next
   If iX1 < 0 Then
      iX1 = 0
   ElseIf iX1 >= iScreenW Then
      iX1 = iScreenW-1
   EndIf
   If iX2 < 0 Then
      iX2 = 0
   ElseIf iX2 >= iScreenW Then
      iX2 = iScreenW-1
   EndIf
   If iY1 < 0 Then
      iY1 = 0
   ElseIf iY1 >= iScreenH Then
      iY1 = iScreenH-1
   EndIf
   If iY2 < 0 Then
      iY2 = 0
   ElseIf iY2 >= iScreenH Then
      iY2 = iScreenH-1
   EndIf
   
   
   tMX.Invert
   Dim As Double fX, fY
   Dim As Integer iSX, iSY
   Dim As Single fFX, fFY, fFX1, fFY1
   Dim As UInteger aColor(2, 2)
   Dim As t_ARGB Ptr aARGB(2, 2)
   
   For iX As Integer = 0 To 1
      For iY As Integer = 0 To 1
         aARGB(iX, iY) = @aColor(iX, iY)   
      Next
   Next
   
      
   ScreenLock()
   For x As Integer = iX1 To iX2
      For y As Integer = iY1 To iY2      
         tMX.MulVector(x, y, fX, fY)
         
         If (fX >= 0) And (fY >= 0) And (fX < iBmpW) And (fY < iBmpH) Then
            
            iSX = Int(fX)
            iSY = Int(fY)
            fFX = Frac(fX)
            fFY = Frac(fY)
         
            For iLX As Integer = iSX To iSX + 1
               For iLY As Integer = iSY To iSY + 1
                  If (iLX < 0) Or (iLY < 0) Or (iLX >= iBmpW) Or (iLY >= iBmpH) Then
                     aColor(iLX - iSX, iLY - iSY) = 0
                  Else
                     aColor(iLX - iSX, iLY - iSY) = pPixel[iLY * iBmpP + iLX]
                  EndIf
               Next
            Next
            
            fFX1 = 1 - fFX
            fFY1 = 1 - fFY
         
            'Interpolate X aColor(0, 0) <-> aColor(1, 0)
            aARGB(0, 0)->A = aARGB(0, 0)->A * fFX1 + aARGB(1, 0)->A * fFX
            aARGB(0, 0)->R = aARGB(0, 0)->R * fFX1 + aARGB(1, 0)->R * fFX
            aARGB(0, 0)->G = aARGB(0, 0)->G * fFX1 + aARGB(1, 0)->G * fFX
            aARGB(0, 0)->B = aARGB(0, 0)->B * fFX1 + aARGB(1, 0)->B * fFX
         
            'Interpolate X aColor(0, 1) <-> aColor(1, 1)
            aARGB(0, 1)->A = aARGB(0, 1)->A * fFX1 + aARGB(1, 1)->A * fFX
            aARGB(0, 1)->R = aARGB(0, 1)->R * fFX1 + aARGB(1, 1)->R * fFX
            aARGB(0, 1)->G = aARGB(0, 1)->G * fFX1 + aARGB(1, 1)->G * fFX
            aARGB(0, 1)->B = aARGB(0, 1)->B * fFX1 + aARGB(1, 1)->B * fFX
         
            'Interpolate Y aColor(0, 0) <-> aColor(0, 1)
            aARGB(0, 0)->A = aARGB(0, 0)->A * fFY1 + aARGB(0, 1)->A * fFY
            aARGB(0, 0)->R = aARGB(0, 0)->R * fFY1 + aARGB(0, 1)->R * fFY
            aARGB(0, 0)->G = aARGB(0, 0)->G * fFY1 + aARGB(0, 1)->G * fFY
            aARGB(0, 0)->B = aARGB(0, 0)->B * fFY1 + aARGB(0, 1)->B * fFY
         
            pScreen[y * iPitch + x] = aColor(0, 0)
         EndIf
      Next
   Next
   ScreenUnlock()
End Sub





Screen 19,32
Dim As String sFileName = "C:\Programme\FreeBASIC\examples\libraries\GL\NeHe\data\BG.bmp"
Dim As Integer iBmpW, iBmpH, iScreenW, iScreenH, iPitch
ScreenInfo iScreenW, iScreenH, , , iPitch

Dim As Integer iFile = FreeFile
Open sFileName For Input As #iFile
Get #iFile, 19, iBmpW
Get #iFile, 23, iBmpH
Close #iFile

Dim pImg As Any Ptr
pImg = ImageCreate(iBmpW, iBmpH)

Bload sFileName, pImg

Dim As t_MATRIX2D tMX



tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Rotate(45)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ForwardMapping(tMX, pImg, iScreenW, iScreenH, iPitch)


Sleep



tMX.Reset
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Scale(5, 5)
tMX.Rotate(10)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ForwardMapping(tMX, pImg, iScreenW, iScreenH, iPitch)


Sleep

tMX.Reset
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Scale(5, 5)
tMX.Rotate(10)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ReverseMapping(tMX, pImg, iScreenW, iScreenH, iPitch)


Sleep


tMX.Reset
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Scale(5, 5)
tMX.Rotate(10)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ReverseMapping_Interpolate(tMX, pImg, iScreenW, iScreenH, iPitch)


Sleep
If pImg <> 0 Then ImageDestroy(pImg)
End
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 565
Wohnort: Jüterbog

BeitragVerfasst am: 30.05.2013, 19:32    Titel: Antworten mit Zitat

@Eukalyptus: UI.... das ist ein Brett...

Also ich bedank mich mal artig bei allen und betrachte mein Problem als
gelöst

Da mein Ergebnis sehr fragwürdig ist werd ich mich wohl doch auf Fremdcode verlassen, was in meinem Fall das beste ist

happy
Code:

'definitely inspired by D.J.Peters'>>Multiput<<
'original code at: http://www.freebasic.net/forum/viewtopic.php?f=8&t=19303

 #include "fbgfx.bi"
using FB

'******************************************************************************
type vector
  x as double
  y as double
end type
'******************************************************************************

declare sub RotPut(img as any ptr,posx as integer,posy as integer, pivotx as integer=0, pivoty as integer=0, arcus as double)

sub RotPut(img as any ptr,posx as integer,posy as integer, pivotx as integer=0, pivoty as integer=0, arcus as double)
  'posx,posy      Position,es gilt Koordinatensystem Screen
  'pivotx,pivoty  Drehpunkt als Offset von Pixel(0,0) links oben, es gilt Koordinatensystem Screen
  dim as integer imgw,imgh                    'Größe Originalimage
  dim as integer xmin,xmax,ymin,ymax          'Größenermittlung temporäres Image
  dim as any ptr imgtmp                   'temporäres Image
  dim as integer imgtmpw,imgtmph              'Größe temp. Image
  dim as double x,y                           'Hilfsvariablen
  dim  as integer ii,kk
  dim as vector Points(6)                     'Punkte und Vektoren
  dim as uinteger pixelcolor                  'Farbwert
  dim as uinteger ptr pixaddr,pixaddrtmp      'Adressen der Pixel
  dim as Image ptr header,headertmp           'um an die Daten im Imageheader zu kommen
  header=img
  imgw=header->width
  imgh=header->height

  'Verortung Originalimage, Pixel (0,0) ist im Koordinatenursprung und braucht nicht berechnet zu werden
  Points(1).x=0
  Points(1).y=-imgh
  Points(2).x=imgw
  Points(2).y=-imgh
  Points(3).x=imgw
  Points(3).y=0
  Points(4).x=pivotx                          'gewünschter Drehpunkt
  Points(4).y=-pivoty                         'Anpassung an kartesisches Koordinatensystem

  'Origalimage Eckpunkte drehen um Größe und Lage des temp Images zu ermitteln
  for i as integer=1 to 4
    if i<4 then
      x= Points(i).x * cos(arcus) - Points(i).y * sin(arcus)
      y= Points(i).x * sin(arcus) + Points(i).y * cos(arcus)
      Points(i).x= x
      Points(i).y= y
      if x<xmin then  xmin=x
      if x>xmax then  xmax=x
      if y<ymin then  ymin=y
      if y>ymax then  ymax=y
    else
      Points(5).x= Points(i).x * cos(arcus) - Points(i).y * sin(arcus)
      Points(5).y= Points(i).x * sin(arcus) + Points(i).y * cos(arcus)
    end if
  next i

  'Verschiebung berechnen
  Points(6).x= Points(4).x - Points(5).x
  Points(6).y= Points(4).y - Points(5).y

  Points(0).x=xmin                            'Position linke obere Ecke des temp. Images
  Points(0).y=ymax
  Points(1).x=1                               'Zeilenvektor
  Points(1).y=0
  Points(2).x=0                               'Spaltenvektor
  Points(2).y=-1
  for i as integer=0 to 2
    if i>0 then
      x= Points(i).x * cos(-arcus) - Points(i).y * sin(-arcus)
      y= Points(i).x * sin(-arcus) + Points(i).y * cos(-arcus)
      Points(i).x= x
      Points(i).y= y
    else
      Points(3).x= Points(i).x * cos(-arcus) - Points(i).y * sin(-arcus)
      Points(3).y= Points(i).x * sin(-arcus) + Points(i).y * cos(-arcus)
    end if
  next i

  'temp. Image erzeugen
  imgtmpw=xmax-xmin
  imgtmph=ymax-ymin
  imgtmp=imagecreate(imgtmpw,imgtmph,&HFF00FF)
  if imgtmp then
    headertmp=imgtmp
    'Scan
    dim as integer switch=0
    for k as integer=0 to imgtmph-1
      for i as integer=0 to imgtmpw-1
        ii=int(Points(3).x + Points(1).x*i + Points(2).x*k)
        kk=int(Points(3).y + Points(1).y*i + Points(2).y*k)
        if (ii>=0) and (ii<imgw-1) and (kk<=0) and (kk>-imgh+1) then
          'pset imgtmp,(i,k),point(ii,-kk,img)'<---- Flaschenhals!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
          'dies ist schneller.....
          pixaddr=img + 32 + (-kk * header->pitch) + (ii * header->bpp)
          pixaddrtmp=imgtmp + 32 + (k * headertmp->pitch) + (i * headertmp->bpp)
          *pixaddrtmp=*pixaddr
        end if
      next i
    next k
    put (posx + Points(0).x + Points(6).x,posy - Points(0).y - Points(6).y),imgtmp,trans
    imagedestroy imgtmp
  end if
end sub
'******************************************************************************
'******************************************************************************
'******************************************************************************
screen 19,32

'Originalimage
dim img as any ptr'Image

img=imagecreate(400,300)
if img then
  bload "pattern.bmp",img
  for arcus as double=0 to 6.28 step .01
    screenlock
    cls
    RotPut(img,300,200,200,150,arcus)
    screenunlock
    sleep 2
  next arcus
  imagedestroy img
end if

sleep
end


edit: Code korrigiert
edit2: Flaschenhals entfernt, Farbwert wird direkt von einem Image ins andere kopiert... bedeutend schneller
Mutton
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz