void FormatHexColor(char *buffer, size_t size, const RGB8Color color) { assert(size >= 7); snprintf(buffer, size, "#%02X%02X%02X", color.Red(), color.Green(), color.Blue()); }
static constexpr RGB8Color Interpolate(RGB8Color c1, RGB8Color c2, unsigned f, unsigned of, unsigned interp_levels) { return RGB8Color((f * c2.Red() + of * c1.Red()) >> interp_levels, (f * c2.Green() + of * c1.Green()) >> interp_levels, (f * c2.Blue() + of * c1.Blue()) >> interp_levels); }
/** * Shade the given color according to the illumination value. * * illum = 64: Contour, mixed with 50% brown * illum < 0: Shadow, mixed with up to 50% dark blue * illum > 0: Highlight, mixed with up to 25% yellow * illum = 0: No shading */ gcc_const inline BGRColor TerrainShading(const int illum, RGB8Color color) { if (illum == -64) { // brown color mixed in for contours return BGRColor(MIX(100, color.Red(), 64), MIX(70, color.Green(), 64), MIX(26, color.Blue(), 64)); } else if (illum < 0) { // shadow to blue int x = std::min(63, -illum); return BGRColor(MIX(0, color.Red(), x), MIX(0, color.Green(), x), MIX(64, color.Blue(), x)); } else if (illum > 0) { // highlight to yellow int x = std::min(32, illum / 2); return BGRColor(MIX(255, color.Red(), x), MIX(255, color.Green(), x), MIX(16, color.Blue(), x)); } else return BGRColor(color.Red(), color.Green(), color.Blue()); }
explicit constexpr Color(RGB8Color other) :r(Import(other.Red())), g(Import(other.Green())), b(Import(other.Blue())), a(MAX) {}
explicit constexpr Color(RGB8Color other) :value({other.Red(), other.Green(), other.Blue(), OPAQUE}) {}
explicit constexpr Color(RGB8Color other) :value(RGB(other.Red(), other.Green(), other.Blue())) {}
int main(int argc, char **argv) { const ColorRamp ramp[] = { {0, 0xff, 0x80, 0x00}, {1000, 0x00, 0x40, 0xcc}, }; const ColorRamp ramp2[] = { {-1000, 0x00, 0x00, 0xff}, { -1, 0x00, 0xff, 0xff}, { 0, 0xff, 0xff, 0x00}, { 1000, 0xff, 0x00, 0x00}, }; RGB8Color color; plan_tests(39); // Test lower limit color = ColorRampLookup(0, ramp, 2); ok1(color.Red() == 0xff); ok1(color.Green() == 0x80); ok1(color.Blue() == 0x00); // Test below lower limit color = ColorRampLookup(-100, ramp, 2); ok1(color.Red() == 0xff); ok1(color.Green() == 0x80); ok1(color.Blue() == 0x00); // Test upper limit color = ColorRampLookup(1000, ramp, 2); ok1(color.Red() == 0x00); ok1(color.Green() == 0x40); ok1(color.Blue() == 0xcc); // Test above upper limit color = ColorRampLookup(1500, ramp, 2); ok1(color.Red() == 0x00); ok1(color.Green() == 0x40); ok1(color.Blue() == 0xcc); // Test middle color = ColorRampLookup(500, ramp, 2); ok1(color.Red() == 0x7f); ok1(color.Green() == 0x60); ok1(color.Blue() == 0x66); // Test lower limit color = ColorRampLookup(-1000, ramp2, 4); ok1(color.Red() == 0x00); ok1(color.Green() == 0x00); ok1(color.Blue() == 0xff); // Test below lower limit color = ColorRampLookup(-2000, ramp2, 4); ok1(color.Red() == 0x00); ok1(color.Green() == 0x00); ok1(color.Blue() == 0xff); // Test upper limit color = ColorRampLookup(1000, ramp2, 4); ok1(color.Red() == 0xff); ok1(color.Green() == 0x00); ok1(color.Blue() == 0x00); // Test above upper limit color = ColorRampLookup(2000, ramp2, 4); ok1(color.Red() == 0xff); ok1(color.Green() == 0x00); ok1(color.Blue() == 0x00); // Test interpolation point 1 color = ColorRampLookup(0, ramp2, 4); ok1(color.Red() == 0xff); ok1(color.Green() == 0xff); ok1(color.Blue() == 0x00); // Test interpolation point 2 color = ColorRampLookup(-1, ramp2, 4); ok1(color.Red() == 0x00); ok1(color.Green() == 0xff); ok1(color.Blue() == 0xff); // Test intermediate point 1 color = ColorRampLookup(500, ramp2, 4); ok1(color.Red() == 0xff); ok1(color.Green() == 0x7f); ok1(color.Blue() == 0x00); // Test intermediate point 2 color = ColorRampLookup(-500, ramp2, 4); ok1(color.Red() == 0x00); ok1(color.Green() == 0x7f); ok1(color.Blue() == 0xff); return exit_status(); }