Reputation: 3856
I have two colors in my .NET application that are user defined. I'd like to somehow get the color in between those two colors. It's the color in the middle of the gradient. Is there any way to accomplish this?
Upvotes: 3
Views: 3012
Reputation: 1
My function in VB.NET:
'Fade3
Dim opacita As Integer = 1
Dim Amount4 As Double = 50 '50%
Dim Amount5 As Double = 1 'Brightness
Dim Amount6 As Double = 1 'Saturation
Private Function FadeBitmap3(bmp1 As Bitmap, bmp2 As Bitmap) As Bitmap
Dim faded As Bitmap = New Bitmap(bmp1.Width, bmp2.Height) ':/
If bmp1.Width = bmp2.Width Then
If bmp1.Height = bmp2.Height Then
For x = 0 To bmp1.Width - 1
For y = 0 To bmp1.Height - 1
Dim c1 = bmp1.GetPixel(x, y)
Dim c2 = bmp2.GetPixel(x, y)
'Fade 3
Dim dr, dg, db, da As Double
Dim frac As Double = 0.01 * Amount4
Dim omfrac As Double = 1.0 - frac
Dim r, g, b, a As Byte
dr = frac * CLng(c1.R) + omfrac * CLng(c2.R)
dg = frac * CLng(c1.G) + omfrac * CLng(c2.G)
db = frac * CLng(c1.B) + omfrac * CLng(c2.B)
da = frac * CLng(c1.A) + omfrac * CLng(c2.A)
If da > 254 Then da = 254.0
If da < 1 Then da = 1.0
If dr > 254 Then dr = 254.0
If dr < 1 Then dr = 1.0
If dg > 254 Then dg = 254.0
If dg < 1 Then dg = 1.0
If db > 254 Then db = 254.0
If db < 1 Then db = 1.0
Dim min As Double = Math.Min(dr, Math.Min(dg, db))
Dim max As Double = Math.Max(dr, Math.Max(dg, db))
'Saturazione
Dim diff = max - min
Dim ks = Amount6
If (ks * diff > max) Then
ks = max / diff
End If
dr = max - ks * (max - dr)
dg = max - ks * (max - dg)
db = max - ks * (max - db)
'Luminosità
Dim kb = Amount5
If (kb * max > 255.0) Then
kb = 255.0 / max
End If
r = Convert.ToByte(kb * dr + 0.5)
g = Convert.ToByte(kb * dg + 0.5)
b = Convert.ToByte(kb * db + 0.5)
a = Convert.ToByte(da + 0.5)
Dim mixture = Color.FromArgb(a, r, g, b)
faded.SetPixel(x, y, mixture)
Next
Next
End If
End If
Return faded
End Function
Upvotes: 0
Reputation: 1
So was looking for a solution and decided to build off the avg idea to a general, kinda brute force lol, hope this help someone in the future.
// GetColors by Matt Meents, creates const foreach ARGB and then sum out the colors...
public static Color[] GetColors(Color A, Color B, int HowMany) {
List<Color> aRet = new List<Color>();
aRet.Add(A);
if (HowMany > 0) {
Int32 iCount = 0;
int sA = (B.A - A.A) / (HowMany + 1);
int sR = (B.R - A.R) / (HowMany + 1);
int sG = (B.G - A.G) / (HowMany + 1);
int sB = (B.B - A.B) / (HowMany + 1);
int AA = A.A; int AR = A.R; int AG = A.G; int AB = A.B;
while (iCount < HowMany) {
AA += sA; AR += sR; AG += sG; AB += sB;
if (AA > 255) AA = 255; if (AA < 0) AA = 0;
if (AR > 255) AR = 255; if (AR < 0) AR = 0;
if (AG > 255) AG = 255; if (AG < 0) AG = 0;
if (AB > 255) AB = 255; if (AB < 0) AB = 0;
aRet.Add(Color.FromArgb(AA, AR, AG, AB));
iCount++;
}
}
aRet.Add(B);
return aRet.ToArray();
}
Upvotes: 0
Reputation: 1503090
Well, the simplest way is to take the average of each of the red, green, blue and alpha values:
Color c1 = ...;
Color c2 = ...;
Color midpoint = Color.FromArgb((c1.A + c2.A) / 2,
(c1.R + c2.R) / 2,
(c1.G + c2.G) / 2,
(c1.B + c2.B) / 2);
Even though the A, R, G and B properties are bytes, they'll be promoted to ints before addition, so there won't be an overflow problem. The result of the division will still be in the range [0, 255] and FromArgb
takes Int32
values but discards everything other than the lowest 8 bits - just what we want.
An alternative would be to use a different colour model (e.g. HSV) but that would be somewhat more complicated. For gradients, this should do fine.
Upvotes: 14
Reputation: 96
Averaging is the best answer, but a word of caution:
An issue of color averages is that unless they're within the same thematic family, (high R, low G, low B) you'll end up trending towards grey.
Note that the more you use the averaging function, the more grey the result will become.
Upvotes: 8
Reputation: 101635
By color do you mean an instance of Color
struct?
If so, just take every of the R
, G
and B
components in turn, and compute average for each. Combine the result to get your blended color.
Upvotes: 6