Bild (ver-)zerren?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Ich habe das Programm noch mal ein wenig verbessert, nun sind auch echtes drehen möglich und beim drehen sind alle Winkel möglich.

Code: Alles auswählen

EnableExplicit 


; 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
   #btn_Pull
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 

#Mode_Pull = 0
#Mode_Rotate = 1

#WND_MAIN = 0 

Enumeration 
	#ima_Picture 
	#ima_Mask 
	#ima_MaskTmp
	#ima_Dest
EndEnumeration

UseJPEGImageDecoder() 

;- Prozedur Zerren, verformt ein Bild in ImgSource zu hdcDest. Bezugspunkt ist die untere linke Ecke 
; ->   Mode: #Mode_Pull: Verzerren; #Mode_Rotate: Drehen
;			 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(Mode, Source, hdcDest, *imgRect.RECT, xAngle.d, yAngle.d = 0 , xZoom.d = 1, yZoom.d = 1, Maske = 0, mx = 0, my = 0) 
   Protected x, y, w, h, hz, wz, d, wk.d, hdcSrc , sz, xmin, xma, ymin, ymax
   Dim Plg.POINT(2)      ; Array für Paralelogramm 
   
   sz = ElapsedMilliseconds()
   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 = Int(w * xZoom)
   hz = Int(h * yZoom)
    
   ;Parallelogramm berechnen
   If Mode = #Mode_Pull
	   Plg(0)\x = Int(hz * Tan(xAngle))
	   Plg(0)\y = 0 
	   Plg(1)\x = wz + Int(hz * Tan(xAngle))
	   Plg(1)\y = Int(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)\x < 0 
	      ;Falls gezerrtes Image nach links gestaucht wird so weit nach rechts verschieben bis kein negatives x vorhanden 
	      Plg(0)\x - Plg(1)\x 
	      Plg(2)\x - Plg(1)\x 
	      Plg(1)\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 
	 ElseIf Mode = #Mode_Rotate
	 		Plg(0)\x = Int(hz * Sin(xAngle))
	 		Plg(0)\y = hz - Int(hz * Cos(xAngle))
	 		d = Sqr(hz * hz + wz * wz)
	 		wk = ATan(wz / hz)
	 		Plg(1)\x = Int(d * Sin(xAngle + wk))
	 		Plg(1)\y = hz - Int(d * Cos(xAngle + wk))
	 		Plg(2)\x = 0
	 		Plg(2)\y = hz
	 		; Kleinsten x - Wert herausfinden
	 		xmin = Plg(0)\x
	 		If Plg(1)\x < xmin : xmin = Plg(1)\x : EndIf
	 		If Plg(2)\x < xmin : xmin = Plg(2)\x : EndIf
	 		If (Plg(1)\x + Plg(2)\x - Plg(0)\x) < xmin : xmin = Plg(1)\x + Plg(2)\x - Plg(0)\x : EndIf
	 		Plg(0)\x - xmin
	 		Plg(1)\x - xmin
	 		Plg(2)\x - xmin
	 		ymin = Plg(0)\y
	 		If Plg(1)\y < ymin : ymin = Plg(1)\y : EndIf
	 		If Plg(2)\y < ymin : ymin = Plg(2)\y : EndIf
	 		If (Plg(1)\y + Plg(2)\y - Plg(0)\y) < ymin : ymin = Plg(1)\y + Plg(2)\y - Plg(0)\y : EndIf
	 		Plg(0)\y - ymin
	 		Plg(1)\y - ymin
	 		Plg(2)\y - ymin
	 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) 
   
   If *imgRect = 0
   	DeleteDC_(hdcSrc)
   EndIf
   SetWindowTitle(#WND_MAIN, "PlgBlt - " + Str(ElapsedMilliseconds() - sz))
EndProcedure 

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, "Drehen")
ButtonGadget(#btn_Pull, 710, 525, 80, 30, "Zerren") 

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_MaskTmp, File)
               If IsImage(#ima_Mask)
               	FreeImage(#ima_Mask)
               EndIf
               CreateImage(#ima_Mask, 700, 600, 1)
               StartDrawing(ImageOutput(#ima_Mask))
               	DrawImage(ImageID(#ima_MaskTmp), 0, 0)
               StopDrawing() 
               SetGadgetText(#str_Mask, GetFilePart(File)) 
            Else
               If IsImage(#ima_Mask) : FreeImage(#ima_Mask) : EndIf
               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(#Mode_Rotate, hdcSrc, hdcDest, @SrcRect, AngleX, AngleY, ZoomX, ZoomY, ImageID(#ima_Mask), Val(GetGadgetText(#str_MaskLeft)), Val(GetGadgetText(#str_MaskTop))) 
               Else 
                  Zerren(#Mode_Rotate, hdcSrc, hdcDest, @SrcRect, AngleX, AngleY, ZoomX, ZoomY) 
               EndIf 
               DeleteDC_(hdcSrc) 
            StopDrawing() 
            SetGadgetState(#img_Picture, ImageID(#ima_Dest)) 
         Case #btn_Pull 
            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(#Mode_Pull, hdcSrc, hdcDest, @SrcRect, AngleX, AngleY, ZoomX, ZoomY, ImageID(#ima_Mask), Val(GetGadgetText(#str_MaskLeft)), Val(GetGadgetText(#str_MaskTop))) 
               Else 
                  Zerren(#Mode_Pull, hdcSrc, hdcDest, @SrcRect, AngleX, AngleY, ZoomX, ZoomY) 
               EndIf 
               DeleteDC_(hdcSrc) 
            StopDrawing() 
            SetGadgetState(#img_Picture, ImageID(#ima_Dest)) 
      EndSelect 
   EndIf 
Until Event = #PB_Event_CloseWindow
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

Das gleiche wie TransformSprite3D nur über GDI: :wink:

Code: Alles auswählen

Structure QUADBLT_VERTEX 
x.l 
y.l 
EndStructure 

Structure QUADBLT_QUAD 
v.QUADBLT_VERTEX[4] 
EndStructure 

Structure QUADBLT_TRIANGLE 
v.QUADBLT_VERTEX[3] 
EndStructure 

Procedure QuadBlt(hdcDest.l,*points.QUADBLT_QUAD,hdcSrc.l,lXSrc.l,lYSrc.l,lWidth.l,lHeight.l) 
If hdcDest=0 Or *points=0 Or hdcSrc=0 
ProcedureReturn #False 
EndIf 

GetClipBox_(hdcSrc,clipbox.rect) 
If lXSrc+lWidth>clipbox\right-clipbox\left Or lYSrc+lHeight>clipbox\bottom-clipbox\top Or lXSrc<0 Or lYSrc<0 Or lWidth<=0 Or lHeight<=0 
ProcedureReturn #False 
EndIf 
rectrgn=CreateRectRgn_(clipbox\left,clipbox\top,clipbox\right,clipbox\bottom) 
lResult=GetClipRgn_(hdcDest,rectrgn) 
If lResult=-1 Or rectrgn=0 
ProcedureReturn #False 
EndIf 

Triangle2.QUADBLT_TRIANGLE 
Triangle2\v[0]\x=*points\v[3]\x 
Triangle2\v[0]\y=*points\v[3]\y 
Triangle2\v[1]\x=*points\v[2]\x 
Triangle2\v[1]\y=*points\v[2]\y 
Triangle2\v[2]\x=*points\v[1]\x 
Triangle2\v[2]\y=*points\v[1]\y 

rgntriangle1=CreatePolygonRgn_(*points,3,1) 
rgntriangle2=CreatePolygonRgn_(Triangle2,3,1) 

If lResult<>0 
CombineRgn_(rgntriangle1,rgntriangle1,rectrgn,#RGN_AND) 
CombineRgn_(rgntriangle2,rgntriangle2,rectrgn,#RGN_AND) 
EndIf 

lOldStretchBltMode=SetStretchBltMode_(hdcDest,#COLORONCOLOR) 

SelectClipRgn_(hdcDest,rgntriangle1) 
PlgBlt_(hdcDest,*points,hdcSrc,lXSrc,lYSrc,lWidth,lHeight,0,0,0) 

SelectClipRgn_(hdcDest,rgntriangle2) 
PlgBlt_(hdcDest,Triangle2,hdcSrc,lWidth+lXSrc,lHeight+lYSrc,-lWidth,-lHeight,0,0,0) 

SetStretchBltMode_(hdcDest,lOldStretchBltMode) 

If lResult=0 
SelectClipRgn_(hdcDest,0) 
Else 
SelectClipRgn_(hdcDest,rectrgn) 
EndIf 

DeleteObject_(rectrgn) 
DeleteObject_(rgntriangle1) 
DeleteObject_(rgntriangle2) 
EndProcedure 



Dim pt.Point(3) 

OpenWindow(1,0,0,500,400,"TEST") 
LoadImage(1,"C:\bm.bmp") 
MemDC=CreateCompatibleDC_(0) 
SelectObject_(MemDC,ImageID(1)) 


Repeat 
ST=GetTickCount_() 
DC=GetDC_(WindowID(1)) 



pt(0)\x=77 
pt(0)\y=199 

pt(1)\x=400 
pt(1)\y=100 

pt(2)\x=200 
pt(2)\y=280 

pt(3)\x=300 
pt(3)\y=300 

QuadBlt(DC,@pt(),MemDC,0,0,ImageWidth(1),ImageHeight(1)) 
ReleaseDC_(WindowID(1),DC) 

Until WindowEvent()=#PB_Event_CloseWindow 
DeleteDC_(MemDC)
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Hallo Leute,

wie kann ich das Ergebnis aus Stefans Code auf Leinwand bannen, sprich speichern?

Müsste doch eigentlich nur das DC speichern oder so?

Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Antworten