-- RGB - HSL -- -- 1. Convert the RBG values to the range 0-1 -- Example: from the video colors page, colorbar red has R=83%, B=7%, G=7%, or in this scale, -- R=.83, B=.07, G=.07 -- -- 2. Find min and max values of R, B, G -- In the example, maxcolor = .83, mincolor=.07 -- -- 3. L = (maxcolor + mincolor)/2 -- For the example, L = (.83+.07)/2 = .45 -- -- 4. If the max and min colors are the same (ie the color is some kind of grey), -- S is defined to be 0, and H is undefined but in programs usually written as 0 -- -- 5. Otherwise, test L. -- If L < 0.5, S=(maxcolor-mincolor)/(maxcolor+mincolor) -- If L >=0.5, S=(maxcolor-mincolor)/(2.0-maxcolor-mincolor) -- For the example, L=0.45 so S=(.83-.07)/(.83+.07) = .84 -- -- 6. If R=maxcolor, H = (G-B)/(maxcolor-mincolor) -- If G=maxcolor, H = 2.0 + (B-R)/(maxcolor-mincolor) -- If B=maxcolor, H = 4.0 + (R-G)/(maxcolor-mincolor) -- For the example, R=maxcolor so H = (.07-.07)/(.83-.07) = 0 -- -- 7. To use the scaling shown in the video color page, convert L and S back to percentages, -- and H into an angle in degrees (ie scale it from 0-360). From the computation in step 6, -- H will range from 0-6. RGB space is a cube, and HSL space is a double hexacone, -- where L is the principal diagonal of the RGB cube. -- Thus corners of the RGB cube; red, yellow, green, cyan, blue, and magenta, become the vertices -- of the HSL hexagon. Then the value 0-6 for H tells you which section of the hexgon you are in. -- H is most commonly given as in degrees, so to convert -- H = H*60.0 -- If H is negative, add 360 to complete the conversion. LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; USE ieee.std_logic_unsigned.all; ENTITY rgb_hsl IS PORT( R : IN STD_LOGIC_VECTOR(4 DOWNTO 0); V : IN STD_LOGIC_VECTOR(5 DOWNTO 0); B : IN STD_LOGIC_VECTOR(4 DOWNTO 0); H : OUT STD_LOGIC_VECTOR(8 DOWNTO 0); S : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); L : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) ); END rgb_hsl; ARCHITECTURE a OF rgb_hsl IS SIGNAL maxcolor : STD_LOGIC_VECTOR(5 DOWNTO 0); SIGNAL mincolor : STD_LOGIC_VECTOR(5 DOWNTO 0); SIGNAL colorsum : STD_LOGIC_VECTOR(6 DOWNTO 0); SIGNAL colordif : STD_LOGIC_VECTOR(5 DOWNTO 0); SIGNAL R_max : STD_LOGIC; SIGNAL V_max : STD_LOGIC; -- SIGNAL B_max : STD_LOGIC; -- déduit, donc inutile signal remain_sig : std_logic_vector(7 downto 0); signal quotient : std_logic_vector(11 downto 0); signal denom_sat : std_logic_vector(7 downto 0); signal numer_sat : std_logic_vector(11 downto 0); signal quotient_hue : std_logic_vector(11 downto 0); signal numer_hue : std_logic_vector(11 downto 0); signal remain_sig2 : std_logic_vector(5 downto 0); component division PORT ( numer : IN STD_LOGIC_VECTOR (11 DOWNTO 0); denom : IN STD_LOGIC_VECTOR (7 DOWNTO 0); quotient : OUT STD_LOGIC_VECTOR (11 DOWNTO 0); remain : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ); end component; component division_hue PORT ( numer : IN STD_LOGIC_VECTOR (11 DOWNTO 0); denom : IN STD_LOGIC_VECTOR (5 DOWNTO 0); quotient : OUT STD_LOGIC_VECTOR (11 DOWNTO 0); remain : OUT STD_LOGIC_VECTOR (5 DOWNTO 0) ); end component; BEGIN -- Process Statement color_extrem : process (R, V, B) begin if R > V(5 downto 1) then -- R > V if B > R then -- B > R > V maxcolor <= B&'0'; mincolor <= V; R_max <= '0'; V_max <= '0'; elsif V(5 downto 1) > B then -- R > V > B maxcolor <= R&'0'; mincolor <= B&'0'; R_max <= '1'; V_max <= '0'; else -- R > B >= V maxcolor <= R&'0'; mincolor <= V; R_max <= '1'; V_max <= '0'; end if; else -- V >= R if not(V(5 downto 1) > B) then -- B >= V >= R maxcolor <= B&'0'; mincolor <= R&'0'; R_max <= '0'; V_max <= '0'; elsif not(B > R) then -- V >= R > B ou V > R >= B maxcolor <= V; mincolor <= B&'0'; R_max <= '0'; V_max <= '1'; else -- V >= B > R maxcolor <= V; mincolor <= R&'0'; R_max <= '0'; V_max <= '1'; end if; end if; end process; sum_dif : process (maxcolor, mincolor) begin colorsum <= ('0'&maxcolor) + ('0'&mincolor); colordif <= maxcolor - mincolor; end process; lum : process (colorsum) begin L <= colorsum(6 downto 1); end process; numer_sat <= colordif&"000000"; sat : process (colordif, colorsum, quotient) begin if colordif = "000000" then S <= "0000000"; else if colorsum(6) = '0' then denom_sat <= "0"&colorsum; S <= quotient(6 downto 0); else denom_sat <= "01111110"-("0"&colorsum); S <= quotient(6 downto 0); end if; end if; end process; hue : process (colordif, quotient_hue, R, V, B, R_max, V_max) begin if colordif = "000000" then H <= "000000000"; else if R_max = '1' then -- H = (G-B)/colordif numer_hue <= ('0'&V&"00000")-('0'&B&'0'&"00000"); H <= quotient_hue(8 downto 0) + "000100000"; -- pour avoir un domaine sur H "continu", ici de 0 à 32 elsif V_max = '1' then -- H = 2.0 + (B-R)/colordif numer_hue <= ('0'&B&'0'&"00000")-('0'&R&'0'&"00000"); H <= quotient_hue(8 downto 0) + "001100001"; -- idem, ici de 33 à 127 else -- H = 4.0 + (R-G)/colordif numer_hue <= ('0'&R&'0'&"00000")-('0'&V&"00000"); H <= quotient_hue(8 downto 0) + "010110000"; -- idem, ici de 128 à 206 end if; -- au final on a H entre 0 et 206 (mais c'est pas le H du "vrai" HSL du coup) end if; end process; -- Component Instantiation Statement division_sat : division PORT MAP ( numer => numer_sat, denom => denom_sat, quotient => quotient, remain => remain_sig ); division_teinte : division_hue PORT MAP ( numer => numer_hue, denom => colordif, quotient => quotient_hue, remain => remain_sig2 ); END a;