Skip to content

Instantly share code, notes, and snippets.

@run-dlang
Created October 2, 2023 21:30
Show Gist options
  • Save run-dlang/a17d2e2b56c9232a1ee914db30c575c6 to your computer and use it in GitHub Desktop.
Save run-dlang/a17d2e2b56c9232a1ee914db30c575c6 to your computer and use it in GitHub Desktop.
Code shared from run.dlang.io.
import std;
struct Color {
ubyte r;
ubyte g;
ubyte b;
ubyte a;
}
enum Colors : Color
{
transparent = Color(0, 0, 0, 0),
black = Color(0, 0, 0, 255),
white = Color(255, 255, 255, 255),
red = Color(255, 0, 0, 255),
green = Color(0, 255, 0, 255),
blue = Color(0, 0, 255, 255),
yellow = Color(255, 255, 0, 255),
cyan = Color(0, 255, 255, 255)
}
Color parseColor(string input)
{
if ([EnumMembers!Colors].canFind!(a => to!string(a) == input))
{
return input.to!Colors;
}
// По умолчанию альфа-канал равен 255 (непрозрачный)
ubyte defaultAlpha = 255;
// Регулярные выражения для различных форматов
auto hexPattern = regex(`^#([0-9a-fA-F]{3,8})$`);
auto rgbPattern = regex(`^rgb\((\d+),\s*(\d+),\s*(\d+)\)$`);
auto rgbaPattern = regex(`^rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d*(?:\.\d+)?)\)$`);
auto hslPattern = regex(`^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$`);
auto hslaPattern = regex(`^hsla\((\d+),\s*(\d+)%,\s*(\d+)%,\s*(\d*(?:\.\d+)?)\)$`);
// Проверка на соответствие
if (matchFirst(input, hexPattern))
{
auto hexMatch = matchFirst(input, hexPattern);
uint hexValue = to!uint(hexMatch[1], 16); // Преобразование всей строки в целое число
switch (hexMatch[1].length)
{
case 3:
return Color(
(hexValue >> 8 & 0xF) | (hexValue >> 4 & 0xF0),
(hexValue >> 4 & 0xF) | (hexValue & 0xF0),
(hexValue & 0xF) | (hexValue << 4 & 0xF0),
defaultAlpha
);
case 6:
return Color(
(hexValue >> 16) & 0xFF,
(hexValue >> 8) & 0xFF,
hexValue & 0xFF,
defaultAlpha
);
case 8:
return Color(
(hexValue >> 24) & 0xFF,
(hexValue >> 16) & 0xFF,
(hexValue >> 8) & 0xFF,
hexValue & 0xFF
);
default:
throw new Exception("Invalid hex color format");
}
}
else if (matchFirst(input, rgbPattern))
{
auto rgbMatch = matchFirst(input, rgbPattern);
return Color(to!ubyte(rgbMatch[1]),
to!ubyte(rgbMatch[2]),
to!ubyte(rgbMatch[3]),
defaultAlpha);
}
else if (matchFirst(input, rgbaPattern))
{
auto rgbaMatch = matchFirst(input, rgbaPattern);
return Color(to!ubyte(rgbaMatch[1]),
to!ubyte(rgbaMatch[2]),
to!ubyte(rgbaMatch[3]),
to!ubyte(round(to!float(rgbaMatch[4]) * 255)));
}
else if (matchFirst(input, hslPattern))
{
auto hslMatch = matchFirst(input, hslPattern);
return hslToRgb(to!float(hslMatch[1]),
to!float(hslMatch[2]) / 100.0,
to!float(hslMatch[3]) / 100.0);
}
else if (matchFirst(input, hslaPattern))
{
auto hslaMatch = matchFirst(input, hslaPattern);
return hslToRgb(to!float(hslaMatch[1]),
to!float(hslaMatch[2]) / 100.0,
to!float(hslaMatch[3]) / 100.0,
to!ubyte(round(to!float(hslaMatch[4]) * 255)));
}
else
{
throw new Exception("Invalid color format");
}
}
Color hslToRgb(float h, float s, float l, ubyte a = 255)
{
float r, g, b;
if (s == 0)
{
r = g = b = l; // achromatic
}
else
{
float hue2rgb(float p, float q, float t)
{
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1.0 / 6.0)
return p + (q - p) * 6.0 * t;
if (t < 1.0 / 2.0)
return q;
if (t < 2.0 / 3.0)
return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
return p;
}
float q = l < 0.5 ? l * (1 + s) : l + s - l * s;
float p = 2 * l - q;
h /= 360.0;
r = hue2rgb(p, q, h + 1.0 / 3.0);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1.0 / 3.0);
}
return Color(to!ubyte(r * 255), to!ubyte(g * 255), to!ubyte(b * 255), a);
}
unittest {
// Hex
assert(parseColor("#F00") == Color(255, 0, 0, 255));
assert(parseColor("#FF0000") == Color(255, 0, 0, 255));
assert(parseColor("#FF000080") == Color(255, 0, 0, 128));
// RGB
assert(parseColor("rgb(255, 0, 0)") == Color(255, 0, 0, 255));
// RGBA
assert(parseColor("rgba(255, 0, 0, 0.5)") == Color(255, 0, 0, 128));
// HSL
assert(parseColor("hsl(0, 100%, 50%)") == Color(255, 0, 0, 255));
assert(parseColor("hsl(120, 100%, 50%)") == Color(0, 255, 0, 255));
assert(parseColor("hsl(240, 100%, 50%)") == Color(0, 0, 255, 255));
// HSLA
assert(parseColor("hsla(0, 100%, 50%, 0.5)") == Color(255, 0, 0, 128));
assert(parseColor("hsla(120, 100%, 50%, 0.5)") == Color(0, 255, 0, 128));
assert(parseColor("hsla(240, 100%, 50%, 0.5)") == Color(0, 0, 255, 128));
}
void main()
{
writeln(parseColor("green"));
writeln(parseColor("rgb(255, 0, 0)"));
writeln(parseColor("rgba(255, 0, 0, 0.5)"));
writeln(parseColor("hsl(120, 100%, 50%)"));
writeln(parseColor("hsla(0, 100%, 50%, 0.5)"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment