Bild (ver-)zerren?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Bild (ver-)zerren?

Beitrag 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
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag 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
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag 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.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag 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)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag 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
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag 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:
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Vielen Dank!
Scarabol :allright: :allright: :allright:
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag 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:
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag 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.
Antworten