Bilder drehen

Für allgemeine Fragen zur Programmierung mit PureBasic.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Bilder drehen

Beitrag von ccode_new »

@ts-soft!

:mrgreen:

Unter Linux z.B. so:

# Bild nach links drehen:
xrandr -o left

# Bild normal ausrichten:
xrandr -o normal

# Bild nach rechts drehen:
xrandr -o right

# Bild auf den Kopf drehen:
xrandr -o inverted

Aber das geht am Thema (etwas) vorbei.
;)
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Bilder drehen

Beitrag von ts-soft »

Das ganze noch Crossplattform:
Bild
Jetzt ist aber Schluss mit Offtopi :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
#NULL
Beiträge: 2239
Registriert: 20.04.2006 09:50

Re: Bilder drehen

Beitrag von #NULL »

nehmt doch einfach runde Bilder, dann braucht ihr sie nicht drehen :mrgreen:
Bild
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
HeX0R
Beiträge: 3056
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Bilder drehen

Beitrag von HeX0R »

ccode_new hat geschrieben:Hallo HeXOR!
[...]Du bist am Zug mir eine schnellere Procedure zu liefern. ;)
Pfff... ich muss gar nix machen, ausser die beiden Prozeduren in eine nutzbare Testumgebung zu pappen.

Code: Alles auswählen

DisableDebugger
#USE_PLOT_AND_POINT = 0 ;<- change



InitNetwork()
UseJPEGImageDecoder()

Procedure RotiereEinBild(bild, richtung)  ;<-- https://www.purebasic.fr/german/viewtopic.php?p=349925#p349925
 Protected i.i, k.i
 Protected rbild.i
 Protected w.i = ImageWidth(bild)
 Protected h.i = ImageHeight(bild)
 Protected Dim p(w,h)
 
  If IsImage(bild)
   
    ;Lese die Pixel
    StartDrawing( ImageOutput(bild) )
      For k=0 To h-1
        For i=0 To w-1
          p(i,k)=Point(i,k)
        Next
      Next
    StopDrawing()
   
    ;Drehrichtung
    If richtung = 0 ;"90° oder Pi/2"
      If w<>h
        Swap w,h
        rbild = CreateImage(#PB_Any,w+1,h+1)
        If IsImage(rbild)
          FreeImage(bild)
        EndIf
      EndIf
     
      StartDrawing( ImageOutput(rbild) )
      For k=0 To h
        For i=0 To w
          Plot(i,k, p(k,w-i))
        Next
      Next
      StopDrawing()
    ElseIf richtung = 1 ;"180° oder Pi"
      rbild = CreateImage(#PB_Any,w+1,h+1)
      If IsImage(rbild)
        FreeImage(bild)
      EndIf
     
      StartDrawing( ImageOutput(rbild) )
      For k=0 To h-1
        For i=0 To w-1
          kk = (h-1)-k
          ii = (w-1)-i
          Plot(i,k, p(ii,kk))
        Next
      Next
      StopDrawing()
    ElseIf richtung = 2 ;"270° oder 3/2 * Pi"
      If w<>h
        Swap w,h
        rbild = CreateImage(#PB_Any,w+1,h+1)
        If IsImage(rbild)
          FreeImage(bild)
        EndIf
      EndIf
     
      StartDrawing( ImageOutput(rbild) )
      For k=0 To h
        For i=0 To w
          kk = (h)-k
          ii = (w)-i
          Plot(i,k, p(kk,ii))
        Next
      Next
      StopDrawing()
    EndIf
 
    ProcedureReturn rbild
  EndIf
EndProcedure

Structure _SWAP_
	StructureUnion
		l.l[0]
		b.b[0]
		w.w[0]
	EndStructureUnion
EndStructure

Procedure ROTATE(image, flag) ;<-- https://www.purebasic.fr/english/viewtopic.php?p=438200#p438200
															;if flag <> 0 image rotates left else image rotates right
	
	Protected A, B, result, padding, imgTemp, format
	Protected *SBuf  ; pointer to first memory byte of source buffer
	Protected *DBuf	 ; pointer to first memory byte of destination buffer
	Protected *FPix	 ; points to where first pixel is peeked in source buffer
	Protected *S._SWAP_,*D._SWAP_  ; source and destination pointers
	Protected Iw									 ; image width
	Protected Ih									 ; image height
	Protected Depth								 ; image color depth, 24 or 32
	Protected SBpp								 ; SourceBytesPerPixel
	Protected DBpp								 ; DestinationBytesPerPixel
	Protected SPitch							 ; source image number of bytes per row (x)
	Protected DPitch							 ; destination image number of bytes per row (x)
	
	;    Macro Copy3Bytes(Source, Destination)
	;       PokeA(Destination, PeekA(Source))
	;       PokeW(Destination+1, PeekW(Source+1))
	;    EndMacro
	;    
	;    Macro Copy4Bytes(Source, Destination)
	;       PokeL(Destination, PeekL(Source))
	;    EndMacro
	Macro Copy3Bytes(Source, Destination)
		Destination\w[0] = Source\w[0]
		Destination\b[2] = Source\b[2]
	EndMacro
	
	Macro Copy4Bytes(Source, Destination)
		Destination\l[0] = Source\l[0]
	EndMacro
	
	If IsImage(image) = 0 : ProcedureReturn result : EndIf
	
	StartDrawing(ImageOutput(image))
	; Get information for source image
	Iw = OutputWidth() : Ih = OutputHeight() ; Get image size
	*SBuf  = DrawingBuffer()
	SPitch = DrawingBufferPitch()
	format = DrawingBufferPixelFormat()
	
	Select  format & $7FFF
		Case #PB_PixelFormat_24Bits_RGB : SBpp = 3 : Depth = 24 ; 3 Bytes per pixel (RRGGBB)
		Case #PB_PixelFormat_24Bits_BGR : SBpp = 3 : Depth = 24	; 3 Bytes per pixel (BBGGRR)
		Case #PB_PixelFormat_32Bits_RGB : SBpp = 4 : Depth = 32	; 4 Bytes per pixel (RRGGBB)
		Case #PB_PixelFormat_32Bits_BGR : SBpp = 4 : Depth = 32	; 4 Bytes per pixel (BBGGRR)
		Default
			MessageRequester("Sorry...","24 and 32 bit depths only")
			StopDrawing()
			ProcedureReturn result
	EndSelect
	
	If format & #PB_PixelFormat_ReversedY = 0 ; this is for Linux
		flag = flag ! 1 & 1
	EndIf
	StopDrawing()
	
	; Create temporary image with axis swapped
	Swap Ih,Iw
	imgTemp = CreateImage(#PB_Any, Iw, Ih, 8*SBpp)
	
	; perform the rotation
	If imgTemp
		StartDrawing(ImageOutput(imgTemp))
		*DBuf = DrawingBuffer()
		DPitch = DrawingBufferPitch()
		DBpp = SBpp
		
		If flag = 0 ; configure to rotate right
			*FPix = *SBuf + (Ih-1) * SBpp ; point to last pixel in first row
			SBpp = -SBpp									; reverse X iteration direction
		Else														; configure to rotate left
			*FPix = *SBuf + (Iw-1) * SPitch ; point to first pixel in last row
			SPitch = -SPitch								; reverse Y iteration direction
		EndIf
		
		; time to fly
		If Depth = 24
			A = 0 : While A < Ih
				*S = *FPix + (A * SBpp)   ; set source pointer X position
				*D = *DBuf + (A * DPitch)	; set destination pointer Y position
				B = 0 : While B < Iw
					Copy3Bytes(*S, *D)
					*S + SPitch ; increment source pointer Y position
					*D + DBpp		; increment destination pointer X position
				B + 1 : Wend
			A + 1 : Wend
		ElseIf Depth = 32
			A = 0 : While A < Ih
				*S = *FPix + (A * SBpp)   ; set source pointer X position
				*D = *DBuf + (A * DPitch)	; set destination pointer Y position
				B = 0 : While B < Iw
					Copy4Bytes(*S, *D)
					*S + SPitch ; increment source pointer Y position
					*D + DBpp		; increment destination pointer X position
				B + 1 : Wend
			A + 1 : Wend
		EndIf
		
		StopDrawing()
		
		FreeImage(image)
		result = imgTemp
	EndIf
	
	ProcedureReturn result
EndProcedure



Procedure main()
	Protected Image, ms
	
	If ReceiveHTTPFile("https://images.pexels.com/photos/753626/pexels-photo-753626.jpeg?cs=srgb&dl=badeort-berg-bora-bora-753626.jpg&fm=jpg", GetTemporaryDirectory() + "pic.jpg")
		Image = LoadImage(#PB_Any, GetTemporaryDirectory() + "pic.jpg")
		If Image
			ms = ElapsedMilliseconds()
			CompilerIf #USE_PLOT_AND_POINT
				Image = RotiereEinBild(Image, 0)
			CompilerElse
				Image = ROTATE(Image, 0)
			CompilerEndIf
			ms = ElapsedMilliseconds() - ms
			If Image
				OpenWindow(0, 0, 0, ImageWidth(Image), ImageHeight(Image), "")
				ImageGadget(0, 0, 0, ImageWidth(Image), ImageHeight(Image), ImageID(Image))
				
				While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
				CloseWindow(0)
				MessageRequester("Needed time", Str(ms) + "ms")
			EndIf
		EndIf
	EndIf
	
EndProcedure

main()
Plot und co: ~100ms
Buffer: 45ms!
Zuletzt geändert von HeX0R am 22.11.2018 00:26, insgesamt 1-mal geändert.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Bilder drehen

Beitrag von ccode_new »

@HeX0R

Ah!

Bei mir sieht es (ohne Debugger) so aus:

102 ms bei: ;Image = RotiereEinBild(Image, 0)

und:

218 ms bei: ;ROTATE(Image, 0)

Also genau umgekehrt.

Bei mir ist meine gepostete Procedure leider viel schneller!

Ich würde mich freuen, wenn mein Resultat von Anderen bestätigt werden könnte.

Mit Video-Ram / Shader ist aber noch viel schneller. (Dafür muss man aber Resize-Bilder als Sprites übergeben.)
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
HeX0R
Beiträge: 3056
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Bilder drehen

Beitrag von HeX0R »

Ich habe das nochmal geringfügig verfeinert, nun habe ich sogar 45ms bei DrawBuffer, ausserdem war die CopyImage() Funktion mit einem #PB_Any Handle sehr ungünstig gelöst und hat meinen Rechner hier ziemlich ins schwitzen gebracht.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Bilder drehen

Beitrag von ccode_new »

@HeX0R

Ich habe mal mehrere Durchläufe getestet.

Mit DrawingBuffer ist es jetzt im Durchschnitt doch etwas schneller.

Manchmal liegen da 30 bis 300 ms Unterschied dazwischen.
Ich hatte aber auch einen Ausreißer, da war es mit DrawingBuffer langsamer.

Aber Shader schaffen es in unter 3 ms.

Also es wäre mir mit GPU-Unterstützung dann doch noch lieber.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Bilder drehen

Beitrag von ccode_new »

#NULL hat geschrieben:nehmt doch einfach runde Bilder, dann braucht ihr sie nicht drehen :mrgreen:
Das trifft leider auch nur auf dein Beispiel zu.

Die meisten runden Bilder dürften gedreht anders aussehen. ;)
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
juergenkulow
Beiträge: 190
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Bilder drehen

Beitrag von juergenkulow »

Hallo ccode_new,

wenn ich Dich richtig verstanden habe willst Du ein 8k Bild in 3 ms per PB inline-ASM drehen, möglichst bei jedem Winkel.
Wie viel Zeit in Manntagen möchtest Du dafür investieren? Welche praktische Anwendung hat das?
Sollten neben dem 24, 32 bit-Format nicht auch High Dynamic Range(HDR)Formate unterstützt werden?

Gruß
Bitte stelle Deine Fragen, denn den Erkenntnisapparat einschalten entscheidet über das einzig bekannte Leben im Universum.

Jürgen Kulow Wersten :D_üsseldorf NRW D Europa Erde Sonnensystem Lokale_Flocke Lokale_Blase Orion-Arm
Milchstraße Lokale_Gruppe Virgo-Superhaufen Laniakea Sichtbares_Universum
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Bilder drehen

Beitrag von ccode_new »

juergenkulow hat geschrieben:wenn ich Dich richtig verstanden habe willst Du ein 8k Bild in 3 ms per PB inline-ASM drehen, möglichst bei jedem Winkel.
Das wäre wirklich toll!

Aber ich halte es für realitätsfern.

Von jeden Winkel habe ich nichts gesagt. (Das wäre aber auch toll.)

Wenn du eine schnelle Inline-Asm-Procedure zum Bilder drehen hast. (Es reicht 90, 180, 270 °) dann darfst du sie hier gerne posten.

Ich verbleibe mit freundlichem Gruß.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Antworten