How to randomize between two set colors? - colors

I want to know how to be able to have my program generate random color between two set colors and all inbetween the two. For example just the way that I would say:
fill(random(255),0,0));
in order to get a range reds.
I want to be able to choose two colors, let's say orange and blue, and have it generate colors from these two sets of colors. So for it to randomly generate a color from that shade of blue, any shade in between that and into a specific shade of orange.
How do I go about doing that?

Let's say you have 3 variables that hold the "base" color:
float baseR = 50;
float baseG = 100;
float baseB = 200;
You could then add a random number to those values to get a new shade "around" that color:
float shadeDistance = 10;
float r = baseR + random(-shadeDistance, shadeDistance);
float g = baseG + random(-shadeDistance, shadeDistance);
float b = baseB + random(-shadeDistance, shadeDistance);
fill(r, g, b);
Or if you have two colors that you want to blend, you can use the lerpColor() function:
stroke(255);
background(51);
color from = color(204, 102, 0);
color to = color(0, 102, 153);
color interA = lerpColor(from, to, .33);
color interB = lerpColor(from, to, .66);
fill(from);
rect(10, 20, 20, 60);
fill(interA);
rect(30, 20, 20, 60);
fill(interB);
rect(50, 20, 20, 60);
fill(to);
rect(70, 20, 20, 60);
(source: processing.org)

Related

How do i calculate four colors linear grdient?

If I have four colours (A, B, C & D) on four points on a line and I want to fill with a gradient that blends nicely between the four colours how would I calculate the colour of the point E?
and A is starting point and D is ending point, before starting point and after ending point fill starting colour and end colour. inside line need to blend colour according to the distance and angle.
The closer E is to any of the other points, the strong that colour should affect the result.
I need like this one.
Any idea how to do that? Speed and simplicity is preferred to accuracy.
Well, in simple terms, take point ß that is halfway between A and B. Assuming the use of RGB colors, if A is red rgb(255, 0, 0) and B is yellow rgb(255, 255, 0), then ß's color will be halfway between these: rgb(255, 128, 0), that is, orange.
As you can see this can be calculated by using a weighted average per color channel - weighted by how close your point is to A and B.
Here's a code example you can run right here:
const slider = document.getElementById("range")
const between = document.getElementById("between")
slider.addEventListener("input", ev => {
const distFromA = ev.target.value
const G = distFromA / 3.92
// Not calculating R and B values, as these don't change in this specific example
const R = 255
const B = 0
between.style.background = `rgb(${R}, ${G}, ${B})`
})
#A { background: red; color: white; }
#B { background: yellow; }
#between { background: gainsboro; }
#between, #A, #B { display: inline-block; width: 50px; height: 50px; }
<aside id=A>A</aside>
<aside id=between>ß</aside>
<aside id=B>B</aside>
<nav><input type=range min=0 max=1000 id=range /></nav>
Do this for each pixel and you get a gradient 👍

Change the border coloring of window

I am trying to create a window with custom coloring. I can see how to change the background color of the window when using something like FL_BORDER_BOX (how to change the background color of Fl_Window by pressing Fl_Button), but I can not find out how to change the border color from black. Any help would be appreciated!
Thanks!
This is using C/C++ and FLTK btw.
Instead of using FL_BORDER_BOX, use FL_BORDER_FRAME. The foreground colour of the frame can be changed.
Fl_Box changeling = new Fl_Box(10, 10, 100, 20);
changeling.box(FL_BORDER_FRAME);
changeling.color(FL_RED);
A list of the box types can be found in http://www.fltk.org/doc-1.1/common.html under Box Types
EDIT
If you wish to have a different colour inside, then draw two boxes
int x = 10, y = 10, w = 180, h = 100;
Fl_Box box(x, y, w, h);
box.box(FL_BORDER_FRAME);
box.color(FL_BLUE, FL_RED);
Fl_Box inner(x + 1, y + 1, w - 2, h - 2);
inner.box(FL_FLAT_BOX);
inner.color(FL_YELLOW);

Convert 24-bit color to 4-bit RGBI

I need to convert 24-bit colors to 4-bit RGBI (1 bit for Red, Green, Blue + Intensity).
Converting to 3-bit RGB is rather simple: set color bit if greater than 127, clear otherwise. However, there's only one intensity bit for all three channels, so what's the correct way to set it (if any)?
First I thought about dividing 8-bit channel to three parts like below:
if 0 <= color <= 85, then clear rgbi-color bit
if 86 <= color <= 170, then set rgbi-color bit
if 171 <= color <= 255, then set rgbi-color bit and intensity
But then I thought that probably the correct way would be to set intensity bit only if two of three channels are greater than 127. But in that case pure R, G, or B will not have intensity ever set (for example, in case of rbg(0,0,200)
Any advice is highly appreciated
A simple way to find the closest 4-bit RGBI approximation of a color is to consider the two possibilities for the intensity bit separately. That is to say, first find the closest RGB0 and RGB1 approximations for the color (which is easy to do, just by dividing each color axis at the appropriate point), and the determine which of these approximations is better.
Here's a simple C-ish pseudocode description of this algorithm:
// find the closest RGBx approximation of a 24-bit RGB color, for x = 0 or 1
function rgbx_approx(red, green, blue, x) {
threshold = (x + 1) * 255 / 3;
r = (red > threshold ? 1 : 0);
g = (green > threshold ? 1 : 0);
b = (blue > threshold ? 1 : 0);
return (r, g, b);
}
// convert a 4-bit RGBI color back to 24-bit RGB
function rgbi_to_rgb24(r, g, b, i) {
red = (2*r + i) * 255 / 3;
green = (2*g + i) * 255 / 3;
blue = (2*b + i) * 255 / 3;
return (red, green, blue);
}
// return the (squared) Euclidean distance between two RGB colors
function color_distance(red_a, green_a, blue_a, red_b, green_b, blue_b) {
d_red = red_a - red_b;
d_green = green_a - green_b;
d_blue = blue_a - blue_b;
return (d_red * d_red) + (d_green * d_green) + (d_blue * d_blue);
}
// find the closest 4-bit RGBI approximation (by Euclidean distance) to a 24-bit RGB color
function rgbi_approx(red, green, blue) {
// find best RGB0 and RGB1 approximations:
(r0, g0, b0) = rgbx_approx(red, green, blue, 0);
(r1, g1, b1) = rgbx_approx(red, green, blue, 1);
// convert them back to 24-bit RGB:
(red0, green0, blue0) = rgbi_to_rgb24(r0, g0, b0, 0);
(red1, green1, blue1) = rgbi_to_rgb24(r1, g1, b1, 1);
// return the color closer to the original:
d0 = color_distance(red, green, blue, red0, green0, blue0);
d1 = color_distance(red, green, blue, red1, green1, blue1);
if (d0 <= d1) return (r0, g0, b0, 0);
else return (r1, g1, b1, 1);
}
Alternatively, you could simply use any generic fixed-palette color quantization algorithm. This may yield better results if your actual color palette is not a pure evenly spaced RGBI palette like the code above assumes, but rather something like e.g. the CGA tweaked RGBI palette.

Color over color: how to get the resulting color?

I have the next task:
let's say, there are two colors: color1 and color2
color1 is semi-transparent (color2 maybe too)
I know ARGB values of color1 and color2
how to get the ARGB value of color which you get by overlaying color1 and color2 and vice versa?
Here is an image of what I am looking for:
And here is a code snippet (C#):
private Color getOverlapColor(Color frontColor, Color backColor)
{
//return...
}
The simplest way is to assume a linear scale.
int blend(int front, int back, int alpha)
=> back + (front - back) * alpha / 255;
And then:
Color getOverlapColor(Color front, Color back)
{
var r = blend(front.Red, back.Red, front.Alpha);
var g = blend(front.Green, back.Green, front.Alpha);
var b = blend(front.Blue, back.Blue, front.Alpha);
var a = unsure;
return new Color(r, g, b, a);
}
I'm unsure about how to calculate the resulting alpha:
if both front.Alpha and back.Alpha are 0, the resulting is also 0.
if front.Alpha is 0, the result is back.Alpha.
if front.Alpha is 255, the value of back.Alpha doesn't matter.
if front.Alpha and back.Alpha are both 50%, the result must be larger than 50%.
But I'm sure someone already figured out all of the above. Some SVG renderer, or GIMP, or some other image processing library should already have this code, carefully tested and proven in practice.

Average color (X11 colors)

I want to fill the intersection of two(or more filled) rectangles with the average color. I have the colors of each rectangle stored as unsigned ints. How can I get the average color?
Thank you for you help!
Technically, you might be running on a color-map device, which means you need to go through X11 color management for all of this. You need to query the XColor for your two input colors, compute the average, then look up the closest representable color:
// Query XColor for both input colors
XColor xcol1, xcol2, outcol;
xcol1.pixel = color1;
xcol2.pixel = color2;
XQueryColor(display, colormap, &xcol1);
XQueryColor(display, colormap, &xcol2);
// Average red/green/blue and look up nearest representable color
outcol.red = (xcol1.red + xcol2.red) / 2;
outcol.green = (xcol1.green + xcol2.green) / 2;
outcol.blue = (xcol1.blue + xcol2.blue) / 2;
XAllocColor(display, colormap, &outcol);
// outcol.pixel is now the color to use
On a paletted device, you also need to free the color afterwards etc. - it's a mess, basically.
But in all likelihood you're on a 32-bit truecolor device, which means the integer is just a bitfield of r, g, b and a (not necessarily in that order). You can compute their average like this:
UInt out_color = 0;
for (int i=0; i < 4; i++) {
// Extract channel i from both input colors
UInt in1 = (color1 >> (i*8)) & 0xff;
UInt in2 = (color2 >> (i*8)) & 0xff;
// Compute the average and or it into the output color
out_color |= ((in1 + in2) / 2) << (i*8);
}
Color color1 = Color.FromArgb(UInt1);
Color color2 = Color.FromArgb(UInt2);
Color averageColor = Color.FromArgb(255,(color1.R + color2.R)/2,(color1.G + color2.G)/2,(color1.B + color2.B)/2);
This is assuming that you need a fully opaque average color.

Resources