Seite 1 von 2

Bild (ver-)zerren?

Verfasst: 14.05.2007 14:53
von Scarabol
Hallo Leute,

denke die meisten kennen MSPaint darum nem ich das jetzt mal als Beispiel, gibt es eine Funktion die der MSPaint Funktion "Zerren" entspricht?

Gruß
Scarabol

Verfasst: 14.05.2007 15:15
von STARGÅTE
klar wenn du dein Sprite zum Sprite3D machst kannst du mit

Code: Alles auswählen

TransformSprite3D(#Sprite3D, x1, y1, x2, y2, x3, y3, x4, y4) 
dein Bild verzerren.
Wenn dein Bild 64*64 z.B. ist dann kannst du das leicht nach rechts kippen lassen:

Code: Alles auswählen

von so :
 __ 
|  |
|__|

mit :
TransformSprite3D(#Sprite3D, 32, 0, 96, 0, 64, 64, 0, 64)

zu :
  __ 
 /  /
/__/
Das wäre dann genau das was Paint auch macht.

Verfasst: 14.05.2007 15:22
von Scarabol
Cool danke!

Ich probiers mal...

Hat vielleicht noch einer nen Code wie man sowas "manuell" machen kann?
Da mit Sprite3D neue Probs auf mich zu kommen ;-)

Gruß
Scarabol

Verfasst: 14.05.2007 15:37
von Ligatur
Unter Windows lässt sich das mit

Code: Alles auswählen

PlgBlt_(hdcDest.l, *PlgPoints.POINT, hdcSource.l, xSrc.l, ySrc.l, wSrc.l, hSrc.l, Mask.l, xMask.l, yMask.l)
bewerkstellisgen wobei PlgPoints ein Zeiger auf ein Array mit drei Punkten ist, die ein Parallelogramm beschreiben.

Verfasst: 14.05.2007 16:20
von STARGÅTE
Ich glaube das hilft ihm auch nicht weiter.

@Scarabol

Willst du jetzt so ne art Procedure wo du wie in PAINT sagen kannst :

Stecken (in px) (x,y)
und
Zerren (in Grad) (x,y)

Verfasst: 14.05.2007 16:26
von Scarabol
Ja genau daran hatte ich gedacht wobei mir eigentlich auch schon eine RotateImage Procedure reichen würd. Hab sowas im Codearchiv gefunden aber da kann ich keinen Winkel angeben :cry: .

[Edit]
Hab gerad in der API rumgestöbert und bin drauf gekommen das ich das wahrscheinlich manuell über die Winkelfunktionen mache. Bin aber offen für schnellere Varianten :wink: .
[/Edit]

Gruß
Scarabol

Verfasst: 14.05.2007 16:37
von STARGÅTE

Code: Alles auswählen

Procedure DisplaySprite3D_Paint(Sprite, x, y, xZoom, yZoom, xZerr.f, yZerr.f, Trans) 
 xZerr = xZerr*(#PI/180) 
 yZerr = -yZerr*(#PI/180) 
 TransformSprite3D(Sprite, x+Tan(xZerr)*xZoom, y, x+xZoom+Tan(xZerr)*xZoom, y+Tan(yZerr)*xZoom, x+xZoom, y+yZoom+Tan(yZerr)*xZoom, x, y+yZoom) 
 DisplaySprite3D(Sprite, x, y, Trans) 
EndProcedure 
Bitte schön ^^

INFO:
xZoom, yZoom müssen in Pixel abgegeben werden (also die Sprite Größe)
xZerr, yZerr müssen in Grad angegeben werden, aber nur -89° bis 89°

Also wie in Paint

habe es auchgetestet, ergebnis ist wie in Paint :allright:

Verfasst: 14.05.2007 16:38
von Scarabol
Vielen Dank!
Scarabol :allright: :allright: :allright:

Verfasst: 14.05.2007 19:42
von PureLust
Hi Scarabol, ...

da Du ja immer nur von "Bild" aber nirgends von "Sprite" gesprochen hast, weiss ich natürlich nicht ob Du in Deinem Programm überhaupt Screens und Sprites benutzt und ob sich Dein Anliegen überhaupt mit den von Stargate vorgeschlagenen Sprite(3D) Befehlen realisieren lässt.
Scarabol hat geschrieben:... wobei mir eigentlich auch schon eine RotateImage Procedure reichen würd. Hab sowas im Codearchiv gefunden aber da kann ich keinen Winkel angeben :cry: .
Ich hatte damals mal eine Rotationsroutine (inkl. Filterung) geschrieben, mit der man Bilder in jedem beliebigen Winkel drehen kann.
Falls es Dir also um die Rotation von Images und nicht von Sprites geht, kannst Du ja mal HIER nachschauen, ob Du mit der Routine was anfangen kannst.
Es gibt sowohl eine reine PB-Lösung (die Plattformübergreifend laufen sollte) als auch eine schnellere aber dafür eben auf Windows limitierte WinAPI-Version (weiter hinten im Thread).

Vermutlich ist das aber noch alles in PB3.94, so dass Du's noch auf PB4 umsetzen müsstest.

Gruß und viel Erfolg, PL. :allright:

Verfasst: 15.05.2007 00:11
von Ligatur
STARGÅTE hat geschrieben: Ich glaube das hilft ihm auch nicht weiter.

[...]
Da er nicht mit 3DSprites arbeiten wollte würde PlgBlt schon etwas bringen. Ich habe mal ein kleines Beispiel dazu geschrieben, bei gleichen Winkeln für x und y geht auch drehen ohne Probleme.

Code: Alles auswählen

EnableExplicit


UseJPEGImageDecoder()

;- Prozedur Zerren, verformt ein Bild in ImgSource zu hdcDest. Bezugspunkt ist die untere linke Ecke
; ->	Source: ImageNr, falls *imgRect = 0 - Devicecontext des Sourceimage ansonsten
;			*imgRect: Ausschnitt aus hdcSource, falls Source hdc, ansonsten 0, falls ImageNr. übergeben wird
;			xAngle, yAngle: Winkel, um den verzerrt werden soll
;			xZoom, yZoom: Faktor, um den skaliert werden soll
;			Maske: Maske, die bestimmt, welche Bits berücksichtigt werden sollen (ImageID bzw. Bitmaphandle)
;			mx, my: Startpunkt, ab der die Maske benutzt werden soll 
Procedure Zerren(Source, hdcDest, *imgRect.RECT, xAngle.d, yAngle.d, xZoom.d = 1, yZoom.d = 1, Maske = 0, mx = 0, my = 0)
	Protected x, y, w, h, hz, wz, hdcSrc
	Dim Plg.POINT(2)		; Array für Paralelogramm
	
	If *imgRect = 0
		; Source ist ein Image, Abmessungen von Image holen
		x = 0
		y = 0
		w = ImageWidth(Source)
		h = ImageHeight(Source)
	Else
	; Source ist ein Devicekontext, Abmessungen aus *imgRect
		x = *imgRect\left
		y = *imgRect\top
		w = (*imgRect\right - *imgRect\left)
		h = (*imgRect\bottom - *imgRect\top)
	EndIf
	; Gezoomte Breite und Höhe bestimmen um damit das Parallelogramm zu berechnen
	wz = w * xZoom
	hz = h * yZoom
	
	;Parallelogramm berechnen
	Plg(0)\x = hz * Tan(xAngle)
	Plg(0)\y = 0
	Plg(1)\x = wz + hz * Tan(xAngle)
	Plg(1)\y = wz * Tan(yAngle)
	Plg(2)\x = 0
	Plg(2)\y = hz
	
	If Plg(0)\x < 0
		;Falls gezerrtes Image nach links gestaucht wird so weit nach rechts verschieben bis kein negatives x vorhanden
		Plg(1)\x + Plg(0)\x
		Plg(2)\x + Plg(0)\x
		Plg(0)\x = 0
	EndIf
	
	If Plg(1)\y < 0
		;Falls gezerrtes Image nach oben gestaucht wird so weit nach unten verschieben bis kein negatives y vorhanden
		Plg(0)\y + Plg(1)\y
		Plg(2)\y + Plg(1)\y
		Plg(1)\y = 0
	EndIf
	
	If *imgRect = 0
		; hdcSrc muß erstellt werden, der einfachheit halber mit Hilfe des DestHDC
		hdcSrc = CreateCompatibleDC_(hdcDest)
      SelectObject_(hdcSrc, ImageID(Source))
	Else
		hdcSrc = Source
	EndIf
	
	PlgBlt_(hdcDest, @Plg(0), hdcSrc, x, y, w, h, Maske, mx, my)
		
EndProcedure

#WND_MAIN = 0

#ima_Picture = 0
#ima_Mask = 1
#ima_Dest = 2
; Gadgetkonstanten
Enumeration 
	#img_Picture
	#btn_Load
	#str_Picture
	#btn_LoadMask
	#str_Mask
	#str_AngleX
	#str_AngleY
	#str_ZoomX
	#str_ZoomY
	#str_SrcLeft
	#str_SrcTop
	#str_SrcRight
	#str_SrcBottom
	#str_MaskLeft
	#str_MaskTop
	#btn_Start
EndEnumeration

;Konstanten für funktionslose Gadgets
Enumeration #PB_Compiler_EnumerationValue
	#txt_AngleX
	#txt_AngleY
	#txt_ZoomX
	#txt_ZoomY
	#txt_SrcLeft
	#txt_SrcTop
	#txt_SrcRight
	#txt_SrcBottom
	#txt_MaskLeft
	#txt_MaskTop
EndEnumeration

Define.l Event, hwnd, AngleX.d, AngleY.d, ZoomX.d, ZoomY.d, x, y, w, h
Define.l imaDest, hdcDest, hdcSrc, SrcRect.RECT
Define.s File, Mask

hwnd = OpenWindow(#WND_MAIN, 0, 0, 800, 600, "PlgBlt", #PB_Window_SystemMenu)
CreateGadgetList(hwnd)

ImageGadget(#img_Picture, 0, 0, 700, 600, 0, #PB_Image_Border)
ButtonGadget(#btn_Load, 710, 10, 80, 30, "Laden")
StringGadget(#str_Picture, 700, 45, 100, 20, "", #PB_String_ReadOnly)
ButtonGadget(#btn_LoadMask, 710, 75, 80, 30, "Maske")
StringGadget(#str_Mask, 700, 110, 100, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_AngleX, 710, 140, 80, 15, "X Winkel")
StringGadget(#str_AngleX, 710, 160, 80, 20, "0")
TextGadget(#txt_AngleY, 710, 185, 80, 15, "Y Winkel")
StringGadget(#str_AngleY, 710, 205, 80, 20, "0")
TextGadget(#txt_ZoomX, 710, 235, 80, 15, "Zoom X")
StringGadget(#str_ZoomX, 710, 255, 80, 20, "1")
TextGadget(#txt_ZoomY, 710, 280, 80, 15, "Zoom Y")
StringGadget(#str_ZoomY, 710, 300, 80, 20, "1")
TextGadget(#txt_SrcLeft, 710, 330, 20, 20, "SL")
StringGadget(#str_SrcLeft, 735, 330, 55,20, "-1")
TextGadget(#txt_SrcTop, 710, 355, 20, 20, "ST")
StringGadget(#str_SrcTop, 735, 355, 55,20, "0")
TextGadget(#txt_SrcRight, 710, 380, 20, 20, "SR")
StringGadget(#str_SrcRight, 735, 380, 55,20, "0")
TextGadget(#txt_SrcBottom, 710, 405, 20, 20, "SB")
StringGadget(#str_SrcBottom, 735, 405, 55,20, "0")
TextGadget(#txt_MaskLeft, 710, 435, 20, 20, "ML")
StringGadget(#str_MaskLeft, 735, 435, 55,20, "0")
TextGadget(#txt_MaskTop, 710, 460, 20, 20, "SB")
StringGadget(#str_MaskTop, 735, 460, 55,20, "0")
ButtonGadget(#btn_Start, 710, 560, 80, 30, "Start")

Repeat
	Event = WaitWindowEvent()
	If Event = #PB_Event_Gadget
		Select EventGadget()
			Case #btn_Load
				File = OpenFileRequester("Bild wählen", "", "Bilddateien (*.jpg;*.jpeg;*.bmp)|*.jpg;*.jpeg;*.bmp|JPG Dateien (*.jpg;*.jpeg)|*.jpg;*.jpeg|Bitmap Dateien (*.bmp)|*.bmp|Alle Dateien (*.*)|*.*", 0)
				If File <> ""
					LoadImage(#ima_Picture, File)
					If ImageWidth(#ima_Picture) > 700
						ResizeImage(#ima_Picture, 700, ImageHeight(#ima_Picture) * 700 / ImageWidth(#ima_Picture))
					EndIf
					SetGadgetState(#img_Picture, ImageID(#ima_Picture))
					SetGadgetText(#str_Picture, GetFilePart(File))
					SetGadgetText(#str_SrcLeft, "0")
					SetGadgetText(#str_SrcTop, "0")
					SetGadgetText(#str_SrcRight, Str(ImageWidth(#img_Picture)))
					SetGadgetText(#str_SrcBottom, Str(ImageHeight(#img_Picture)))
				EndIf
			Case #btn_LoadMask
				File = OpenFileRequester("Bild wählen", "", "Bilddateien (*.jpg;*.jpeg;*.bmp)|*.jpg;*.jpeg;*.bmp|JPG Dateien (*.jpg;*.jpeg)|*.jpg;*.jpeg|Bitmap Dateien (*.bmp)|*.bmp|Alle Dateien (*.*)|*.*", 0)
				If File <> ""
					LoadImage(#ima_Mask, File)
					SetGadgetText(#str_Mask, GetFilePart(File))
				Else
					FreeImage(#ima_Mask)
					SetGadgetText(#str_Mask, "")
				EndIf
			Case #btn_Start
				AngleX = ValD(GetGadgetText(#str_AngleX)) * 3.14159 / 180
				AngleY = ValD(GetGadgetText(#str_AngleY)) * 3.14159 / 180
				ZoomX = ValD(GetGadgetText(#str_ZoomX))
				ZoomY = ValD(GetGadgetText(#str_ZoomY))
				CreateImage(#ima_Dest, 700, 600)
				hdcDest = StartDrawing(ImageOutput(#ima_Dest))
					hdcSrc = CreateCompatibleDC_(hdcDest)
					SelectObject_(hdcSrc, ImageID(#ima_Picture))
					SrcRect\left = Val(GetGadgetText(#str_SrcLeft))
					SrcRect\top = Val(GetGadgetText(#str_SrcTop))
					SrcRect\right = Val(GetGadgetText(#str_SrcRight))
					SrcRect\bottom = Val(GetGadgetText(#str_SrcBottom))
					If IsImage(#ima_Mask)
						Zerren(hdcSrc, hdcDest, @SrcRect, AngleX, AngleY, ZoomX, ZoomY, ImageID(#ima_Mask), Val(GetGadgetText(#str_MaskLeft)), Val(GetGadgetText(#str_MaskTop)))
					Else
						Zerren(hdcSrc, hdcDest, @SrcRect, AngleX, AngleY, ZoomX, ZoomY)
					EndIf
					DeleteDC_(hdcSrc)
				StopDrawing()
				SetGadgetState(#img_Picture, ImageID(#ima_Dest))
		EndSelect
	EndIf 
Until Event = #PB_Event_CloseWindow
// Edit //
Sollen Drehwinkel über 90° zulässig sein muß der Teil wo die Koordinaten für das Parallelogramm berechnet werden entsprechend angepasst werden.