Code:
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>
typedef enum {
UNKNOWN = 0,
HSV888,
HSV101010,
} colormodel;
int main(int argc, char *argv[])
{
colormodel model;
FILE *out;
if (argc < 2 || argc > 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s MODEL [ FILENAME ]\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This program outputs a 64-megabyte conversion table,\n");
fprintf(stderr, "from RGB888 (red msb, blue lsb) to the specified model.\n");
fprintf(stderr, "If FILENAME is specified, the table is saved to that file,\n");
fprintf(stderr, "otherwise to standard output.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Supported models:\n");
fprintf(stderr, " HSV888 8-bit hue (msb), saturation, value (lsb)\n");
fprintf(stderr, " HSV101010 10-bit hue (msb), saturation, value (msb)\n");
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
if (!strcmp(argv[1], "HSV888") || !strcmp(argv[1], "hsv888"))
model = HSV888;
else
if (!strcmp(argv[1], "HSV101010") || !strcmp(argv[1], "hsv101010"))
model = HSV101010;
else {
fprintf(stderr, "%s: Unknown model.\n", argv[1]);
return EXIT_FAILURE;
}
if (argc > 2) {
out = fopen(argv[2], "wb");
if (out == NULL) {
fprintf(stderr, "%s: %s.\n", argv[2], strerror(errno));
return EXIT_FAILURE;
}
} else
out = stdout;
if (model == HSV888 || model == HSV101010) {
int red, green, blue;
for (red = 0; red < 256; red++) {
for (green = 0; green < 256; green++) {
const int rgmax = (green >= red) ? green : red;
for (blue = 0; blue < 256; blue++) {
const double alpha = 0.001953125 * (double)(2*red - green - blue);
const double beta = 0.00338291173353296346392 * (double)(green - blue);
const double hue = 0.159154943091895335768883763372514362 * atan2(beta, alpha);
const double chroma = sqrt(alpha * alpha + beta * beta);
const double value = ((blue > rgmax) ? blue : rgmax) / 255.0;
const double saturation = (value > 0.0) ? chroma / value : 0.0;
uint32_t result = 0U;
if (model == HSV888) {
if (hue >= 1.0)
result = 255U << 16;
else
if (hue > 0.0)
result = (uint32_t)(256.0 * hue) << 16;
else
result = 0U;
if (saturation >= 1.0)
result |= 255U << 8;
else
if (saturation > 0.0)
result |= (uint32_t)(256.0 * saturation) << 8;
if (value >= 1.0)
result |= 255U;
else
if (value > 0.0)
result |= (uint32_t)(256.0 * value);
} else
if (model == HSV888) {
if (hue >= 1.0)
result = 1023U << 20;
else
if (hue > 0.0)
result = (uint32_t)(1024.0 * hue) << 20;
else
result = 0U;
if (saturation >= 1.0)
result |= 1023U << 10;
else
if (saturation > 0.0)
result |= (uint32_t)(1024.0 * saturation) << 10;
if (value >= 1.0)
result |= 1023U;
else
if (value > 0.0)
result |= (uint32_t)(1024.0 * value);
}
if (fwrite(&result, sizeof result, 1, out) != 1) {
fprintf(stderr, "Write error.\n");
return EXIT_FAILURE;
}
}
}
fprintf(stdout, "\r%5.1f%% ", 0.390625 * (double)red);
fflush(stdout);
}
fprintf(stdout, "\rAll done.\n");
fflush(stdout);
} else {
fprintf(stderr, "Oops! Model %s is not yet implemented.\n", argv[1]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
However, this approach would allow you to do the image processing using much more interesting colorspaces, like for example 30-bit