Jeff Stock
Jeff Stock

Reputation: 3856

Get blend of two colors in .NET

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

Answers (6)

user16860989
user16860989

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

Mattei
Mattei

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

GryPTonite
GryPTonite

Reputation: 21

CByte((CInt(byte1) + CInt(byte2)) \ 2)

Upvotes: 2

Jon Skeet
Jon Skeet

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

user210729
user210729

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

Pavel Minaev
Pavel Minaev

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

Related Questions