RGB_To_HSV et HSV_To_RGB (Color3f)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

RGB_To_HSV et HSV_To_RGB (Color3f)

Message par Guimauve »

Bonjour à tous,

Pour ceux qui travaille sur des images de haute qualité, voici un système de conversion de couleur basé sur des nombres réels au lieu de nombres entiers.

Les composantes Rouge (Red), Verte (Green), Bleu (Blue) sont dites clampées entre [0.0, 1.0]. Pour obtenir les composantes d'une couleur RGB 0 à 255, un petit :

Code : Tout sélectionner

NormalizeColor3f_RGB(RGB_0_255.Color3f, RGB_0_1.Color3f)
et pour faire l'inverse :

Code : Tout sélectionner

ClampColor3f_RGB(RGB_0_1.Color3f, RGB_0_255.Color3fA)
Pour les composantes Teinte (Hue), Saturation (Saturation) et Valeur (Value) ont un clampage différent. La teinte [0.0, 360.0] et pour la saturation ainsi que la valeur le clampage est de [0.0, 1.0].
La commande de normalisation fera la conversion afin que la Teinte ait une valeur allant de [0.0, 255.0] comme pour les autres composantes :

Code : Tout sélectionner

NormalizeColor3f_HSV(HSV_0_255.Color3f, HSV_0_Max.Color3f)
Et pour faire l'inverse pour l'inverse la teinte retrouvera une valeur clampé [0.0, 360.0] alors que la saturation et la valeur leurs clampages [0.0, 1.0]

Code : Tout sélectionner

ClampColor3f_HSV(HSV_0_Max.Color3f, HSV_0_255.Color3fA)
J'ai comparé les résultats de conversion de couleur avec le sélecteur de couleur de l'éditeur "The GIMP" et bien que la normalisation HSV soit différente (Teinte [0,360] et Saturation et Valeur [0, 100]), les résultats ramené sur la même base sont identiques dans les deux conversions.

A+
Guimauve

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; CODE GÉNÉRÉ AUTOMATIQUEMENT, NE PAS MODIFIER À
; MOINS D'AVOIR UNE RAISON TRÈS TRÈS VALABLE !!!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code généré par : Dev-Type V3.137.654
; Nom du projet : Color3f
; Nom du fichier : Color3f.pb
; Version du fichier : 1.0.0
; Programmation : OK
; Programmé par : Guimauve
; Date : 23-02-2012
; Mise à jour : 23-02-2012
; Codé pour PureBasic V4.60
; Plateforme : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Notes à propos des commandes :
;
; - Color3f_RGB_To_HSV()
; - Color3f_HSV_To_RGB()
;
; Source : http://www.cs.rit.edu/~ncs/color/t_convert.html
;
; Les composantes Rouge (Red), Verte (Green), Bleu (Blue), 
; Saturation (Saturation) et Valeur (Value) sont dites
; clampées entre [0.0, 1.0]. La teinte (Hue) est clampée 
; entre [0.0, 360.0]. 
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Déclaration de la Structure <<<<<

Structure Color3f
  
  StructureUnion
    Red.f
    Hue.f
  EndStructureUnion
  
  StructureUnion
    Green.f
    Saturation.f
  EndStructureUnion
  
  StructureUnion
    Blue.f
    Value.f
  EndStructureUnion
  
EndStructure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les observateurs <<<<<

Macro GetColor3fRed(Color3fA)

  Color3fA\Red

EndMacro

Macro GetColor3fHue(Color3fA)

  Color3fA\Hue

EndMacro

Macro GetColor3fGreen(Color3fA)

  Color3fA\Green

EndMacro

Macro GetColor3fSaturation(Color3fA)

  Color3fA\Saturation

EndMacro

Macro GetColor3fBlue(Color3fA)

  Color3fA\Blue

EndMacro

Macro GetColor3fValue(Color3fA)

  Color3fA\Value

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les mutateurs <<<<<

Macro SetColor3fRed(Color3fA, P_Red)

  GetColor3fRed(Color3fA) = P_Red

EndMacro

Macro SetColor3fHue(Color3fA, P_Hue)

  GetColor3fHue(Color3fA) = P_Hue

EndMacro

Macro SetColor3fGreen(Color3fA, P_Green)

  GetColor3fGreen(Color3fA) = P_Green

EndMacro

Macro SetColor3fSaturation(Color3fA, P_Saturation)

  GetColor3fSaturation(Color3fA) = P_Saturation

EndMacro

Macro SetColor3fBlue(Color3fA, P_Blue)

  GetColor3fBlue(Color3fA) = P_Blue

EndMacro

Macro SetColor3fValue(Color3fA, P_Value)

  GetColor3fValue(Color3fA) = P_Value

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Reset <<<<<

Macro ResetColor3f(Color3fA)
 
  ClearStructure(Color3fA, Color3f)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Copy : A = Source : B = Destination <<<<<

Macro CopyColor3f(Color3fA, Color3fB)
 
  CopyMemory(Color3fA, Color3fB, SizeOf(Color3f))

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Compare <<<<<

Macro CompareColor3f(Color3fA, Color3fB)
  
  CompareMemory(Color3fA, Color3fB, SizeOf(Color3f))
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Swap <<<<<

Macro SwapColor3f(Color3fA, Color3fB)

  Swap GetColor3fRed(Color3fA), GetColor3fRed(Color3fB)
  Swap GetColor3fGreen(Color3fA), GetColor3fGreen(Color3fB)
  Swap GetColor3fBlue(Color3fA), GetColor3fBlue(Color3fB)
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur ProductByScalar : R = A * Scalar <<<<<

Macro ProductByScalarColor3f(Color3fR, Color3fA, Scalar)
 
  SetColor3fRed(Color3fR, GetColor3fRed(Color3fA) * Scalar)
  SetColor3fGreen(Color3fR, GetColor3fGreen(Color3fA) * Scalar)
  SetColor3fBlue(Color3fR, GetColor3fBlue(Color3fA) * Scalar)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur DivideByScalar : R = A / Scalar <<<<<

Macro DivideByScalarColor3f(Color3fR, Color3fA, Scalar)
 
  SetColor3fRed(Color3fR, GetColor3fRed(Color3fA) / Scalar)
  SetColor3fGreen(Color3fR, GetColor3fGreen(Color3fA) / Scalar)
  SetColor3fBlue(Color3fR, GetColor3fBlue(Color3fA) / Scalar)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Lecture sur fichier Binaire <<<<<

Macro ReadColor3f(FileID, Color3fA)
  
  ReadData(FileID, Color3fA, SizeOf(Color3f))
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Écriture sur fichier Binaire <<<<<

Macro WriteColor3f(FileID, Color3fA)
  
  WriteData(FileID, Color3fA, SizeOf(Color3f))
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Macro de déboguage <<<<<

Macro DebugColor3f(Color3fA, Flag = 0)
  
  If Flag = 0
    Debug "Red : " + StrF(GetColor3fRed(Color3fA), 4)
    Debug "Green : " + StrF(GetColor3fGreen(Color3fA), 4)
    Debug "Blue : " + StrF(GetColor3fBlue(Color3fA), 4)
  Else
    Debug "Hue : " + StrF(GetColor3fHue(Color3fA), 4)
    Debug "Saturation : " + StrF(GetColor3fSaturation(Color3fA), 4)
    Debug "Value : " + StrF(GetColor3fValue(Color3fA), 4)
  EndIf

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code généré en : 00.011 secondes (23272.73 lignes/seconde) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Update <<<<<

Macro UpdateColor3f(Color3fA, P_Red, P_Green, P_Blue)

  SetColor3fRed(Color3fA, P_Red)
  SetColor3fGreen(Color3fA, P_Green)
  SetColor3fBlue(Color3fA, P_Blue)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Update <<<<<

Macro UpdateColor3f_HSV(Color3fA, P_Hue, P_Saturation, P_Value)

  SetColor3fHue(Color3fA, P_Hue)
  SetColor3fSaturation(Color3fA, P_Saturation)
  SetColor3fValue(Color3fA, P_Value)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur ClampColor3f_RGB <<<<<

Macro ClampColor3f_RGB(Color3fR, Color3fA)
 
  DivideByScalarColor3f(Color3fR, Color3fA, 255)
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur ClampColor3f_RGB <<<<<

Macro NormalizeColor3f_RGB(Color3fR, Color3fA)
 
  ProductByScalarColor3f(Color3fR, Color3fA, 255)
  
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur ClampColor3f_HSV <<<<<

Macro ClampColor3f_HSV(Color3fR, Color3fA)
 
  SetColor3fHue(Color3fR, GetColor3fHue(Color3fA) * 360 / 255)
  SetColor3fSaturation(Color3fR, GetColor3fSaturation(Color3fA) / 255)
  SetColor3fValue(Color3fR, GetColor3fValue(Color3fA) / 255)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur DivideByScalar : R = A / Scalar <<<<<

Macro NormalizeColor3f_HSV(Color3fR, Color3fA)
 
  SetColor3fHue(Color3fR, GetColor3fHue(Color3fA) * 255 / 360)
  SetColor3fSaturation(Color3fR, GetColor3fSaturation(Color3fA) * 255)
  SetColor3fValue(Color3fR, GetColor3fValue(Color3fA) * 255)

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Macro MinMax 3 <<<<<

Macro MinMax3(P_Min, P_Max, P_Number01, P_Number02, P_Number03)
  
  P_Min = P_Number01
  P_Max = P_Number01  
  
  If P_Number02 < P_Min
    P_Min = P_Number02
  EndIf
  
  If P_Number02 > P_Max
    P_Max = P_Number02
  EndIf
  
  If P_Number03 < P_Min
    P_Min = P_Number03
  EndIf
  
  If P_Number03 > P_Max
    P_Max = P_Number03
  EndIf
  
EndMacro

Procedure Color3f_RGB_To_HSV(*Color3f_RGB.Color3f, *Color3f_HSV.Color3f)
  
  MinMax3(P_Min.f, P_Max.f, GetColor3fRed(*Color3f_RGB), GetColor3fGreen(*Color3f_RGB), GetColor3fBlue(*Color3f_RGB))

  SetColor3fValue(*Color3f_HSV, P_Max)
  
  Delta.f = P_Max - P_Min 
  
  If Delta <> 0.0
    
    SetColor3fSaturation(*Color3f_HSV, Delta / P_Max)
    
    If GetColor3fRed(*Color3f_RGB) = P_Max
      SetColor3fHue(*Color3f_HSV, (GetColor3fGreen(*Color3f_RGB) - GetColor3fBlue(*Color3f_RGB)) / Delta)
    ElseIf GetColor3fGreen(*Color3f_RGB) = P_Max
      SetColor3fHue(*Color3f_HSV, 2.0 + (GetColor3fBlue(*Color3f_RGB) - GetColor3fRed(*Color3f_RGB)) / Delta)
    ElseIf GetColor3fBlue(*Color3f_RGB) = P_Max
      SetColor3fHue(*Color3f_HSV, 4.0 + (GetColor3fRed(*Color3f_RGB) - GetColor3fGreen(*Color3f_RGB)) / Delta)
    EndIf
    
    SetColor3fHue(*Color3f_HSV, 60 * GetColor3fHue(*Color3f_HSV))
    
    If GetColor3fHue(*Color3f_HSV) < 0.0
      SetColor3fHue(*Color3f_HSV, GetColor3fHue(*Color3f_HSV) + 360)
    EndIf

  Else
    
    SetColor3fSaturation(*Color3f_HSV, 0.0)
    SetColor3fHue(*Color3f_HSV, -1.0)
    
  EndIf

  ProcedureReturn 1
EndProcedure

Procedure Color3f_HSV_To_RGB(*Color3f_HSV.Color3f, *Color3f_RGB.Color3f)
  
  If GetColor3fSaturation(*Color3f_HSV) = 0.0
    
    SetColor3fRed(*Color3f_RGB, GetColor3fSaturation(*Color3f_HSV))
    SetColor3fGreen(*Color3f_RGB, GetColor3fSaturation(*Color3f_HSV))
    SetColor3fBlue(*Color3f_RGB, GetColor3fSaturation(*Color3f_HSV))
    
  Else
    
    SecNum.l = Int(Round(GetColor3fHue(*Color3f_HSV) / 60, #PB_Round_Down))
    FracSec.f = GetColor3fHue(*Color3f_HSV) / 60 - SecNum
    
    p.f = GetColor3fValue(*Color3f_HSV) * (1 - GetColor3fSaturation(*Color3f_HSV))
    q.f = GetColor3fValue(*Color3f_HSV) * (1 - GetColor3fSaturation(*Color3f_HSV) * FracSec)
    t.f = GetColor3fValue(*Color3f_HSV) * (1 - GetColor3fSaturation(*Color3f_HSV) * (1 - FracSec))
    
    Select SecNum
        
      Case 0
        UpdateColor3f(*Color3f_RGB, GetColor3fValue(*Color3f_HSV), t, p)

      Case 1
        UpdateColor3f(*Color3f_RGB, q, GetColor3fValue(*Color3f_HSV), p)

      Case 2
        UpdateColor3f(*Color3f_RGB, p, GetColor3fValue(*Color3f_HSV), t)

      Case 3
        UpdateColor3f(*Color3f_RGB, p, q, GetColor3fValue(*Color3f_HSV))

      Case 4
        UpdateColor3f(*Color3f_RGB, t, p, GetColor3fValue(*Color3f_HSV))

      Case 5
        UpdateColor3f(*Color3f_RGB, GetColor3fValue(*Color3f_HSV), p, q)
  
    EndSelect

  EndIf

  ProcedureReturn 1
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<< 
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<< 
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<< 
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

UpdateColor3f(RGB_0_1.Color3f, 1.0, 0.5, 0.25)
NormalizeColor3f_RGB(RGB_0_255.Color3f, RGB_0_1)

DebugColor3f(RGB_0_1)
Debug ""
DebugColor3f(RGB_0_255)
Debug ""
ClampColor3f_RGB(RGB_0_1, RGB_0_255)
DebugColor3f(RGB_0_1)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

UpdateColor3f(HSV_0_MAX.Color3f, 270, 0.5, 0.25)
NormalizeColor3f_HSV(HSV_0_255.Color3f, HSV_0_MAX)

DebugColor3f(HSV_0_MAX, 1)
Debug ""
DebugColor3f(HSV_0_255, 1)
Debug ""
ClampColor3f_HSV(HSV_0_MAX, HSV_0_255)
DebugColor3f(HSV_0_MAX, 1)

Debug ""
Debug "; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
Debug ""

Color3f_RGB_To_HSV(RGB_0_1.Color3f, RGB_0_1_HSV.Color3f)
NormalizeColor3f_HSV(RGB_0_1_HSV, RGB_0_1_HSV)
DebugColor3f(RGB_0_1_HSV, 1)

Debug ""

ClampColor3f_HSV(RGB_0_1_HSV, RGB_0_1_HSV)
Color3f_HSV_To_RGB(RGB_0_1_HSV, RGB_0_1_B.Color3f)
DebugColor3f(RGB_0_1_B) ; Normalement on devrait avoir les valeurs de départ

; <<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< FIN DU FICHIER <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: RGB_To_HSV et HSV_To_RGB (Color3f)

Message par dayvid »

Trop compliquer pour moi :mrgreen:
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: RGB_To_HSV et HSV_To_RGB (Color3f)

Message par Le Soldat Inconnu »

la même chose codé différemment pour la conversion RGB vers TSL (extrait de ma librairie GetColor)

Code : Tout sélectionner

Rouge = 210
Vert = 50
Bleu = 70

If Rouge >= Vert And Rouge >= Bleu
	x = Rouge
	If Vert >= Bleu
		y = Bleu
	Else
		y = Vert
	EndIf
ElseIf Vert >= Rouge And Vert >= Bleu
	x = Vert
	If Rouge >= Bleu
		y = Bleu
	Else
		y = Rouge
	EndIf
Else
	x = Bleu
	If Rouge >= Vert
		y = Vert
	Else
		y = Rouge
	EndIf
EndIf
If Rouge = Vert And Rouge = Bleu
	Teinte = 160
	Saturation = 0
Else
	If Rouge >= Vert And Rouge >= Bleu
		Calcul = (Vert - Bleu) / (x - y)
	ElseIf Vert >= Rouge And Vert >= Bleu
		Calcul = (Bleu - Rouge) / (x - y) + 2
	Else
		Calcul = (Rouge - Vert) / (x - y) + 4
	EndIf
	Teinte = Int(Round(240 / 6 * Calcul, #PB_Round_Nearest)) % 240
	If Teinte < 0
		Teinte = 240 + Teinte
	EndIf
	If x + y < 255
		Saturation = Round(240 * (x - y) / (x + y), #PB_Round_Nearest)
	Else
		Saturation = Round(240 * (x - y) / (2 * 255 - x - y), #PB_Round_Nearest)
	EndIf
EndIf
If Rouge = 0 And Vert = 0 And Bleu = 0
	Luminosite = 0
ElseIf Rouge = 255 And Vert = 255 And Bleu = 255
	Luminosite = 240
Else
	Luminosite = Round(240 * (x + y) / (2 * 255), #PB_Round_Nearest)
EndIf

Debug Teinte
Debug Saturation
Debug Luminosite
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: RGB_To_HSV et HSV_To_RGB (Color3f)

Message par Le Soldat Inconnu »

J'ai rien inventer, j'ai suivi le calcul décrit dans Wikipedia :mrgreen:
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre