Fonctions - gestion de la couleur

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Fonctions - gestion de la couleur

Message par Guillot »

Salut les codeurs,

3 petites fonctions toutes bête, mais que je trouve indispensables pour la gestion des couleurs

- ColorBlend : retourne la couleur resultant du mélange de 2 couleurs (composant alpha inclus)
le paramétré blend [0->1] permet d'ajuster les proportions
(plus pratique que alphablend a mon avis. perso, je vois pas trop son intérêt, en tous cas pour mes besoins)

- HSLToRGB : retourne une couleur (RGB) definit par les parametres hue, saturation, lightness (valeurs comprises entre 0 et 255)
(je me suis aperçu que j'étais pas le premier à la proposer... )
c'est à mon avis la façon la plus pratique et intuitive pour definir une couleur
(surtout pour avoir une liste de couleur bien separé (couleur des joueurs...))

- RGBToHSL : la fonction réciproque (moins utile à mon avis, peut-etre pour le traitement d'image...)

Code : Tout sélectionner

Procedure.l HSLToRGB(hue.a, saturation.a, lightness.a, alpha=0)
    Protected.f h=hue *6/256
    Protected.f s=saturation/255
    Protected.f l=lightness/255
    Protected.f c,x,r_,v_,b_,m
    c=(1-Abs(2*l-1))*s
    x=c*(1-Abs(Mod(h, 2) -1))
    Select Int(h)
        Case 0:r_=c:v_=x
        Case 1:r_=x:v_=c
        Case 2:v_=c:b_=x
        Case 3:v_=x:b_=c
        Case 4:r_=x:b_=c
        Case 5:r_=c:b_=x
    EndSelect
    m=l-c/2
    Protected r,v,b
    r=Int((r_+m)*255)
    v=Int((v_+m)*255)
    b=Int((b_+m)*255)
    ProcedureReturn RGBA(r,v,b,alpha)
EndProcedure

Procedure.l RGBToHSL(red.a, green.a, blue.a, alpha=0)
    Protected.f r=red/255
    Protected.f g=green/255
    Protected.f b=blue/255
    Protected.f cmax, cmin, h_,c,m,h,s,l
    Protected.l imax,imin
    If r>=g And r>=b:imax=1:cmax=r:EndIf
    If g>=r And g>=b:imax=2:cmax=g:EndIf
    If b>=r And b>=g:imax=3:cmax=b:EndIf
    If r<=g And r<=b:imin=1:cmin=r:EndIf
    If g<=r And g<=b:imin=2:cmin=g:EndIf
    If b<=r And b<=g:imin=3:cmin=b:EndIf
    c=cmax-cmin
    Select imax
        Case 1:h_=Mod((g-b)/c+6,6)
        Case 2:h_=(b-r)/c+2
        Case 3:h_=(r-g)/c+4
    EndSelect
    h=h_/6
    l=(cmax+cmin)/2
    If l<>1:s=c/(1-Abs(2*l-1)):Else:s=0:EndIf
    ProcedureReturn RGBA(h*255,s*255,l *255,alpha)  
EndProcedure

Procedure ColorBlend(color1.l, color2.l, blend.f)
    Protected r.w,g.w,b.w,a.w
    r=  Red(color1) + (Red(color2)     - Red(color1)) * blend
    g=Green(color1) + (Green(color2) - Green(color1)) * blend
    b= Blue(color1) + (Blue(color2) -   Blue(color1)) * blend
    a=Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
    ProcedureReturn  RGBA(r,g,b,a)
EndProcedure

; ============= exemple ==============

Define.l i,j,n,x,y,r,h,c

OpenWindow(0, 0, 0, 512, 256, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateImage(0, 512, 256,24,$888888)
StartDrawing(ImageOutput(0))
Box(0, 0, 256, 256, $ffffff)
For j=0 To 255
    For i = 0 To 255
        Plot(i,j, HSLToRGB(i,j,128))
    Next
Next

DrawingMode(#PB_2DDrawing_Gradient)
Macro sphere
    ResetGradientColors()
    GradientColor(0.0,HSLToRGB(h,64,200))
    GradientColor(0.3,HSLToRGB(h,64,128))
    GradientColor(1.0,HSLToRGB(h,64,64))
    CircularGradient(x-r*0.3, y+r*1.2+r*0.5,r)    
    Circle(x,y+r*1.2,r)
    
    ResetGradientColors()
    GradientColor(0.0,HSLToRGB(h,255,255))
    GradientColor(0.3,HSLToRGB(h,255,128))
    GradientColor(1.0,HSLToRGB(h,255,64))
    CircularGradient(x-r*0.3, y-r*0.3,r)    
    Circle(x,y,r)
EndMacro

For j=1 To 4
    n=1<<j
    For i=0 To n-1
        h=(0.5+i)/n*256
        r=50/Sqr(n)
        r=120/n
        x=256+h
        y=16*(i & 1)+330-420/Sqr(n)
        sphere
    Next
Next
StopDrawing() 
ImageGadget(0, 0, 0, 200, 200, ImageID(0))

c=HSLToRGB(128,186,137)
Debug ""+Red(c)+"  "+Green(c)+"  "+Blue(c)+"  "+Alpha(c)
c=RGBToHSL(Red(c),Green(c),Blue(c))
Debug ""+Red(c)+"  "+Green(c)+"  "+Blue(c)+"  "+Alpha(c)

c=ColorBlend($ff0000,$0000ff,0.5)
Debug ""+Red(c)+"  "+Green(c)+"  "+Blue(c)+"  "+Alpha(c)

Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow

Avatar de l’utilisateur
JohnJohnsonSHERMAN
Messages : 648
Inscription : dim. 13/déc./2015 11:05
Localisation : Allez, cherche...
Contact :

Re: Fonctions - gestion de la couleur

Message par JohnJohnsonSHERMAN »

Merci beaucoup du partage !!
A mon avis de telles fonctions devraient même être nativement incluses dans PB.
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Fonctions - gestion de la couleur

Message par Micoute »

Excellent, grand merci pour ce partage !
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Fonctions - gestion de la couleur

Message par Kwai chang caine »

Merci, toujours utiles ce genre de fonctions 8)
Quand on y rajoute les couleurs du HTML, visualbasic, etc...j'ai toujours du mal à m'en sortir
Merci pour le partage
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Fonctions - gestion de la couleur

Message par Zorro »

hum ... je ne suis pas d'accords avec le résultat de ta fonction Blend !

je m'explique , en principe si on mélange la couleur rouge RGB(255,0,0) avec la couleur bleu RGB(0,0,255)

a égale part (100% pour les deux ) on devrai avoir comme résultat un violet RGB(255,0,255)

hors ta procédure renvoie un violet RGB(128,0,128) avec le paramètre de mélangé égale a 0.5

ce n'est donc pas juste !


ici ; la fonction que je propose

pourcent.i est un pourcentage qu'on désire pour les deux couleurs

par exemple si on prends un rouge RGB(255,0,0) et un bleu RGB(0,0,255)
avec un pourcentage de 100% (pourcent.i=100) on obtiendra un
RGB(255,0,255) , ce qui est juste !

si on prends un rouge RGB(255,0,0) et un bleu RGB(0,0,255)
mais avec un pourcentage de 50% (pourcent.i=50)
on obtiendra un RGB(127,0,127) ; ce qui est juste

si on prends un rouge RGB(255,0,0) et un bleu RGB(0,0,255)
mais avec un pourcentage de 25% (pourcent.i=25)
on obtiendra un RGB(63,0,63) ; ce qui est juste

voici le code :)


Code : Tout sélectionner


Procedure ColorBlend2(color1.i, color2.i, pourcent.i)	
;By Zorro	
		protected p1.i,p2.i,r1,v1,b1,a1,r2,v2,b2,a2

		r1=red(color1.i)*pourcent.i/100
		v1=green(color1.i)*pourcent.i/100
		b1=blue(color1.i)*pourcent.i/100
		a1=alpha(color1.i)
		;
		r2=red( color2.i)*pourcent.i/100
		v2=green(color2.i)*pourcent.i/100
		b2=blue(color2.i)*pourcent.i/100
		a2=alpha(color2.i)

		rs=r1+r2
		vs=v1+v2
		bs=b1+b2
		als=(a1+a2)/2
		if rs>255:rs=255:Endif
		if vs>255:vs=255:Endif
		if bs>255:bs=255:Endif
		ProcedureReturn  RGBA(rs,vs,bs,als)
EndProcedure
;
color1.l=rgbA(255,0,0,255)
color2.l=rgbA (0,0,255,255)
pourcent=100 ; en pourcentage

coul_res=ColorBlend2(color1.l, color2.l, pourcent)
debug red(coul_res)
debug green(coul_res)
debug Blue(coul_res)
debug Alpha(coul_res)

Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Re: Fonctions - gestion de la couleur

Message par Guillot »

à zorro:

ColorBlend fait un mélange des 2 couleurs
blend =0 : retourne color1
blend =0.5 : retourne la moyenne des 2 couleurs
blend =1 : retourne color2

une petite exemple pour illustrer:

Code : Tout sélectionner

Procedure ColorBlend(color1.l, color2.l, blend.f)
    Protected r.w,g.w,b.w,a.w
    r=  Red(color1) + (Red(color2)     - Red(color1)) * blend
    g=Green(color1) + (Green(color2) - Green(color1)) * blend
    b= Blue(color1) + (Blue(color2) -   Blue(color1)) * blend
    a=Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
    ProcedureReturn  RGBA(r,g,b,a)
EndProcedure

OpenWindow(0, 0, 0, 512,512, "",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, 512,512)

StartDrawing(CanvasOutput(0))
col=Random($ffffff)
For j=0 To 127
    acol=col:col=Random($ffffff)
    For i=0 To 255
        a.f=(j+i/256)
        r.f=a*a/20
        Circle(256+Cos(a)*r,256+Sin(a)*r,j/4,ColorBlend(acol,col,i/256))
    Next
Next
StopDrawing()

Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Fonctions - gestion de la couleur

Message par Zorro »

oui, c'est bien joli :)


mais c'est pas juste !
soit tu choisi de faire un melange de 2 couleurs, soit tu fais autre chose ! (meme si c'est joli )

pourquoi faire la moyenne ??

lorsque je melange deux couleurs , deux pots de peinture par exemple
le resultat n'est pas la moyenne des deux !!

c'est une nouvelle couleur, l'addition des deux !

voici par exemple un code qui affiche 6 boxs !

la partie gauche est de couleur rouge
la partie droite de couleur bleu

le centre en haut c'est le résultat de ta procédure
le centre en bas , le résultat de la mienne

note, que je ne dis pas que c'est pas joli , je dis juste que ton résultat n'est pas correcte :)
note2 : ton résultat pourrai sembler juste au premier regard , car il ressemble a ce qu'on aurai si nous étions en synthèse
soustractive (sur papier en imprimerie par exemple )

mais sur un écran d'ordinateur, on est en synthèse Additive , et le mélange du bleu pur, et du rouge pur donne un "rose" ;)

ici exemple de synthèse additive
Image


Image

voici le code :

Code : Tout sélectionner

;Voir code plus loin
ps: pour que j'ai la meme couleur que toi , il me faut mettre ma procedure a 50%
ligne : pourcent.i=50 ;%

mais dans ce cas il me manque en fait 50% de la couleur :)
il faudrai 2 parametres pourcent
et lorsque j'en baisse un , ça monte l'autre :)
un peut le principe que tu utilises, mais de 0 a 255 et pas de 0 a 128
Dernière modification par Zorro le mer. 26/oct./2016 16:21, modifié 1 fois.
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Fonctions - gestion de la couleur

Message par Zorro »

j'ai modifié ma procedure pour tenir compte de ta volonter d'utiliser un seul parametre
et que ça change la proportion du melange
j'anime le passage d'une a l'autre couleur tout en respectant un parfait melange lorsque la pourcentage est a 50 % ;)


Image

voici le code :

Code : Tout sélectionner

Declare colorblend(color1.l, color2.l, blend.f)
Declare colorblend2(color1.i, color2.i, Taux.i)
OpenWindow(0, 0, 0, 512,512, "",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, 512,512)
pas=2
Repeat
		StartDrawing(CanvasOutput(0))
				rouge =rgb(255,0,0)
				bleu=rgb(0,0,255)
				blend.f=0.5
				box (1,1,170,255,rouge)
				box (170,1,170,255,ColorBlend(rouge, bleu, blend.f))
				box (342,1,170,255,bleu)
				drawtext (180,200,"violet Guillot")
				; Zorro
				taux.i = taux.i +pas ; on va progressivement passer de l'un a l'autre
				box (1,256,170,255,rouge)
				box (170,256,170,255,ColorBlend2(rouge, bleu,taux.i))
				box (342,256,170,255,bleu)
				drawtext (180,450,"violet Zorro")
				drawtext (180,480,"pourcentage :"+str(taux))
		StopDrawing()
		if taux=100 :pas=-pas:endif
		if taux<=1 :pas=-pas:endif
		delay(100)
Until WaitWindowEvent(2)=#PB_Event_CloseWindow



;zone Procedures
Procedure ColorBlend(color1.l, color2.l, blend.f)
		Protected r.w,g.w,b.w,a.w
		r=  Red(color1) + (Red(color2)     - Red(color1)) * blend
		g=Green(color1) + (Green(color2) - Green(color1)) * blend
		b= Blue(color1) + (Blue(color2) -   Blue(color1)) * blend
		a=Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
		ProcedureReturn  RGBA(r,g,b,a)
EndProcedure
;
Procedure ColorBlend2(color1.i, color2.i, taux.i)   
		;By Zorro   
		If taux<0:taux=0:endif
		If taux>100:taux=100:endif		
		protected p1.i,p2.i,r1,v1,b1,a1,r2,v2,b2,a2
		pourcent1.i=255 * taux  /100
		pourcent2.i=255-pourcent1.i
		r1=red(color1.i)*pourcent1.i/100
		v1=green(color1.i)*pourcent1.i/100
		b1=blue(color1.i)*pourcent1.i/100
		a1=alpha(color1.i)
		;
		r2=red( color2.i)*pourcent2.i/100
		v2=green(color2.i)*pourcent2.i/100
		b2=blue(color2.i)*pourcent2.i/100
		a2=alpha(color2.i)
		rs=r1+r2
		vs=v1+v2
		bs=b1+b2
		als=(a1+a2)/2
		if rs>255:rs=255:Endif
		if vs>255:vs=255:Endif
		if bs>255:bs=255:Endif
		ProcedureReturn  RGBA(rs,vs,bs,als)
EndProcedure
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Répondre