Helligkeit und Kontrast ändern

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Plenz
Beiträge: 38
Registriert: 05.05.2021 01:19

Helligkeit und Kontrast ändern

Beitrag von Plenz »

Wie kann ich Helligkeit und Kontrast von Bildern ändern?

In VisualBasic kann ich das über Farbmatritzen machen. In PureBasic finde ich nichts dergleichen. Ich könnte zwar "convert" aufrufen (das soll unter Linix laufen), aber das finde ich umständlich, zumal es Zwischenspeichern bedeutet.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Helligkeit und Kontrast ändern

Beitrag von STARGÅTE »

Öhm, in welchem Anwendungsgebiet denn?
- Anwendung mit Window und ImageGadget?
- Anwendung mit CanvasGadget und DrawImage?
- OpenGLGadget()?
- VectorDrawing?
- Spiele mit Sprites?
- Spiele mit Engine3D?

So gäbe es ja verschiedene Ansätze wie den CustomFilterCallback() bei Drawing2D oder die Nutzung von Shadern bei Engine3D
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
Plenz
Beiträge: 38
Registriert: 05.05.2021 01:19

Re: Helligkeit und Kontrast ändern

Beitrag von Plenz »

Vielen Dank, der Hinweis auf CustomFilterCallback() scheint genau das richtige zu sein, denn es geht um ein einfaches Image.
Aus dem Beispielprogramm in der Hilfe werde ich allerdings nicht schlau. Der Kommentar "Nehme nur die Rot-Komponente aus der Quelle, ändere nicht die anderen" weist darauf hin, dass die folgende Zeile bestimmt, welche Farbe woher kommt, aber ich vermisse eine Angabe darüber, was mit dieser Farbe gemacht werden soll wie z.B. den Kontrast erhöhen. Oder was mich auch interessieren würde: wie man ein Bild unscharf macht.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Helligkeit und Kontrast ändern

Beitrag von STARGÅTE »

Also für beides gibt es in PureBasic keine eingebaute Funktion.
Zur Änderung der Helligkeit würde ich z.B. auf die drei Farbkanäle einfach einen Wert drauf addieren, dann noch den Überlauf (255) abfangen und die neue Farbe zurück geben.
Hier mal ein Beispiel Code dazu. Bitte nicht wundern, dass es im Debugger-Modus ziemlich Ruckelt. Ohne Debugger ist es "recht flink".
Mit dem Schieberegler kannst du die Helligkeit ändern.

Code: Alles auswählen

Enumeration
	#Window
	#CanvasGadget
	#TrackBarGadget
	#Image
EndEnumeration

InitNetwork()
UseJPEGImageDecoder()


; Beispiel Bild
Define *Memory = ReceiveHTTPMemory("http://data.unionbytes.de/convergence_by_rahll.jpg")
If *Memory
	If CatchImage(#Image, *Memory) = #False
		MessageRequester("Failed", "Konnte Bild nicht laden!")
	EndIf
Else
	MessageRequester("Failed", "Konnte Bild nicht laden!")
EndIf


Global Brightness.i ; Slider-Wert

; Limit-Funktion für Überlaufverhinderung
Procedure.i Limit(Value.i, Min.i, Max.i)
	If Value < Min     : ProcedureReturn Min
	ElseIf Value > Max : ProcedureReturn Max
	Else               : ProcedureReturn Value
	EndIf
EndProcedure

; Filter der Helligkeit
Procedure.l FilterCallback(X.i, Y.i, FrontColor.i, BackColor.i)
	Protected R.i = Limit(Red(FrontColor) + Brightness, 0, 255)
	Protected G.i = Limit(Green(FrontColor) + Brightness, 0, 255)
	Protected B.i = Limit(Blue(FrontColor) + Brightness, 0, 255)
	ProcedureReturn RGB(R, G, B)
EndProcedure

; Aktualisierung des Gadgets
Procedure UpdateGadget(Gadget.i)
	
	If StartDrawing(CanvasOutput(Gadget))
		DrawingMode(#PB_2DDrawing_CustomFilter)
		CustomFilterCallback(@FilterCallback())
		DrawImage(ImageID(#Image), 0, 0)
		StopDrawing()
	EndIf
	
EndProcedure




OpenWindow(#Window, 0, 0, ImageWidth(#Image), 20+ImageHeight(#Image), "Vector Canvas Gadget", #PB_Window_MaximizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#CanvasGadget, 0, 20, WindowWidth(#Window), WindowHeight(#Window), #PB_Canvas_Keyboard)
UpdateGadget(#CanvasGadget)
TrackBarGadget(#TrackBarGadget, 0, 0, WindowWidth(#Window), 20, 0, 510)
SetGadgetState(#TrackBarGadget, 255)

Repeat
	
	Select WaitWindowEvent()
		Case #PB_Event_CloseWindow
			Break
		Case #PB_Event_Gadget
			Select EventGadget()
				Case #TrackBarGadget
					Brightness = GetGadgetState(#TrackBarGadget) - 255
					UpdateGadget(#CanvasGadget)
			EndSelect
	EndSelect
	
ForEver

End
Das Unscharf machen eines Bilds ist nicht so einfach über CustomFilterCallback() zu lösen, da ja auch auf die Nachbarpixel zugegriffen werden muss. Da müsste man das Bild z.B. in einem Array Zwischenspeichern. Auch hier mal ein Beispiel mit ganz einfacher linearer Unschärfe in X-Richtung:

Code: Alles auswählen

Enumeration
	#Window
	#CanvasGadget
	#TrackBarGadget
	#Image
EndEnumeration

InitNetwork()
UseJPEGImageDecoder()


; Beispiel Bild
Define *Memory = ReceiveHTTPMemory("http://data.unionbytes.de/convergence_by_rahll.jpg")
If *Memory
	If CatchImage(#Image, *Memory) = #False
		MessageRequester("Failed", "Konnte Bild nicht laden!")
	EndIf
Else
	MessageRequester("Failed", "Konnte Bild nicht laden!")
EndIf


Global Blur.i ; Slider-Wert
Global Dim Pixel.i(ImageWidth(#Image)-1, ImageHeight(#Image)-1)
Global Width.i = ImageWidth(#Image)
Global Height.i = ImageHeight(#Image)

; Limit-Funktion für Überlaufverhinderung
Procedure.i Limit(Value.i, Min.i, Max.i)
	If Value < Min     : ProcedureReturn Min
	ElseIf Value > Max : ProcedureReturn Max
	Else               : ProcedureReturn Value
	EndIf
EndProcedure

; Bild zu Array
Procedure.l Callback_ImageToArray(X.i, Y.i, FrontColor.i, BackColor.i)
	Pixel(X, Y) = FrontColor
EndProcedure

; Bild in X-Unschärfen
Procedure.l Callback_BlurX(X.i, Y.i, FrontColor.i, BackColor.i)
	Protected R.i, G.i, B.i
	Protected X0.i = Limit(X-Blur, 0, Width-1)
	Protected X1.i = Limit(X+Blur, 0, Width-1)
	Protected I.i
	For I = X0 To X1
		R + Red(Pixel(I, Y)) : G + Green(Pixel(I, Y)) : B + Blue(Pixel(I, Y))
	Next
	ProcedureReturn RGB(R/(1+X1-X0), G/(1+X1-X0), B/(1+X1-X0))
EndProcedure


; Aktualisierung des Gadgets
Procedure UpdateGadget(Gadget.i)
	
	If StartDrawing(CanvasOutput(Gadget))
		DrawingMode(#PB_2DDrawing_CustomFilter)
		; Bild ins Array
		CustomFilterCallback(@Callback_ImageToArray())
		DrawImage(ImageID(#Image), 0, 0)
		; Unschärfe
		CustomFilterCallback(@Callback_BlurX())
		DrawImage(ImageID(#Image), 0, 0)
		StopDrawing()
	EndIf
	
EndProcedure




OpenWindow(#Window, 0, 0, ImageWidth(#Image), 20+ImageHeight(#Image), "Vector Canvas Gadget", #PB_Window_MaximizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#CanvasGadget, 0, 20, WindowWidth(#Window), WindowHeight(#Window), #PB_Canvas_Keyboard)
UpdateGadget(#CanvasGadget)
TrackBarGadget(#TrackBarGadget, 0, 0, WindowWidth(#Window), 20, 0, 20)
SetGadgetState(#TrackBarGadget, 0)

Repeat
	
	Select WaitWindowEvent()
		Case #PB_Event_CloseWindow
			Break
		Case #PB_Event_Gadget
			Select EventGadget()
				Case #TrackBarGadget
					Blur = GetGadgetState(#TrackBarGadget)
					UpdateGadget(#CanvasGadget)
			EndSelect
	EndSelect
	
ForEver

End
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
Plenz
Beiträge: 38
Registriert: 05.05.2021 01:19

Re: Helligkeit und Kontrast ändern

Beitrag von Plenz »

Das sieht ja hochinteressant aus, besten Dank dafür!
Ich denke, auf diesem Beispiel kann ich aufbauen. Vermutlich kann ich den Kontrast ändern, wenn ich einen Wert multipliziere. Ich werde das einfach mal ausprobieren.
Plenz
Beiträge: 38
Registriert: 05.05.2021 01:19

Re: Helligkeit und Kontrast ändern

Beitrag von Plenz »

Vielen Dank nochmal, das mit der Helligkeit klappt prima.
Für Kontrast plus Helligkeit habe ich die Formel Red(FrontColor) * (1.0 + Brightness / 255) benutzt, klappt auch prima.

Das mit der Unschärfe war zweitrangig, und weil mein Programm jetzt schon so nahe am 800-Zeilen-Limit ist, dass ich schon Leerzeilen löschen musste, lasse ich das Thema beiseite. Trotzdem danke für deine Mühe!
Antworten