Weicher Farbverlauf schwarz->regenbogenfarben->weiss

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

Hawkins

Betreff: Weicher Farbverlauf schwarz->regenbogenfarben->weiss

BeitragMi, Aug 12, 2009 0:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Hoi,

weil ich für ein Fraktalprogramm möglichst alle Farben ausnutzen wollte aber weiche verläufe, hab ich diese Funktion geschrieben.

Will man einzelne Pixel zeichnen, muss die Farbe als Integezahl angegeben werden. Zählt man einfach von 0 hoch bis zum maximum (256*256*256 - 1), dann ergibt sich kein Farbverlauf, sondern viele bunte Streifen.

Die Funktion benötigt eine Zahl zwischen 0 und 1, sie liefert den Farbwert zurück, der dem Farbverlauf entspricht. (siehe beispiel)

es fadet in folgender reihenfolge die farben durch
schwarz -> rot -> gelb -> grün -> türkis/cyan -> blau -> lila/magenta -> weiss

user posted image


Es ist deshalb zwischen 0 und 1, sodass mman ohne viel umzurechnen, einfach direkt runterteilen kann.

Code: [AUSKLAPPEN]
Graphics 400,300,16,2
SetBuffer FrontBuffer()

Repeat
   Cls
   For i = 0 To GraphicsWidth()-1
      For j=GraphicsHeight()/2 -5 To GraphicsHeight()/2 + 5
      WritePixel i,j,rgbfade(Float(i)/GraphicsWidth())
      Next
   Next
Until KeyHit(1)


Function rgbfade(value#);0-1
   value#=value#*7
   rise#=(value# Mod 1):fall#=1-rise#
   If Floor(value#)=0 Then r%=rise#*255:g%=0:b%=0   
   If Floor(value#)=1 Then r%=255:g%=rise#*255:b%=0
   If Floor(value#)=2 Then r%=fall#*255:g%=255:b%=0
   If Floor(value#)=3 Then r%=0:g%=255:b%=rise#*255
   If Floor(value#)=4 Then r%=0:g%=fall#*255:b%=255
   If Floor(value#)=5 Then r%=rise#*255:g%=0:b%=255
   If Floor(value#)=6 Then r%=255:g%=rise#*255:b%=255
   colorcode=r%*256^2+g%*256+b%   
   Return colorcode%
End Function


Hier ist die Funktion zusammen mit dem Beispiel.
Man sieht, das in der Funktion 7 Sektoren sind (0 bis 6) bei der immer eine Farbe fest ist (0 oder 255) und eine andere gerade gefadet wird mit rise# oder fall#
SOmit kann die Funktion auch umgebaut werden um andere Farbverläufe zu erzeugen.

Hier eine Skizze, die verdeutlicht, welche Farben wann hochgefaet werden. Die Zahlen oben geben die Sektoren an, links steht, welcher Farbkanal gefadet wird
user posted image

Alles für das "normale" Blitz 2d, damit es möglichst überall läuft (ausser blitzmax).


(Würde nicht automatisch immer dieser Beitrag beim schrieben nach oben scrollen, sodass man blind schrieben muss, würde ich auch tippfehler, groß/kleinschreibung korrigieren. liegt bestimmt am iexplorer :-( )

TimBo

BeitragMi, Aug 12, 2009 0:59
Antworten mit Zitat
Benutzer-Profile anzeigen
nice, sieht nicht schlecht aus, obwohl es doch geschickter wäre das Bild einmal vor der Hauptschleife per CreateImage zu zaubern und dann nur DrawImage auszuführen.

Dürfte das Tempo extrem Steigern.

Grüße
TimBo
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31
hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht.

hazumu-kun

BeitragMi, Aug 12, 2009 11:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Genau, lass den Frabverlauf vorberechnen, nach bestimmten Parametern, und dann wenn man die Farben durchfaden will wird mit Readpixel gearbeitet.

Die Idee von Schwarz-Rot-...-Blau-lila undso ist gut, entspricht sogar bis auf das Ende dem Lichtspektrum.
(Weiß als elementarfrabe gibt es als lichtwelle nicht, magenta prinzipiell auch nicht.)

Ich würde noch eine option einbauen das nur lichtfarben angezeigt werden, das ist für einen echten Regenbogen sinnvoller.
Warum kann es keine omnipotente Macht geben?
Weil diese omnipotente Macht in der Lage sein müsste, einen so schweren Stein zu schaffen, dass sie ihn nicht heben kann
-> nicht omnipotent
 

Hawkins

BeitragMi, Aug 12, 2009 12:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für Euer feedback. Genau sowas hilft mir das zu verbessern. Ich bin immer sehr unzufrieden mit meinen Programmen weil ich immer weiss, man könnte da bestimmt was verbessern.
Die richtigen Kniffe und Tricks beherrsche ich noch nicht.

@ TimBo
Zitat:
obwohl es doch geschickter wäre das Bild einmal vor der Hauptschleife per CreateImage zu zaubern und dann nur DrawImage auszuführen.

Dürfte das Tempo extrem Steigern.


Naja, das ganze einfach als Bild abzuspeichern und dann zu zeichnen würde nur dann was bringen, wenn man direkt so einen farbigen Balken haben möchte.
Aber das war ja nur ein Beispiel. In den Anwendungen soll die Funktion ja dazu dienen einfach einen Parameter per Farbe anzuzeigen. Sagen wir mal, wir haben eine 3D Funktion z=ƒ(x,y) aber wir wollten keine 3D Graphik anzeigen, sondern die 2D-Ebene, dafür aber die z-Werte je nach Wert in einer anderen Farbe. Hätte ich nur einen übergang von schwarz zu rot, dann gäbe es nur 256 Verschiedene Farben, und somit Werte, die für z Unterschieden werden könnten. Und mit dem Auge wäre es unmöglich aus dem Farbton ein zu schätzen, welchen wert z hätte.
Dadurch, dass ich ein möglichst großes Frabspektrum einsetze, wo jede Farbe nur einmal vorkommt (deshalb wird am Ende ins weisse gefadet), lässt sich z besser ablesen und es sieht halt eben auch recht schön aus, wie ich finde.
Aber ich glaube, mit dem vorher abspeichern das lässt sich trotzdem noch nutzen, wie auch viken_emesh erklärt hatte.

@ viken_emesh
Also du meinst, man sollte den Farbverlauf vorzeichnen, ein Pixel hoch und dafür die volle Auflösung breit (in diesem Fall 7*256 = 1792), das ganze aber in einen anderen Buffer zeichnen und dann mit ReadPixel lesen?
Hmm, da verstehe ich noch nicht, wie das gehen könnte.


Achso, ich poste mal die Anwendung, für den ich den Farbverlauf benötigt habe, dann wird klarer wozu er dienen könnte, wie flexibel er seinmüsste, was möglich ist und was nicht.
Ich weiss nur noch nicht, wo ich das posten soll, denn hier unter Codearchiv steht unter
"Wie poste ich richtig" dass keine kompletten Spiele/Module hochgeladen werden sollen. Aber ein richtiges Projekt was unter "sonstiges -> Projekte" gehört, ist es ja auch nicht...

naja, hier der Link https://www.blitzforum.de/foru...p?p=341562
 

Krischan

BeitragMi, Aug 12, 2009 14:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Hast Du Dir schon einmal meine Farbverlaufsfunktion angeschaut? Die ist recht einfach einzusetzen, flexibel und arbeitet mit Arrays.

https://www.blitzforum.de/foru...hp?t=29955
 

Krischan

BeitragMi, Aug 12, 2009 15:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habs mal eingebaut und es funzt. Zwei Anmerkungen: Deine Funktion liefert nicht 0...1 sondern 0.x-1 zurück, mit 255 multipliziert ergibt das 25 bis 255, ich habe mal eine schnelle Normalisierung eingebaut, so dass die Rottöne auch bei rot anfangen. Richtig gut geschrieben wäre es, wenn man alle Werte einmal ausrechnet und zwischenspeichert, dabei den min/max Wert zeitgleich herausfindet und in einer weiteren Funktion dann den normalisierten Wert als Bild ausgibt. Den Ansatz dafür habe ich mal eingebaut.

Und dann ist dein Programm auch noch viel schneller geworden wenn man Flip 0 verwendet:

Code: [AUSKLAPPEN]
Graphics 800,600,32,2
SetBuffer BackBuffer()

Global c#,ci#,maxit%,ra#
Global zoom#,xoff#,yoff#
Global maxx%,maxy%,bit1%=1

Dim Prozent#(0),Rot%(0),Gruen%(0),Blau%(0)
Const maxcols%=256
Global SpectrumR%[maxcols],SpectrumG%[maxcols],SpectrumB%[maxcols]
Global min=65536,max=0

Restore Spektrum
CreateGradient(11,maxcols,False,SpectrumR,SpectrumG,SpectrumB)

initvalues()
Repeat
   For i=0 To maxx-1
      ;If Not bit1% Then AppTitle "Julia-Fraktal   c = "+c#+" + "+ci#+"i     Iterationen = "+maxit%
      ;If bit1% Then AppTitle "Mandelbrot-Fraktal" + "          Iterationen = " + maxit%
      control()
      LockBuffer BackBuffer()
      For j=0 To maxy-1
         x#=Float(xoff#+i-maxx/2)/(maxy/2)
         y#=Float(yoff#+j-maxy/2)/(maxy/2)
         x#=x#/zoom#:y#=y#/zoom#
         
         If Not bit1% Then col%=Int(Floor(jtransform(x#,y#,maxit%)*255))
         If bit1% Then col%=Int(Floor(mtransform(x#,y#,maxit%)*255))
         
         If col<min Then min=col
         If col>max Then max=col
         
         col=Norm(col,25,255,0,255)
         
         rgb=SpectrumR[col]*$10000+SpectrumG[col]*$100+SpectrumB[col]
         
         WritePixelFast i,j,rgb
      Next
      UnlockBuffer BackBuffer()
      AppTitle min+","+max
      Flip 0
   Next
Until KeyHit(1)
End

Function initvalues()
;c#=0 : ci#=0
   c#=-0.74 : ci#=0.12               ;MS
;c#=-0.6 : ci#=0.6                   ;Cantor-Staub
;c#=0.11031 : ci#=0.67037             ;Fatou-Staub
;c#=-0.39054 : ci#=0.58679             ;Siegel-Disk
   maxx%=GraphicsWidth():maxy%=GraphicsHeight()
   xoff#=0:yoff#=0:zoom# = 0.6
   maxit%=50 : ra# = 2000000
End Function

Function jtransform#(x#,y#,maxit%)
   it%=0
   Repeat
      x1#=x#^2 - y#^2 + c#
      y1#=2*x#*y# + ci#
      distance#=Sqr(x1#^2+y2#^2)
      x#=x1#:y#=y1#:it%=it%+1
   Until it%>=maxit% Or distance#>=ra#
   Return Float(it%)/Float(maxit%)
End Function

Function mtransform#(c#,ci#,maxit%)
   it%=0
   Repeat
      x1#=x#^2 - y#^2 + c#
      y1#=2*x#*y# + ci#
      distance#=Sqr(x1#^2+y2#^2)
      x#=x1#:y#=y1#:it%=it%+1
   Until it%>=maxit% Or distance#>=ra#
   Return Float(it%)/Float(maxit%)
End Function

Function control()
   If KeyHit(57) Then bit1%=1-bit1%
   zoom#=zoom#/(2^KeyHit(74)):xoff#=xoff/(2^KeyHit(74)):yoff#=yoff/(2^KeyHit(74))
   zoom#=zoom#*(2^KeyHit(78)):xoff#=xoff*(2^KeyHit(78)):yoff#=yoff*(2^KeyHit(78))
   If KeyHit(203) Then xoff#=xoff#-maxx/4
   If KeyHit(205) Then xoff#=xoff#+maxx/4
   If KeyHit(200) Then yoff#=yoff#-maxy/4
   If KeyHit(208) Then yoff#=yoff#+maxy/4
   maxit%=maxit%+10*KeyHit(201)
   maxit%=maxit%-10*KeyHit(209)
   ci#=ci#-0.02*KeyHit(31)
   ci#=ci#+0.02*KeyHit(17)
   c#=c#-0.02*KeyHit(30)
   c#=c#+0.02*KeyHit(32)   
   If KeyHit(14) Then initvalues()
   If KeyHit(1) Then End
End Function

Function rgbfade(value#);0-1
   value#=value# Mod 1
   value#=value#*7
   rise#=(value# Mod 1):fall#=1-rise#
   If Floor(value#)=0 Then r%=rise#*255:g%=0:b%=0   
   If Floor(value#)=1 Then r%=255:g%=rise#*255:b%=0
   If Floor(value#)=2 Then r%=fall#*255:g%=255:b%=0
   If Floor(value#)=3 Then r%=0:g%=255:b%=rise#*255
   If Floor(value#)=4 Then r%=0:g%=fall#*255:b%=255
   If Floor(value#)=5 Then r%=rise#*255:g%=0:b%=255
   If Floor(value#)=6 Then r%=255:g%=rise#*255:b%=255
   colorcode=r%*256^2+g%*256+b%   
   Return colorcode%
End Function

Function CreateGradient(colors%,steps%,inverse=False,R%[maxcols],G%[maxcols],B%[maxcols])
   
   Dim Prozent#(colors),Rot%(colors),Gruen%(colors),Blau%(colors)
   
   Local i%,pos1%,pos2%,pdiff%
   Local rdiff%,gdiff%,bdiff%
   Local rstep#,gstep#,bstep#
   Local counter%=0
   
   ; Farbcodes einlesen und ggf. invertieren
   If inverse Then
      For i=colors To 1 Step -1
         Read Prozent(i),Rot(i),Gruen(i),Blau(i)
         Prozent(i)=100.0-Prozent(i)
      Next
   Else
      For i=0 To colors-1 : Read Prozent(i),Rot(i),Gruen(i),Blau(i) : Next
   EndIf
   
    ; Gradient berechnen
   While counter<colors
      
        ; Prozent in Step-Position umrechnen
      pos1=Prozent(counter)*steps*1.0/100
      pos2=Prozent(counter+1)*steps*1.0/100
      
        ; Abstand berechnen
      pdiff=pos2-pos1
      
      
        ; Differenz zwischen den Farben berechnen
      rdiff%=Rot(counter)-Rot(counter+1)
      gdiff%=Gruen(counter)-Gruen(counter+1)
      bdiff%=Blau(counter)-Blau(counter+1)
      
        ; Schrittweite zwischen den Farben berechnen
      rstep#=rdiff*1.0/pdiff
      gstep#=gdiff*1.0/pdiff
      bstep#=bdiff*1.0/pdiff
      
      
        ; Zwischenfarbcodes berechnen
      For i=0 To pdiff
         
         R[pos1+i]=Int(Rot(counter)-(rstep*i))
         G[pos1+i]=Int(Gruen(counter)-(gstep*i))
         B[pos1+i]=Int(Blau(counter)-(bstep*i))
         
      Next
      
        ; Zähler erhöhen
      counter=counter+1
      
   Wend
   
End Function

; normalize a value
Function Norm#(v#=128.0,vmin#=0.0,vmax#=255.0,nmin#=0.0,nmax#=1.0)
   
   Return ((v-vmin)/(vmax-vmin))*(nmax-nmin)+nmin
   
End Function

.Spektrum
Data   0.0,255,  0,  0   ; rot
Data  10.0,255,128,  0   ; orange
Data  20.0,255,255,  0   ; gelb
Data  30.0,128,255,  0   ; gelbgrün
Data  40.0,  0,255,  0   ; grün
Data  50.0,  0,255,128   ; grüntürkis
Data  60.0,  0,255,255   ; türkis
Data  70.0,  0,128,255   ; hellblau
Data  80.0,  0,  0,255   ; blau
Data  90.0,128,  0,255   ; violett-blau
Data 100.0,  0,  0,  0   ; scharz

DAK

BeitragMi, Aug 12, 2009 15:27
Antworten mit Zitat
Benutzer-Profile anzeigen
danke!

habs auf bmax umgeschrieben und da sehr gut verwenden können. genau was ich gebraucht hab!
Gewinner der 6. und der 68. BlitzCodeCompo
 

Hawkins

BeitragMi, Aug 12, 2009 15:35
Antworten mit Zitat
Benutzer-Profile anzeigen
joa hab mir das mal angeschaut @ krischan.
wär nur nicht der sourcecode so lang und arrays versuche ich auch zu umgehen.
Ich will imemr ganz kleine funktionen, die auch garnicht großartig auffallen udn möglichst wenig speicher verwenden.

ein ansatz von mir um einen regenverlauf zu machen war auch, die drei kanäle rot grün blau mit nem sinus zu steuern, der je nach kanal 120° verschoben ist (wie beim drehstrom)
somit hat man imemr die gleiche helligkeit. leider ist die sättigung dann nicht immer 100%, weil ja auch dann von jeder farbe ein kleienr anteil drin ist. es wirkt also manchmal "gräulich"

ah freut mich, dass es schon der erste verwenden konnte ^^
 

Krischan

BeitragMi, Aug 12, 2009 15:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Verstehe ich nicht, die Funktion ist eher kurz und viel Speicher verbraucht sie auch nicht.
 

Hawkins

BeitragDo, Aug 13, 2009 12:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja man hat mehrere Funktionen. Aber ich hab mir überlegt, dass wenn man es vorspeichert, man ja auch wiederum 2 Funktionen benötigt.
Naja...

Achso, dass es im Beispiel langsam ist, liegt aber garnicht an dem RGB-Verlauf, sondern einfach am Writepixel mit dem flip.
Und dass es flip 0 auch gibt, ist mir garnicht aufgefallen. das ändert ja alles.. auch mein fraktalprogramm...
das muss ich gleich mal testen.
Danek schön
 

Hawkins

BeitragDo, Aug 13, 2009 14:12
Antworten mit Zitat
Benutzer-Profile anzeigen
nein, es hat mir einfach keine ruhe gelassen:
Ich hab mir noch ne Möglichkeit ausgedacht, wie man den Farbverlauf machen könnte:

Man muss eine Funktion für jeden Farbkanal entwickeln...
ich weiss nicht wie ich es erklären kann, aber hier mal ne Zeichnung:

user posted image

Man sieht oben ist das Verhalten, wie der rote Kanal sich verhalten soll.
Untendrunter die Funktion, die das Verhalten beschreibt, ohne die Werte oberhalb von 1 und unterhalb von 0 ab zu schneiden.

Bei meinem speziellen Farbverlauf wäre das also für rot wie im Bild zu sehen:
r(x) = abs(-abs(-x+1.5)+2.5)-1

der grüne kanal ist gerade punktsymmetrisch dazu (muss aber nen offset bekommen, dass es stimmt), also
g(x) = -r(7-x)+1 = abs(abs(7-x-1.5)-2.5)+2 = abs(abs(5.5-x)-2,5)+2
und blau ist zum glück trivialerweise
b(x)=x-3

also
r(x) = abs(-abs(-x+1.5)+2.5)-1
g(x) = -abs(abs(5.5-x)-2,5)+2
b(x) = x-3

(der verlauf zwischen 0 und 7, lässt sich aber wieder normieren)
die funktionen müssen nur noch geshickt "beschnitten" werden, sodass sie nicht größer als 1 udn nicht kleiner als 0 werden.
Aber ich weiss nicht, ob mit diesem Ansatz die Funktion noch schneller ist, aber vom Source her müsste dieser Ansatz um einiges eleganter sein.

Wie kann ich auf die effektiste und kürzeste weise die funktionen begrenzen, dass die zwischen 0 und 1 bleiben?

und kennt noch jemand einen noch eleganteren Ansatz?


Nachtrag:
Ich glaube das abschneiden der Werte unter null und über 1 könnte man so machen:
r = (r>0)*(r<1)*r + (r>=1)

nach-nachtrag:
Also so funktioniert es auch:
Code: [AUSKLAPPEN]
Function rgbfade(value#);0-1
   value#=value#*7
   r#=Abs(-Abs(-value#+1.5)+2.5)-1:
   g#=-Abs(Abs(5.5-value#)-2.5)+2
   b#=value#-3
   r# = (r#>0)*(r#<1)*r# + (r#>=1)
   g# = (g#>0)*(g#<1)*g# + (g#>=1)   
   b# = (b#>0)*(b#<1)*b# + (b#>=1)   
   Return Int(r#*255)*256^2+Int(g#*255)*256+Int(b#*255)
End Function


Aber nun hab ich wieder für r,g und b float werte, aber damit könnte man ja leben.
Aber es muss noch ne bessere udn Kürzere Lösung geben....
 

Hawkins

BeitragSo, Aug 16, 2009 20:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier die Funktion in einem weiteren Beispielprogramm für einen weichen verlauf durch das Regenbogenspektrum.
Es lässt sich daraus ein geschlossener Farbkreis bilden.

user posted image

Code: [AUSKLAPPEN]
maxx=800:maxy=600
Graphics maxx,maxy,16,2
SetBuffer BackBuffer()

Repeat
   For px = 0 To maxx-1
   LockBuffer BackBuffer()
   For py = 0 To maxy-1
       x#=2*(px-maxx/2.0)/maxy : y#=2*(py-maxy/2.0)/maxy
      gradientpos#=180+ATan2(y,x)/360
      If (x#^2 + y#^2 < 1) And (x#^2 + y#^2 > 0.8) Then WritePixelFast px,py,rainbow(gradientpos#)
   Next
   UnlockBuffer BackBuffer()
   If KeyHit(1) Then End
   Flip 0
   Next

Until KeyHit(1)


Function rainbow(value#);0-1
   value#=value#*6 Mod 6
   r#=Abs(3-value#)-1  :r# = (r#>0)*(r#<1)*r# + (r#>=1)
   g#=-Abs(2-value#)+2 :g# = (g#>0)*(g#<1)*g# + (g#>=1)   
   b#=-Abs(4-value#)+2 :b# = (b#>0)*(b#<1)*b# + (b#>=1)   
   Return Int(r#*255)*256^2+Int(g#*255)*256+Int(b#*255)
End Function
  • Zuletzt bearbeitet von Hawkins am So, Aug 16, 2009 21:22, insgesamt 2-mal bearbeitet

Nicdel

BeitragSo, Aug 16, 2009 20:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Nimm BITTE nicht BMP sondern PNG! Es ist kleiner und verlustfrei. Nicht jeder hat eine 16000-Leitung.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7
 

Hawkins

BeitragSo, Aug 16, 2009 21:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Nicdel hat Folgendes geschrieben:
Nimm BITTE nicht BMP sondern PNG! Es ist kleiner und verlustfrei. Nicht jeder hat eine 16000-Leitung.


Vielen Dank für den Tipp. Habs auch direkt geändert. Ich wusste nie, für was das png-Format da ist. Aber das scheint ja wirklich verlustfrei zu sein. Das werd ich mir merken und öfters benutzen

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group