I am writing a UI for a legacy computer called an Amiga (some of you may remember these). They had display modes that had fixed numbers of colours - 2,4,8,16 etc. and you could set any of these using the RGB of 0 to 255.
So on a 4 colour display you could have:
The maximum number of colours you could have on 'normal' display was 255 (there were some special display modes that pushed this higher but I don't need to worry about these).
I am trying to write some C code that will read through the display's colour list and find the reddest, greenest, and bluest colour, but I just cannot get my head around the comparisons involved.
If I have 3 vars -red, green & blue - all ints which hold the current colours rgb vals and 3 more - stored_red, stored_stored_green & stored_blue.
How can I write a function that will remember the colour number which has the most red in relation to the other colours?
I've tried:
If ((red>stored_red) && ((blue <stored_blue) || (green<stored_green)))
But this doesn't work. I think I need to work on ratios but just cannot figure out the maths.
There are different ways to check for maximum "redness"/"greenness" etc, this first simple way here is what my answer originally used:
/* for all palette (color table) entries */
if(red > stored_red) {
max_red_index = current_index;
stored_red = red;
}
if(blue > stored_blue) {
max_blue_index = current_index;
stored_blue = blue;
}
and the same for green of course.
This will just give the colors with the maximum components, but after the comment of @Chris Turner I think this is probably not what you want.
Another way could be to check the ratio of red to the other colors (I'll just use only red from now on):
redness = red*2/(blue + green + 1)
This gives a number between 1 and 510 for "redness", it does not consider brightness. For example R-G-B 50-10-10 is more red (4) than 255-100-100 (2).
Many other formulas are possible, something like
redness = red*red/(blue + green + 1)
would also take the brightness into account and would consider 255-100-100 more red than 50-10-10.
To use these formulas, just set the red
variable from above to the result of the redness formula.
You should calculate the percentage of red to find the reddest color.
Here is a program that uses an RGB
structure, with a function to compare two RGB
structures for "reddness". If two colors have the same percentage of red, the color with the largest value in the .r
field is considered "redder". Another function takes an array of pointers to RGB
structures and returns a pointer to the RGB triple considered "reddest".
Note that care must be taken to check for RGB tuples which are all zeros (0, 0, 0) when calculating the percentage; this could lead to an attempted division by zero. Thanks to @alain for catching this mistake in my original code.
#include <stdio.h>
#include <stdbool.h>
struct RGB {
int r;
int g;
int b;
};
bool is_redder_pct(struct RGB *triple1, struct RGB *triple2);
struct RGB * max_red(struct RGB *triples, size_t num_triples);
int main(void)
{
struct RGB colors[] = { { .r = 125, .g = 0, .b = 0 },
{ .r = 150, .g = 255, .b = 0 },
{ .r = 100, .g = 20, .b = 21 },
{ .r = 255, .g = 21, .b = 22 },
{ .r = 0, .g = 0, .b = 0 },
{ .r = 255, .g = 255, .b = 255 },
{ .r = 128, .g = 128, .b = 128 },
{ .r = 255, .g = 0, .b = 0 } };
size_t num_colors = sizeof colors / sizeof *colors;
struct RGB *reddest = max_red(colors, num_colors);
printf("The reddest color is: (%d, %d, %d)\n",
reddest->r, reddest->g, reddest->b);
return 0;
}
/* Returns true if triple1 is at least as red as triple2 */
bool is_redder_pct(struct RGB *triple1, struct RGB *triple2)
{
bool ret_val;
int triple1_sum = triple1->r + triple1->g + triple1->b;
int triple2_sum = triple2->r + triple2->g + triple2->b;
/* if triple1 is black, triple1 is not redder than triple2 */
if (triple1_sum == 0) {
ret_val = false;
/* otherwise, if triple2 is black, triple1 is redder than triple2 */
} else if (triple2_sum == 0) {
ret_val = true;
/* otherwise the percentages are calculated in a comparison */
} else {
ret_val = triple1->r / (triple1_sum * 1.0)
>= triple2->r / (triple2_sum * 1.0);
}
return ret_val;
}
/* Returns a pointer to the RGB struct in the array TRIPLES
* that compares "reddest" */
struct RGB * max_red(struct RGB *triples, size_t num_triples)
{
struct RGB *max = &triples[0];
for (size_t i = 1; i < num_triples; i++) {
struct RGB *curr = &triples[i];
if (is_redder_pct(curr, max) && curr->r > max->r) {
max = curr;
}
}
return max;
}
Program output:
The reddest color is: (255, 0, 0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With