Skip to content

Instantly share code, notes, and snippets.

@mtwilliams
Last active September 1, 2017 12:14
Show Gist options
  • Save mtwilliams/3c7a89e3fa8afd3de7da70231a0dac92 to your computer and use it in GitHub Desktop.
Save mtwilliams/3c7a89e3fa8afd3de7da70231a0dac92 to your computer and use it in GitHub Desktop.
Generates a table of pretty colors.
//
// Generates a table of evenly distributed and colors at fixed saturation and
// value.
//
// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
//
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
static const float GOLDEN_RATIO = 1.618033988749895f;
static const float GOLDEN_RATIO_CONJUGATE = 1.f - GOLDEN_RATIO;
uint32_t hsv_to_rgba(float h, float s, float v) {
const unsigned slice = (unsigned)(h * 6);
const float f = (h * 6) - floor(h);
const float p = v * (1 - s);
const float q = v * (1 - (f * s));
const float t = v * (1 - (1 - f) * s);
float r, g, b;
switch (slice) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return (((uint32_t)(r * 255.f) & 0xff) << 24)
| (((uint32_t)(g * 255.f) & 0xff) << 16)
| (((uint32_t)(b * 255.f) & 0xff) << 8)
| 0xff;
}
typedef struct color { float r, g, b, a; } color_t;
color_t unpack(uint32_t packed) {
return {
((packed >> 24) & 0xff) * 1.f / 255.f,
((packed >> 16) & 0xff) * 1.f / 255.f,
((packed >> 8) & 0xff) * 1.f / 255.f,
((packed >> 0) & 0xff) * 1.f / 255.f
};
}
int main(int argc, const char *argv[]) {
// Number of colors to generate.
static const unsigned N = 32;
// Table width and height.
static const unsigned W = 6;
static const unsigned H = (N + W - 1) / W;
// Seed the standard random number generator.
srand(time(NULL));
// Pick a random starting hue, and fix saturation and value.
float hue = (float)rand() / (float)RAND_MAX;
const float sat = 0.5f;
const float value = 0.80f;
uint32_t *T = (uint32_t *)calloc(N, sizeof(uint32_t));
for (unsigned i = 0; i < N; ++i) {
T[i] = hsv_to_rgba(hue, sat, value);
hue = hue + GOLDEN_RATIO_CONJUGATE;
hue -= floorf(hue);
}
// Produce a nicely formatted tables.
printf("static const uint32_t char T[%u] = {\n", N); {
for (unsigned y = 0; y < (H-1); ++y) {
printf(" ");
for (unsigned x = 0; x < W; ++x)
printf("0x%08x, ", (unsigned)T[y * W + x]);
printf("\n");
}
// Last line may not be full width.
printf(" ");
for (unsigned x = 0; x < (N - W*(H-1)); ++x)
printf("0x%08x, ", (unsigned)T[(H-1) * W + x]);
printf("\n");
} printf("};\n");
printf("static const float T[%u][4] = {\n", N); {
for (unsigned y = 0; y < (H-1); ++y) {
printf(" ");
for (unsigned x = 0; x < W; ++x) {
const color_t c = unpack(T[y * W + x]);
printf("{%1.3ff, %1.3ff, %1.3ff, %1.3ff}, ", c.r, c.g, c.b, c.a);
}
printf("\n");
}
// Last line may not be full width.
printf(" ");
for (unsigned x = 0; x < (N - W*(H-1)); ++x) {
const color_t c = unpack(T[(H-1) * W + x]);
printf("{%1.3ff, %1.3ff, %1.3ff, %1.3ff}, ", c.r, c.g, c.b, c.a);
}
printf("\n");
} printf("};\n");
free((void *)T);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment