pátek 31. prosince 2010

Převod RGB Barvy z hexadecimální soustavy do desítkové soustavy

pastelkyJak napovídá nadpis dnešního článku, pokusíme se nalézt řešení problému, na který můžeme narazit v případě, kdy potřebujeme z RGB barvy v hexadecimálním zápisu (FF0000) vytvořit naplněnou strukturu Color ze jmenného prostoru System.Drawing reprezentujícího tuto barvu, tedy červenou (255, 0, 0). Celý problém je založen na absenci metody, která by umožnila tuto strukturu naplnit z barev v hexadecimálním formátu.

Vzhledem k tomu, že se tato funkcionalita občas hodí, byl to impuls k zamyšlení se nad vlastním řešením této problematiky.

Obecně řečeno jde o to převést hexadecimální číslo do desítkové soustavy, protože struktura Color má přímo statickou metodu FromArgb(int Red, int Green, int Blue), díky které je možné ji naplnit jednotlivými složkami.

Řešení není nikterak složité a je založené na převodu z hexadecimální soustavy do desítkové soustavy pomocí tohoto vzorce:

clip_image002

Tento vzorec popisuje obecný převod n číslic v hexadecimální soustavě. Pro převod barvy v RGB barvovém prostoru zapsané hexadecimálně, budeme potřebovat převádět vždy pouze dvouciferné hexadecimální číslo do desítkové soustavy, což lze z výše uvedeného vzorce vyvodit následovně:

clip_image002[5]

a po úpravě se tedy dostaneme k výslednému vzorci:

clip_image002[7]

Pokusme se tento vzorec dosadit a k tomuto účelu použijme červenou barvu reprezentovanou hexadecimálně jako FF0000. Rozeberme si tuto barvu po složkách. Červená složka R je FF zelená složka G je 00 a modrá složka B je také 00. Každá z těchto složek obsahuje dvouciferné hexadecimální číslo složené z číslic x0 a x1. Nyní již máme téměř veškeré informace pro náš převod. Jediné co ještě musíme znát, je jaké číslo reprezentují jednotlivá písmena AF. Přiřazení vidíme v následující tabulce:

A 10
B 11
C 12
D 13
E 14
F 15

Nyní už můžeme dosadit do vzorce hodnoty pro jednotlivé složky. Pro červenou:

clip_image002[10]

Pro zelenou:

clip_image002[12]

A pro modrou:

clip_image002[14]

Výsledkem našeho snažení je, že červená barva v RGB barvovém prostoru reprezentovaná čísli v desítkové soustavě vypadá takto: R=255, G=0, B=0. A s tímto výsledkem již můžeme vytvořit a naplnit strukturu Color:

System.Drawing.Color.FromArgb(255, 0, 0);
A tím bychom mohli být hotovy. Celé toto řešení je zabaleno do třídy Color, která obsahuje navíc informaci o průhlednosti a také strukturu Color plní i s touto informací.

image

Jak je vidět z diagramu naší třídy Color, obsahuje vlastnosti reprezentující jednotlivé složky barvového prostoru R, G, B a vlastnost pro průhlednost A. Dále jsou k dispozici konstruktory, které jsou přetížené a tyto vlastnosti naplňují voláním veřejné metody SetColor za použití popsaného převodu. Dále je pak k dispozici metoda GetColor, která vrací naplněnou strukturu System.Drawing.Color. z vlastností A, R, G, B třídy. Dále třída obsahuje statickou metodu GetColor pro rychlý převod barvy. Privátní metody GetHexDigit a GetIntFromHex jsou také statické, protože je potřebujeme využívat jek ve statické metodě GetColor tak i v nestatické metodě SetColor.

Pojďme se podívat jak to funguje. Pro ukázku funkčnosti využijeme statické metody GetColor, která vrací naplněnou strukturu System.Drawing.Color.

public static System.Drawing.Color GetColor(int Alpha = 255, string Color = "FFFFFF")
{
if (!Regex.IsMatch(Color, @"[A-Fa-f0-9]{6}"))
throw new ArgumentException("Hexadecimální zadání barvy není ve správném tvaru. Například 'FFFFFF'.", "Color");
if (Alpha < 0 || Alpha > 255)
throw new ArgumentException("Hodnota průhlednosti je mimo dovolený rozsah 0-255", "Alpha");

return System.Drawing.Color.FromArgb(Alpha,
GetIntFromHex(Color.Substring(0, 2)),
GetIntFromHex(Color.Substring(2, 2)),
GetIntFromHex(Color.Substring(4, 2))
);
}
Na začátku metody nalezneme nezbytné ošetření vstupů, k čemuž se u hexadecimálního zadání barvy hodí regulární výraz a pak ještě zkontrolujeme rozsah parametru průhlednosti. Oba parametry mají nastavenou výchozí hodnotu. Vlastní převod jednotlivých složek se provádí v metodě GetIntFromHex.
private static int GetIntFromHex(string Hex)
{
int L = GetHexDigit(sHex.Substring(0, 1));
int R = GetHexDigit(sHex.Substring(1, 1));
return (L * 16) + R;
}
Zde se v první řadě provede převod písmeného vyjádření hexadecimálního čísla na číselné pokud je to třeba v metodě GetHexDigit. A poté již nic nebrání aplikování výše popsaného vzorce, při čemž tedy x0 je proměnná L a x1 je proměnná R. Zbývá doplnit již zmíněnou metodu GetHexDigit.
private static int GetHexDigit(string Hex)
{
Hex = Hex.ToLower();
Hex = Hex.Replace("a", "10");
Hex = Hex.Replace("b", "11");
Hex = Hex.Replace("c", "12");
Hex = Hex.Replace("d", "13");
Hex = Hex.Replace("e", "14");
Hex = Hex.Replace("f", "15");

return int.Parse(Hex);
}
Tato metoda se tedy stará o převod písmen na čísla po té, co si případné velké písmena upravíme na malé.

Nyní jsme hotovy a převod bude funkční. Pro úplnost je zde ke stažení kompletní třída Color jako knihovna, a také její zdrojový kód.

Žádné komentáře:

Okomentovat