Reputation: 55257
Is there a way to find the complement of a color given its RGB values? Or can it only be found for certain colors? How would someone go about doing this in Java?
Upvotes: 19
Views: 22481
Reputation: 466
This is what I come up: (Conjecture)
Let r
, g
, and b
be RGB components of the original color.
Let r'
, g'
, and b'
be RGB components of the complementary color.
Then:
r' = max(r,b,g) + min(r,b,g) - r
b' = max(r,b,g) + min(r,b,g) - b
g' = max(r,b,g) + min(r,b,g) - g
I see that this gives the same answer to what the websites (i.e. www.color-hex.com) give, but I will still prove it. :)
EDIT (23/07/2023): Yeah this old "immature" answer of mine needs long-due explanation:
Upvotes: 11
Reputation: 5248
For a rough approximation, you can do this by converting RGB to HSL (Hue, Saturation, Lightness).
With the HSL value, shift the hue 180 degrees to get a color on the opposite of the color wheel from the original value.
Finally, convert back to RGB.
I've written a JavaScript implementation using a hex value here - https://stackoverflow.com/a/37657940/4939630
For RGB, simply remove the hex to RGB and RGB to hex conversions.
Upvotes: 2
Reputation: 7601
A more general and simple solution for finding the opposite color is:
private int getComplementaryColor( int color) {
int R = color & 255;
int G = (color >> 8) & 255;
int B = (color >> 16) & 255;
int A = (color >> 24) & 255;
R = 255 - R;
G = 255 - G;
B = 255 - B;
return R + (G << 8) + ( B << 16) + ( A << 24);
}
Upvotes: 4
Reputation: 4810
You might find more information at: Programmatically choose high-contrast colors
public static int complimentaryColour(int colour) {
return ~colour;
}
Upvotes: -1
Reputation:
Just focusing on the 3D RGB cube. Here's a function that does a binary search in that cube to avoid having to figure out how to cast vectors in a direction and find the closest point on the cube boundary that intersects it.
def farthestColorInRGBcubeFrom(color):
def pathsAt(r, g, b):
paths = [(r, g, b)]
if r < 255:
paths.append((int((r + 255)/2), g, b))
if r > 0:
paths.append((int(r/2), g, b))
if g < 255:
paths.append((r, int((g + 255)/2), b))
if g > 0:
paths.append((r, int(g/2), b))
if b < 255:
paths.append((r, g, int((b + 255)/2)))
if b > 0:
paths.append((r, g, int(b/2)))
return paths
r = color.red(); g = color.green(); b = color.blue();
#naive guess:
r0 = 255 - r; g0 = 255 - g; b0 = 255 - b;
paths = pathsAt(r0, g0, b0)
maxPath = None
while paths != []:
for p in paths:
d = (r - p[0])**2 + (g - p[1])**2 + (b - p[0])**2
if maxPath != None:
if d > maxPath[0]:
maxPath = (d, p)
else:
maxPath = (d, p)
p = maxPath[1]
paths = pathsAt(p[0], p[1], p[2])
c = maxPath[1]
return QColor(c[0], c[1], c[2], color.alpha())
Upvotes: 0
Reputation: 1600
None of the answers above really give a way to find the complimentary color, so here's my version written in Processing:
import java.awt.Color;
color initial = color(100, 0, 100);
void setup() {
size(400, 400);
fill(initial);
rect(0, 0, width/2, height);
color opposite = getOppositeColor(initial);
fill(opposite);
rect(width/2, 0, width/2, height);
}
color getOppositeColor(color c) {
float[] hsv = new float[3];
Color.RGBtoHSB(c>>16&0xFF, c>>8&0xFF, c&0xFF, hsv);
hsv[0] = (hsv[0] + 0.5) % 1.0;
// black or white? return opposite
if (hsv[2] == 0) return color(255);
else if (hsv[2] == 1.0) return color(0);
// low value? otherwise, adjust that too
if (hsv[2] < 0.5) {
hsv[2] = (hsv[2] + 0.5) % 1.0;
}
return Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]);
}
Upvotes: 0
Reputation: 16673
it should just be math
the total of the r values of the 2 colors should be 255
the total of the g values of the 2 colors should be 255
the total of the b values of the 2 colors should be 255
Upvotes: -3