Ringe aus Grafik ausschneiden
Ringe aus Grafik ausschneiden
Hallo,
(sorry wg. des umständlichen Betreffs, aber mir fiel nichts sinnvolleres ein.)
Ich bin in Sachen Grafikprogrammierung recht unbeholfen. Deshalb
habe ich bei folgender Aufgabenstellung so meine Probleme.
Gegeben ist ein Bild. Aus diesem sollen nun (ausgehen vom Zentrum)
immer grösser werdende Ringe ausgeschnitten werden.
Im Prinzip also wie die Ringe bei einer Dartscheibe.
Die Ringe sollen dann als separate Dateien abgespeichert werden, so dass
man hinterher das Ausgangsbild und die Ringe wie Ebenen übereinander
legen kann.
Rechteckige Ausschnitte würde ich mir ja noch zutrauen; aber runde?
Danke im voraus & Grüße ... Kiffi
(sorry wg. des umständlichen Betreffs, aber mir fiel nichts sinnvolleres ein.)
Ich bin in Sachen Grafikprogrammierung recht unbeholfen. Deshalb
habe ich bei folgender Aufgabenstellung so meine Probleme.
Gegeben ist ein Bild. Aus diesem sollen nun (ausgehen vom Zentrum)
immer grösser werdende Ringe ausgeschnitten werden.
Im Prinzip also wie die Ringe bei einer Dartscheibe.
Die Ringe sollen dann als separate Dateien abgespeichert werden, so dass
man hinterher das Ausgangsbild und die Ringe wie Ebenen übereinander
legen kann.
Rechteckige Ausschnitte würde ich mir ja noch zutrauen; aber runde?
Danke im voraus & Grüße ... Kiffi
Hygge
-
- Beiträge: 6267
- Registriert: 29.08.2004 08:37
- Computerausstattung: Hoffentlich bald keine mehr
- Kontaktdaten:
Re: Ringe aus Grafik ausschneiden
Da gehst du einfach jedes Pixel durch, nimmst die Entfernung zu deinem Zentrum und gibst diese in eine Funktion ein (z.B. y = Round(Cos(Pow(Abs(Dist), 0.25) * #RING_FACTOR + #PI) * 0.5 + 0.5, #PB_Round_Nearest)), also so:
[EDIT]
Ups, hab übersehen, dass die in einzelne Bilder sollen. Sollen sich die Ringe dann auch berühren?
[EDIT]
Hier mit gleich breiten Ringen:
Und hier mit immer breiter werdenden Ringen:
Code: Alles auswählen
Global OriginX.i, OriginY.i
Procedure.d Distance(X1.d, Y1.d, X2.d, Y2.d)
Protected XDiff.d = X2 - X1
Protected YDiff.d = Y2 - Y1
ProcedureReturn Sqr(XDiff * XDiff + YDiff * YDiff)
EndProcedure
#RING_FACTOR = 30.0
Procedure.i CircleFunc(Dist.d)
ProcedureReturn Round(Cos(Pow(Abs(Dist), 0.25) * #RING_FACTOR + #PI) * 0.5 + 0.5, #PB_Round_Nearest)
EndProcedure
Procedure FilterCallback(X, Y, QuellFarbe, ZielFarbe)
If CircleFunc(Distance(X, Y, OriginX, OriginY))
ProcedureReturn ZielFarbe
Else
ProcedureReturn QuellFarbe
EndIf
EndProcedure
LoadImage(1, #PB_Compiler_Home + "examples/sources/data/geebee2.bmp")
If OpenWindow(0, 0, 0, ImageWidth(1), ImageHeight(1), "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateImage(0, ImageWidth(1), ImageHeight(1))
OriginX = ImageWidth(1) / 2
OriginY = ImageHeight(1) / 2
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_CustomFilter)
CustomFilterCallback(@FilterCallback())
DrawImage(ImageID(1), 0, 0)
StopDrawing()
ImageGadget(0, 0, 0, 400, 200, ImageID(0))
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
Ups, hab übersehen, dass die in einzelne Bilder sollen. Sollen sich die Ringe dann auch berühren?
[EDIT]
Hier mit gleich breiten Ringen:
Code: Alles auswählen
Global OriginX.i, OriginY.i
Global MinDist.d, MaxDist.d
Procedure.d Distance(X1.d, Y1.d, X2.d, Y2.d)
Protected XDiff.d = X2 - X1
Protected YDiff.d = Y2 - Y1
ProcedureReturn Sqr(XDiff * XDiff + YDiff * YDiff)
EndProcedure
Procedure FilterCallback(X, Y, QuellFarbe, ZielFarbe)
Protected Distance.d = Distance(X, Y, OriginX, OriginY)
If Distance >= MinDist And Distance < MaxDist
ProcedureReturn QuellFarbe
Else
ProcedureReturn ZielFarbe
EndIf
EndProcedure
#RING_COUNT = 5
LoadImage(1, #PB_Compiler_Home + "examples/sources/data/geebee2.bmp")
If OpenWindow(0, 0, 0, ImageWidth(1), ImageHeight(1), "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateImage(0, ImageWidth(1), ImageHeight(1))
OriginX = ImageWidth(1) / 2
OriginY = ImageHeight(1) / 2
EndIf
ImageGadget(0, 0, 0, ImageWidth(0), ImageHeight(0), ImageID(0))
Define k.i = 0
Define RingStep.i = ImageWidth(0) / #RING_COUNT
Define Time.i = ElapsedMilliseconds()
Repeat
If ElapsedMilliseconds() - Time > 1000
MinDist = MaxDist
MaxDist + RingStep
StartDrawing(ImageOutput(0))
Box(0, 0, OutputWidth(), OutputHeight(), RGB(0, 0, 0))
DrawingMode(#PB_2DDrawing_CustomFilter)
CustomFilterCallback(@FilterCallback())
DrawImage(ImageID(1), 0, 0)
StopDrawing()
SetGadgetState(0, ImageID(0))
k + 1
If k >= #RING_COUNT
k = 0
EndIf
Time = ElapsedMilliseconds()
EndIf
Event = WaitWindowEvent(5)
Until Event = #PB_Event_CloseWindow
EndIf
Code: Alles auswählen
Global OriginX.i, OriginY.i
Global MinDist.d, MaxDist.d
Procedure.d Distance(X1.d, Y1.d, X2.d, Y2.d)
Protected XDiff.d = X2 - X1
Protected YDiff.d = Y2 - Y1
ProcedureReturn Sqr(XDiff * XDiff + YDiff * YDiff)
EndProcedure
Procedure FilterCallback(X, Y, QuellFarbe, ZielFarbe)
Protected Distance.d = Distance(X, Y, OriginX, OriginY)
If Distance >= MinDist And Distance < MaxDist
ProcedureReturn QuellFarbe
Else
ProcedureReturn ZielFarbe
EndIf
EndProcedure
#RING_COUNT = 5
LoadImage(1, #PB_Compiler_Home + "examples/sources/data/geebee2.bmp")
If OpenWindow(0, 0, 0, ImageWidth(1), ImageHeight(1), "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateImage(0, ImageWidth(1), ImageHeight(1))
OriginX = ImageWidth(1) / 2
OriginY = ImageHeight(1) / 2
EndIf
ImageGadget(0, 0, 0, ImageWidth(0), ImageHeight(0), ImageID(0))
Define k.i = 0
Define RingStep.i = ImageWidth(0) / #RING_COUNT
Define Time.i = ElapsedMilliseconds()
Repeat
If ElapsedMilliseconds() - Time > 1000
MinDist = MaxDist
MaxDist + RingStep / (#RING_COUNT - k)
StartDrawing(ImageOutput(0))
Box(0, 0, OutputWidth(), OutputHeight(), RGB(0, 0, 0))
DrawingMode(#PB_2DDrawing_CustomFilter)
CustomFilterCallback(@FilterCallback())
DrawImage(ImageID(1), 0, 0)
StopDrawing()
SetGadgetState(0, ImageID(0))
k + 1
If k >= #RING_COUNT
k = 0
MaxDist = 1
EndIf
Time = ElapsedMilliseconds()
EndIf
Event = WaitWindowEvent(5)
Until Event = #PB_Event_CloseWindow
EndIf
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Re: Ringe aus Grafik ausschneiden
Habe mal meinen Bresenham Circle von HIER genommen und
so modifiziert, dass es nicht den Kreis innen sondern außen zeichnet.
Dabei setzt das den AlphaChannel auf 0, löscht es also. Übrig bleibt das
richtige Bild innen.
neuesBild = CircleCut(originalBild, x, y, radius)
Ist schön flexibel, da man an jeder Stelle einen Kreis ausschneiden kann.
so modifiziert, dass es nicht den Kreis innen sondern außen zeichnet.
Dabei setzt das den AlphaChannel auf 0, löscht es also. Übrig bleibt das
richtige Bild innen.
neuesBild = CircleCut(originalBild, x, y, radius)
Code: Alles auswählen
UsePNGImageDecoder()
Procedure CircleCut(img,x,y,radius)
; Bresenham circle algorithm
original = GrabImage(img,#PB_Any,x-radius,y-radius,radius*2,radius*2)
result = CreateImage(#PB_Any,radius*2,radius*2,32)
If StartDrawing(ImageOutput(result))
DrawImage(ImageID(original),0,0)
;DrawingMode(#PB_2DDrawing_AlphaChannel)
DrawingMode(#PB_2DDrawing_AllChannels)
temp_x = 0
d = 3 - 2 * radius
w=ImageWidth(result)
h=ImageHeight(result)
x=w*0.5
y=h*0.5
color=0;$FFFFFFFF
While temp_x <= radius
LineXY(0,y+radius,x-temp_x,y+radius,color)
LineXY(x+temp_x,y+radius,w,y+radius,color)
LineXY(0,y+temp_x,x-radius,y+temp_x,color)
LineXY(x+radius,y+temp_x,w,y+temp_x,color)
LineXY(0,y-temp_x,x-radius,y-temp_x,color)
LineXY(x+radius,y-temp_x,w,y-temp_x,color)
LineXY(0,y-radius,x-temp_x,y-radius,color)
LineXY(x+temp_x,y-radius,w,y-radius,color)
If d < 0
d + 4*temp_x + 6
Else
d + 4*(temp_x - radius) + 10
radius - 1
EndIf
temp_x + 1
Wend
StopDrawing()
EndIf
FreeImage(original)
ProcedureReturn result
EndProcedure
original = LoadImage(#PB_Any,"02.png")
If original
cut = CircleCut(original,100,100,80)
If OpenWindow(0, 0, 0, 800, 600, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 800, 600)
StartDrawing(CanvasOutput(0))
Box(0,0,800,800,$FFFF)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(cut),10,10)
StopDrawing()
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
EndIf
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Re: Ringe aus Grafik ausschneiden
Wenns zu kompliziert ist, hier Danilos mit dem Circle-Befehl.
Hier wird auch tatsächlich ein Ring ausgeschnitten.
MFG PMV
Hier wird auch tatsächlich ein Ring ausgeschnitten.
Code: Alles auswählen
UsePNGImageDecoder()
Procedure CircleCut(img,x,y,radius1, radius2)
If radius1 < radius2
Swap radius1, radius2
EndIf
durchmesser = radius1 * 2
result = CreateImage(#PB_Any,durchmesser, durchmesser,32)
If StartDrawing(ImageOutput(result))
DrawImage(ImageID(img),-x+radius1,-y+radius1, durchmesser, durchmesser)
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0, 0, durchmesser, durchmesser, $00FFFFFF)
Circle(radius1, radius1, radius1, $FFFFFFFF)
Circle(radius1, radius1, radius2, $00FFFFFF)
StopDrawing()
EndIf
ProcedureReturn result
EndProcedure
original = LoadImage(#PB_Any,OpenFileRequester("", "", "*.png", 0))
If original
cut = CircleCut(original,100,100,80, 40)
If OpenWindow(0, 0, 0, 800, 600, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 800, 600)
StartDrawing(CanvasOutput(0))
Box(0,0,800,800,$FFFF)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(cut),10,10)
StopDrawing()
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
EndIf
- Falko
- Admin
- Beiträge: 3531
- Registriert: 29.08.2004 11:27
- Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.0 - Kontaktdaten:
Re: Ringe aus Grafik ausschneiden
sollte das nicht so sein und davon mehrere Ringe wie eine Dartscheibe, sodass man diese
Ringe übereinander legen kann, damit ein vollständiges Bild zu sehen ist, aber jeder dieser Ringe in eine eigene Datei gespeichert werden sollte?
Beispiel nur ein Ring mit den obigen Sourcen
Gruß,
Falko
Ringe übereinander legen kann, damit ein vollständiges Bild zu sehen ist, aber jeder dieser Ringe in eine eigene Datei gespeichert werden sollte?
Beispiel nur ein Ring mit den obigen Sourcen
Code: Alles auswählen
UsePNGImageDecoder()
Procedure CircleCut(img,x,y,radius)
durchmesser = radius * 2
result = CreateImage(#PB_Any,durchmesser, durchmesser,32)
If StartDrawing(ImageOutput(result))
DrawImage(ImageID(img),-x+radius,-y+radius, durchmesser, durchmesser)
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0, 0, durchmesser, durchmesser, $00FFFFFF)
Circle(radius, radius, radius, $FFFFFFFF)
StopDrawing()
EndIf
ProcedureReturn result
EndProcedure
original = LoadImage(#PB_Any,OpenFileRequester("", "", "*.png", 0))
If original
cut = CircleCut(original,100,100,80)
If OpenWindow(0, 0, 0, 800, 600, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 800, 600)
StartDrawing(CanvasOutput(0))
Box(0,0,800,800,$FFFF)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(cut),10,10)
Circle(90,90,50,$FF00FFFF)
StopDrawing()
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
EndIf
Falko
Re: Ringe aus Grafik ausschneiden
Jungs, Ihr seid spitze!
Habe was kleines daraus gebastelt. Werde ich
morgen mal vorstellen. Bin jetzt zu müde.
Vielen lieben Dank & Grüße ... Kiffi
Habe was kleines daraus gebastelt. Werde ich
morgen mal vorstellen. Bin jetzt zu müde.
Vielen lieben Dank & Grüße ... Kiffi
Hygge
Re: Ringe aus Grafik ausschneiden
Ooops, ging ja um Ringe und nicht um Kreise. Sorry, habe das Thema total verfehlt.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Re: Ringe aus Grafik ausschneiden
Bei Deinem Code sind die Bilddaten noch da, sie werden nur nicht angezeigtPMV hat geschrieben:Wenns zu kompliziert ist, hier Danilos mit dem Circle-Befehl.
Hier wird auch tatsächlich ein Ring ausgeschnitten.MFG PMVCode: Alles auswählen
UsePNGImageDecoder() Procedure CircleCut(img,x,y,radius1, radius2) If radius1 < radius2 Swap radius1, radius2 EndIf durchmesser = radius1 * 2 result = CreateImage(#PB_Any,durchmesser, durchmesser,32) If StartDrawing(ImageOutput(result)) DrawImage(ImageID(img),-x+radius1,-y+radius1, durchmesser, durchmesser) DrawingMode(#PB_2DDrawing_AlphaChannel) Box(0, 0, durchmesser, durchmesser, $00FFFFFF) Circle(radius1, radius1, radius1, $FFFFFFFF) Circle(radius1, radius1, radius2, $00FFFFFF) StopDrawing() EndIf ProcedureReturn result EndProcedure original = LoadImage(#PB_Any,OpenFileRequester("", "", "*.png", 0)) If original cut = CircleCut(original,100,100,80, 40) If OpenWindow(0, 0, 0, 800, 600, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) CanvasGadget(0, 0, 0, 800, 600) StartDrawing(CanvasOutput(0)) Box(0,0,800,800,$FFFF) DrawingMode(#PB_2DDrawing_AlphaBlend) DrawImage(ImageID(cut),10,10) StopDrawing() Repeat Event = WaitWindowEvent() Until Event = #PB_Event_CloseWindow EndIf EndIf
wenn Du Alpha auf 0 setzt. Mach mal beim zeichnen ins CanvasGadget das
DrawingMode(#PB_2DDrawing_AlphaBlend) weg und Du siehst die Daten sind
noch da. Das macht sicherlich einen Unterschied bei der Speicherung der Bilder
mit Kompression.
Ohne 2 Bilder zu benutzen bekomme ich es allerdings gerade nicht hin
das der AlphaChannel und die Bilddaten am Rand komplett auf 0 gesetzt
werden.
Da das ja nur einmalig zum generieren und abspeichern gebraucht wird,
ist die Geschwindigkeit wohl nicht ganz so wichtig. So sind die nicht
benötigten Daten komplett leer ($00000000), was für eine kleinere
Größe nach dem Abspeichern sorgen sollte:
Code: Alles auswählen
UsePNGImageDecoder()
Procedure CircleCut(img,x,y,radius1, radius2)
If radius1 < radius2
Swap radius1, radius2
EndIf
durchmesser = radius1 * 2
result2 = CreateImage(#PB_Any,durchmesser, durchmesser,32|#PB_Image_Transparent)
If StartDrawing(ImageOutput(result2))
DrawingMode(#PB_2DDrawing_AlphaChannel)
Circle(radius1, radius1, radius1, $FF000000)
Circle(radius1, radius1, radius2, $00000000)
DrawingMode(#PB_2DDrawing_AlphaClip)
DrawImage(ImageID(img),-x+radius1,-y+radius1)
StopDrawing()
EndIf
result = CreateImage(#PB_Any,durchmesser, durchmesser,32|#PB_Image_Transparent)
If StartDrawing(ImageOutput(result))
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(result2),0,0)
StopDrawing()
EndIf
FreeImage(result2)
ProcedureReturn result
EndProcedure
;original = LoadImage(#PB_Any,OpenFileRequester("", "", "*.png", 0))
original = LoadImage(#PB_Any,"02.png")
If original
cut = CircleCut(original,100,100,80, 40)
If OpenWindow(0, 0, 0, 800, 600, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 800, 600)
StartDrawing(CanvasOutput(0))
Box(0,0,800,800,$FFFF)
DrawImage(ImageID(cut),10,10)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(cut),10,310)
StopDrawing()
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
EndIf
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
-
- Beiträge: 6267
- Registriert: 29.08.2004 08:37
- Computerausstattung: Hoffentlich bald keine mehr
- Kontaktdaten:
Re: Ringe aus Grafik ausschneiden
Jop, das was mein zweiter und dritter Code machen. Aber die Aufgabe ist auch nicht detailliert beschrieben, also könnte es alles sein. Kiffi scheint aber schon eine Antwort für sich gefunden zu haben.Falko hat geschrieben:sollte das nicht so sein und davon mehrere Ringe wie eine Dartscheibe, sodass man diese
Ringe übereinander legen kann, damit ein vollständiges Bild zu sehen ist, aber jeder dieser Ringe in eine eigene Datei gespeichert werden sollte?
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Re: Ringe aus Grafik ausschneiden
Hallö,
so, hier - wie versprochen - mein kleines Projekt, für das ich
gestern die Schneidefunktion benötigte:
http://tuebbentools.bplaced.net/RotateLayer/
Die Steuerung ist noch ein wenig hakelig aber mit viel
Spucke und Geduld schafft man es wirklich, alle Winkel
auf einen Modulo von 360° zu bekommen.
Ist insgesamt noch viel Platz für Verbesserungen. Mal
schauen, ob ich mich da noch tiefer reinknien werde.
Übrigens habe ich dann doch die Kreisschneide-Funktion
von Danilo verwendet, weil die Ringe nicht sauber genug
ausgeschnitten werden konnten. Da fehlten an den
Schnitträndern immer ein paar wenige Pixel.
Also, nochmals vielen Dank für Eure tolle Hilfe & Grüße ... Kiffi
so, hier - wie versprochen - mein kleines Projekt, für das ich
gestern die Schneidefunktion benötigte:
http://tuebbentools.bplaced.net/RotateLayer/
Die Steuerung ist noch ein wenig hakelig aber mit viel
Spucke und Geduld schafft man es wirklich, alle Winkel
auf einen Modulo von 360° zu bekommen.
Ist insgesamt noch viel Platz für Verbesserungen. Mal
schauen, ob ich mich da noch tiefer reinknien werde.
Übrigens habe ich dann doch die Kreisschneide-Funktion
von Danilo verwendet, weil die Ringe nicht sauber genug
ausgeschnitten werden konnten. Da fehlten an den
Schnitträndern immer ein paar wenige Pixel.
Also, nochmals vielen Dank für Eure tolle Hilfe & Grüße ... Kiffi
Hygge