Point() und Plot() gleichzeitg in unterschiedlichen Images?

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Point() und Plot() gleichzeitg in unterschiedlichen Images?

Beitrag von Kurzer »

Hallo,

ich habe eine genrelle Frage.

Die 2D-Zeichenoperationen beziehen sich ja immer auf einen bestimmten Zeichenkanal der mit StartDrawing(OutputID(...)) gesetzt wird.

Wenn ich den Zeichenkanal auf ein Image setze, dann beziehen sich sowohl die schreibenden Zeichenoperationen (Plot), als auch die lesenden Operationen (Point) auf dieses Image.

Meine Frage:
Abgesehen davon, dass es andere Herangehensweisen gibt... ist es möglich ein Image on the fly pixelweise auszulesen und pixelweise in ein anderes Image zu schreiben ohne dabei für jeden Pixelzugriff den Zeichenkanal wechseln zu müssen?

Das switchen mittels StartDrawing() / StopDrawing() von Image1 auf Image2 bei jedem Pixel verbaucht immens Zeit und ist sicherlich auch nicht im Sinne des Erfinders. ;)

Mögliche andere Lösungen, die mir einfallen sind:
- Direkter Zugriff auf den Bidspeicher mit Memorybefehlen (=gar kein point und plot benutzen)
- Image erst in ein Array kopieren, dann den Zeichenkanal auf Image 2 wechseln und das Array in das Zielimage plotten
- Image 1 nach Image 2 kopieren und dort dann die Pixel pointen, ändern und wieder an die selbe Stelle plotten (funktioniert nicht, wenn z.B. Zielimage.xy = Quellimage.xy/2 sein soll, also das Bild halbiert werden soll).

Hintergrund ist, das ich mir einige Bildbearbeitungsprozeduren schreiben möchte und die Routinen in einem Testprogramm entwickle, welches ein Quellimage und ein Zielimage darstellt und die Bearbeitungroutinen quasi gleichzeitigen Zugriff auf beide Images haben sollen (lesen, ändern, schreiben). Das ganze soll zwar Pixelweise ablaufen, aber mit wahlfreiem Zugriff auf die x/y Koordinaten beider Images.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Point() und Plot() gleichzeitg in unterschiedlichen Imag

Beitrag von STARGÅTE »

Nutze den CustomFilterCallback()

Code: Alles auswählen

If StartDrawing(ImageOutput(#Image1))
	CustomFilterCallback(@MyFilter())
	DrawImage(ImageID(#Image2), 0, 0)
	StopDrawing()
EndIf
So bekommst du in deinem Callback:

Code: Alles auswählen

Procedure MyFilter(X, Y, FarbeImage2, FarbeImage1)
EndProcedure
immer sofort die Farbe die gerade das Image1 hat und die Farbe die Image2 hat.
Du selbst kannst dann entscheiden, welche Farbe du dann zum Zeichnen zurück gibst.

Edit: Du könntest sogar mit Point(X2, Y2) innerhalt des Callbacks, die Farbe eines anderen Orts in Image2 auslesen.
X, Y ist ja von Image2
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
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Point() und Plot() gleichzeitg in unterschiedlichen Imag

Beitrag von STARGÅTE »

Hier noch eine weitere möglichkeit:
Da jeder Thread (wenn Thread-Sicher eingeschaltet ist) sein eigenen Start-/Stop-Drawing() Block öffnen kann, kann man auch mit zwei Thread in einem lesen und im anderen Schreiben:
Hier ein Beispiel, wo ich oben lese, und unten das Bild gespiegelt und gedreht schreibe:

Code: Alles auswählen

Global Color.i
Global Lesen = CreateSemaphore()
Global Schreiben = CreateSemaphore(1)

Procedure Lesen(Image)
	If StartDrawing(ImageOutput(Image))
		DrawingMode(#PB_2DDrawing_AllChannels)
		For Y = ImageHeight(Image)-1 To 0 Step -1
			For X = ImageWidth(Image)-1 To 0 Step -1
				WaitSemaphore(Schreiben)
				Color = Point(X, Y)
				SignalSemaphore(Lesen)
			Next
		Next
		StopDrawing()
	EndIf
EndProcedure

Procedure Schreiben(Image)
	If StartDrawing(ImageOutput(Image))
		DrawingMode(#PB_2DDrawing_AllChannels)
		For X = ImageWidth(Image)-1 To 0 Step -1
			For Y = ImageHeight(Image)-1 To 0 Step -1
				WaitSemaphore(Lesen)
				Plot(X, Y, Color)
				SignalSemaphore(Schreiben)
			Next
		Next
		StopDrawing()
	EndIf
EndProcedure


Enumeration
	#Image1
	#Image2
	#Window
EndEnumeration

InitNetwork()
UsePNGImageDecoder()
If FileSize(GetTemporaryDirectory()+"UnionBytesIcon.png") = -1
	ReceiveHTTPFile("http://data.unionbytes.de/UnionBytesIcon.png", GetTemporaryDirectory()+"UnionBytesIcon.png")
EndIf

LoadImage(#Image1, GetTemporaryDirectory()+"UnionBytesIcon.png")
CreateImage(#Image2, ImageHeight(#Image1), ImageWidth(#Image1), 32)

CreateThread(@Lesen(), #Image1)
WaitThread(CreateThread(@Schreiben(), #Image2))

OpenWindow(#Window, 0, 0, ImageWidth(#Image1)+ImageWidth(#Image2), ImageHeight(#Image1), "Point & Plot", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
	ImageGadget(#PB_Any, 0, 0, ImageWidth(#Image1), ImageHeight(#Image1), ImageID(#Image1))
	ImageGadget(#PB_Any, ImageWidth(#Image1), 0, ImageWidth(#Image2), ImageHeight(#Image2), ImageID(#Image2))

Repeat
	
	Select WaitWindowEvent()
			
		Case #PB_Event_CloseWindow
			End
			
		Case #PB_Event_Gadget
			Select EventGadget()
			EndSelect
			
	EndSelect
	
ForEver
Vermutlich wäre aber:
- Image erst in ein Array kopieren, dann den Zeichenkanal auf Image 2 wechseln und das Array in das Zielimage plotten
die einfachste und schnellste Variante.
Zudem kannst du dnan selber noch ein eigenes Format erstellen, um zB die Kanäle in Floats zu speichern um schnellere und genauere Farbe-Operationen anzuwenden.
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
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Point() und Plot() gleichzeitg in unterschiedlichen Imag

Beitrag von Kurzer »

Vielen Dank für Deine Antworten und das Beispiel, Stargate. :allright:

Da ich mich erstmal auf die eigentlichen Bildmaipulationsfunktionen stürzen will, wollte ich das "drumherum" (pixel lesen, bearbeiten, schreiben) so einfach und "unablenkend" wie möglich gestalten. Daher mein pipeline-mäßiger Ansatz in einem einzelnen For x ... For y Schleifenkonstrukt.

Den Callback hatte ich mir vorher auch angesehen, aber erstmal verworfen, weil man dabei doch nicht so ganz linear denken kann, wie beim FIFO-Pixelschieben in einer Schleife.

Ich denke zum testen und entwickeln nutze ich erstmal das Array (hab da ja dann auch wahlfreien Zugriff auf alle Pixel) und denke später noch einmal über den Callback nach.

Ich wollte mich halt nur vergewissern, dass Pixel on the fly kopieren wirklich nicht geht ohne den Zeichenkanal zu wechseln.

Also, besten Dank. Frage beantwortet. :allright:
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Re: Point() und Plot() gleichzeitg in unterschiedlichen Imag

Beitrag von Thorium »

Kurzer hat geschrieben: Ich denke zum testen und entwickeln nutze ich erstmal das Array (hab da ja dann auch wahlfreien Zugriff auf alle Pixel) und denke später noch einmal über den Callback nach.
Ein Image ist im Grunde ein Pixelarray. Brauchst es nicht kopieren. Kannst einfach mit Pointern draufzugreifen.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Point() und Plot() gleichzeitg in unterschiedlichen Imag

Beitrag von STARGÅTE »

@Thorium
Naja aber auch nur wenn es ein 32Bit-Image ist, sonst ist ein Bildpunkt immer 3 Byte und jede Zeile hat noch ein Offset.
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
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Point() und Plot() gleichzeitg in unterschiedlichen Imag

Beitrag von Kurzer »

Jupp, Direktzugriff auf den Pixelmemory ist mir aus anderen Projekten geläufig.
Aber Du musst dann auch echt manuell alle Sonderfälle behandeln. Alle Auflösungen, alle RGB/BGR Reihenfolgen und den Modus mit der gespiegelten Y-Achse.

Ich mach erstmal mit Plot und Point. Wenn die Prozeduren stehen tausche ich die dann gegen ein macro aus, dass den Direktzugriff auf den Pixelmemory übernimmt.
Natürlich nur, wenn sich das Geschwindigkeitsmäßig rechnet... ich finde Point und Plot momentan gar nicht mal sooo langsam. :)
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Antworten