Seite 2 von 3

Re: Bilder drehen

Verfasst: 21.11.2018 23:22
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.
;)

Re: Bilder drehen

Verfasst: 21.11.2018 23:43
von ts-soft
Das ganze noch Crossplattform:
Bild
Jetzt ist aber Schluss mit Offtopi :mrgreen:

Re: Bilder drehen

Verfasst: 21.11.2018 23:50
von #NULL
nehmt doch einfach runde Bilder, dann braucht ihr sie nicht drehen :mrgreen:
Bild

Re: Bilder drehen

Verfasst: 21.11.2018 23:55
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!

Re: Bilder drehen

Verfasst: 22.11.2018 00:16
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.)

Re: Bilder drehen

Verfasst: 22.11.2018 00:28
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.

Re: Bilder drehen

Verfasst: 22.11.2018 00:38
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.

Re: Bilder drehen

Verfasst: 22.11.2018 02:10
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. ;)

Re: Bilder drehen

Verfasst: 23.11.2018 07:51
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ß

Re: Bilder drehen

Verfasst: 23.11.2018 16:51
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ß.