Generate color gradient in C# - c#

My question here is similar to the question here, except that I am working with C#.
I have two colors, and I have a predefine steps. How to retrieve a list of Colors that are the gradients between the two?
This is an approach that I tried, which didn't work:
int argbMax = Color.Chocolate.ToArgb();
int argbMin = Color.Blue.ToArgb();
var colorList = new List<Color>();
for(int i=0; i<size; i++)
{
var colorAverage= argbMin + (int)((argbMax - argbMin) *i/size);
colorList.Add(Color.FromArgb(colorAverage));
}
If you try the above code, you will find that a gradual increase in argb doesn't correspond to a visual gradual increase in the color.
Any idea on this?

You will have to extract the R, G, B components and perform the same linear interpolation on each of them individually, then recombine.
int rMax = Color.Chocolate.R;
int rMin = Color.Blue.R;
// ... and for B, G
var colorList = new List<Color>();
for(int i=0; i<size; i++)
{
var rAverage = rMin + (int)((rMax - rMin) * i / size);
var gAverage = gMin + (int)((gMax - gMin) * i / size);
var bAverage = bMin + (int)((bMax - bMin) * i / size);
colorList.Add(Color.FromArgb(rAverage, gAverage, bAverage));
}

Oliver's answer was very close... but in my case some of my stepper numbers needed to be negative. When converting the stepper values into a Color struct my values were going from negative to the higher values e.g. -1 becomes something like 254. I setup my step values individually to fix this.
public static IEnumerable<Color> GetGradients(Color start, Color end, int steps)
{
int stepA = ((end.A - start.A) / (steps - 1));
int stepR = ((end.R - start.R) / (steps - 1));
int stepG = ((end.G - start.G) / (steps - 1));
int stepB = ((end.B - start.B) / (steps - 1));
for (int i = 0; i < steps; i++)
{
yield return Color.FromArgb(start.A + (stepA * i),
start.R + (stepR * i),
start.G + (stepG * i),
start.B + (stepB * i));
}
}

Maybe this function can help:
public IEnumerable<Color> GetGradients(Color start, Color end, int steps)
{
Color stepper = Color.FromArgb((byte)((end.A - start.A) / (steps - 1)),
(byte)((end.R - start.R) / (steps - 1)),
(byte)((end.G - start.G) / (steps - 1)),
(byte)((end.B - start.B) / (steps - 1)));
for (int i = 0; i < steps; i++)
{
yield return Color.FromArgb(start.A + (stepper.A * i),
start.R + (stepper.R * i),
start.G + (stepper.G * i),
start.B + (stepper.B * i));
}
}

public static List<Color> GetGradientColors(Color start, Color end, int steps)
{
return GetGradientColors(start, end, steps, 0, steps - 1);
}
public static List<Color> GetGradientColors(Color start, Color end, int steps, int firstStep, int lastStep)
{
var colorList = new List<Color>();
if (steps <= 0 || firstStep < 0 || lastStep > steps - 1)
return colorList;
double aStep = (end.A - start.A) / steps;
double rStep = (end.R - start.R) / steps;
double gStep = (end.G - start.G) / steps;
double bStep = (end.B - start.B) / steps;
for (int i = firstStep; i < lastStep; i++)
{
var a = start.A + (int)(aStep * i);
var r = start.R + (int)(rStep * i);
var g = start.G + (int)(gStep * i);
var b = start.B + (int)(bStep * i);
colorList.Add(Color.FromArgb(a, r, g, b));
}
return colorList;
}

Use double instead of int:
double stepA = ((end.A - start.A) / (double)(steps - 1));
double stepR = ((end.R - start.R) / (double)(steps - 1));
double stepG = ((end.G - start.G) / (double)(steps - 1));
double stepB = ((end.B - start.B) / (double)(steps - 1));
and:
yield return Color.FromArgb((int)start.A + (int)(stepA * step),
(int)start.R + (int)(stepR * step),
(int)start.G + (int)(stepG * step),
(int)start.B + (int)(stepB * step));

Combining this answer with the idea from several other answers to use floating-point steps, here's a complete method snippet for stepping with floating point. (With integer stepping, I had been getting asymmetrical gradient colors in a 16-color gradient from blue to red.)
Important difference in this version: you pass the total number of colors you want in the returned gradient sequence, not the number of steps to take within the method implementation.
public static IEnumerable<Color> GetColorGradient(Color from, Color to, int totalNumberOfColors)
{
if (totalNumberOfColors < 2)
{
throw new ArgumentException("Gradient cannot have less than two colors.", nameof(totalNumberOfColors));
}
double diffA = to.A - from.A;
double diffR = to.R - from.R;
double diffG = to.G - from.G;
double diffB = to.B - from.B;
var steps = totalNumberOfColors - 1;
var stepA = diffA / steps;
var stepR = diffR / steps;
var stepG = diffG / steps;
var stepB = diffB / steps;
yield return from;
for (var i = 1; i < steps; ++i)
{
yield return Color.FromArgb(
c(from.A, stepA),
c(from.R, stepR),
c(from.G, stepG),
c(from.B, stepB));
int c(int fromC, double stepC)
{
return (int)Math.Round(fromC + stepC * i);
}
}
yield return to;
}

Related

What does "-?" as double type represent in C#?

So I'm running iterations with this formula:
double x = 10 / 0.25 * ((0.0002 * x1 * (10 - 0.25 * x1)) + 0.00217 * x2 * (20 - 0.25 * x2)); With this process: Xn+1 = f(Xn).
And if you start from negative X you will eventually end up with (-/+) infinity, so after 6 iterations I'm supposed to get infinity, but what I got surprised me and I couldn't find anywhere what that is, I got "-?", I've tried comparing it to +/- infinity and tried to compare it to int numbers just to clarify what it is, but I cant get anything out of it, for example, I've tried if ("-?" > 1000) break;, and it doesn't outcome as "true". Neither am I getting any errors by comparing it to int/double, I need to stop iterations when I start going into infinity, how can I do that?
code:
public static double CalculateX1(double x1, double x2)
{
double x = 10 / 0.25 * ((0.0002 * x1 * (10 - 0.25 * x1)) + 0.00217 * x2 * (20 - 0.25 * x2));
return x;
}
public static double CalculateX2(double x2, double x1)
{
double y = 20 / 0.25 * ((0.00052 * x2 * (20 - 0.25 * x2)) + 0.0075 * x1 * (10 - 0.25 * x1));
return y;
}
static void Main(string[] args)
{
string writePath = #"C:\Users\evluc\Desktop\cord.txt";
double X = -5;
double Y = -5;
int pointer = 1;
double[,] coordinates = new double[10001, 2];
coordinates[0, 0] = X;
coordinates[0, 1] = Y;
for (int i = 0; i < 5000; i++)
{
//double XTemp = CalculateX1(X, Y);
//double YTemp = CalculateX2(Y, X);
//X = CalculateX1(coordinates[pointer - 1, 0], coordinates[pointer - 1, 1]);
//Y = CalculateX2(coordinates[pointer - 1, 1], coordinates[pointer - 1, 0]);
coordinates[pointer, 0] = CalculateX1(coordinates[pointer - 1, 0], coordinates[pointer - 1, 1]);
coordinates[pointer, 1] = CalculateX2(coordinates[pointer - 1, 1], coordinates[pointer - 1, 0]);
pointer++;
if (Math.Abs(coordinates[pointer, 0]) > 1000 || Math.Abs(coordinates[pointer, 1]) > 1000)
{
Console.WriteLine("infinity");
Console.ReadKey();
}
}
for (int i = 0; i < 5000; i++)
{
Console.WriteLine("X = " + coordinates[i, 0] + "," + "Y = " + coordinates[i, 1] + "; ");
}
}
I think whatever you use to display/inspect the value cannot print ∞.
double d = double.MinValue;
d *= 2;
Console.WriteLine($"{d}: IsInfinity: {double.IsNegativeInfinity(d)}");
-∞: IsInfinity: True
Stopping at infinity
Here's a loop that stops at infinity:
double d = 2;
var i = 1;
while(!double.IsInfinity(d))
{
d = i*d*d;
i = -i;
}
Console.WriteLine(d);
-∞

C# 2D array interpolation

I need to interpolate whole 2d array in with c#.
I managed to write an interpolation class. It should work as intpl2 function of matlab.
slice: is the 2d array that going to be interpolated
xaxis: interpolated x axis
yaxis: interpolated y axis
It maps as
v0 v1 | v3 v2
EDIT: Solve the issue, but I am open to more elegant solution :)
public static float[,] ArrayBilinear(float[,] slice, float[] xaxis, float[] yaxis)
{
float[,] scaledSlice = new float[xaxis.Length, yaxis.Length];
double xscale = ((xaxis.Length - 1) / (slice.GetLength(0) - 1));
double yscale = ((yaxis.Length - 1) / (slice.GetLength(1) - 1));
for (int x = 0; x < scaledSlice.GetLength(0) ; x++)
{
for (int y = 0; y < scaledSlice.GetLength(1) ; y++)
{
float gx = ((float)x) / xaxis.Length * (slice.GetLength(0) - 1);
float gy = ((float)y) / yaxis.Length * (slice.GetLength(1) - 1);
int xInOriginal = (int)gx;
int yInOriginal = (int)gy;
double v0 = slice[xInOriginal, yInOriginal];
double v1 = slice[xInOriginal + 1, yInOriginal];
double v2 = slice[xInOriginal + 1, yInOriginal + 1];
double v3 = slice[xInOriginal, yInOriginal + 1];
double newValue = (1 - GetScale(xscale, x)) * (1 - GetScale(yscale, y)) * v0 + GetScale(xscale, x) * (1 - GetScale(yscale, y)) * v1 + GetScale(xscale, x) * GetScale(yscale, y) * v2 + (1 - GetScale(xscale, x)) * GetScale(yscale, y) * v3;
scaledSlice[x, y] = (float)newValue;
}
}
return scaledSlice;
}
private static double GetScale(double scale, int i)
{
if (i == 0)
return 0;
if (i % scale > 0)
return (i % scale) / scale;
return 1.0;
}
public static float[] LinSpace(float start, float stop, int length)
{
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
if (length == 0) return new float[0];
if (length == 1) return new[] { stop };
float step = (stop - start) / (length - 1);
var data = new float[length];
for (int i = 0; i < data.Length; i++)
{
data[i] = start + i * step;
}
data[data.Length - 1] = stop;
return data;
}
Test with random 2d array
[Test]
public void testBilinearInterpolation()
{
float[,] array2D = new float[4, 4] { { 0, 0, 0, 5 }, { 1, 1, 4, 0 }, { 0, 1, 3, 1 }, { 0, 4, 0, 1 } };
var xaxes = LinSpace(0, 3, 10);
var yaxes = LinSpace(0, 3, 10);
var intepolatedarr = ArrayBilinear(array2D, xaxes , yaxes);
}
The interpolation result is wrong (Different from interp2 from matlab) I couldn't found why.

Matrix Multiplication returning wrong value

I am calculating values by using weights and bias from MATLAB trained ANN. trying to code a sigmoid simulation equation, but for some reason C# calculations vary too much than that of MATLAB. i.e. error is too high. I tried to check each step of the equation and found out the specific part that is creating the problem (Emphasized part), but I don't know how to solve this issue, if someone could help, would be a huge favour.
1+(purelin(net.LW{2}×(tansig(net.IW{1}×(1-(abs(2×([inputs]-1)))))+net.b{1}))+net.b{2}))/2
//Normalization of Data
public double Normalization(double x, double xMAx, double xMin)
{
double xNorm = 0.0;
xNorm = (x - xMin) / (xMAx - xMin);
if (xNorm < 0)
xNorm = 0;
if (xNorm > 1)
xNorm = 1;
xNorm = Math.Round(xNorm, 4);
return xNorm;
}
// Equation to calculate ANN based Output Values
public double MetrixCalc(double[] Pn, double[,] W1, double[] W2, double[] b1, double b2, double maxValue, double minValue)
{
double FinalValue = 0;
double[] PnCalc1 = new double[Pn.Length];
double[] PnCalc2 = new double[W1.Length / Pn.Length];
for (int i = 0; i < Pn.Length; i++)
{
PnCalc1[i] = 1 - Math.Abs(2 * (Pn[i] - 1));
}
for (int i = 0; i < (W1.Length / Pn.Length); i++)
{
double PnCalc = 0.0;
for (int j = 0; j < Pn.Length; j++)
{
PnCalc = PnCalc + (W1[i, j] * PnCalc1[j]);
}
PnCalc2[i] = PnCalc;
}
for (int i = 0; i < PnCalc2.Length; i++)
{
//PnCalc2[i] = Math.Tanh(PnCalc2[i] + b1[i]);
PnCalc2[i] = PnCalc2[i] + b1[i];
PnCalc2[i] = 2.0 / (1 + Math.Exp(-2 * (PnCalc2[i]))) - 1;
PnCalc2[i] = Math.Round(PnCalc2[i], 4);
}
double FinalCalc = 0.0;
for (int i = 0; i < PnCalc2.Length; i++)
{
*FinalCalc = FinalCalc + (W2[i] * (PnCalc2[i]));*
//FinalValue = FinalCalc;
}
FinalValue = FinalCalc + b2;
FinalValue = 1 + FinalValue;
FinalValue = (1 + FinalValue) / 2.0;
FinalValue = (FinalValue * (maxValue - minValue)) + minValue;
FinalValue = Math.Round(FinalValue, 4);
FinalValue = Math.Abs(FinalValue);
return FinalValue;
}
Problem is solved.
Problem was with the weights matrix copied from MATLAB. debugging mode saved my life. :)

C# Color Matching

Can you help me with my color matching
I tried to search some codes it didn't work well
My logic is like below, with adjustable tolerance like 5% or 10% closest to color:
Red and Light Red = True
Red and Dark Red = True
Red and black = False
here's my code but it didn't work very well
public static bool MatchArgb(int Argb1, int Argb2, int tolerance)
{
Color c1 = Color.FromArgb(Argb1);
Color c2 = Color.FromArgb(Argb2);
return Math.Abs(c1.R - c2.R) <= tolerance ^
Math.Abs(c1.G - c2.G) <= tolerance ^
Math.Abs(c1.B - c2.B) <= tolerance;
}
public static bool MatchColor(Color c1, Color c2, int tolerance)
{
return Math.Abs(c1.R - c2.R) <= tolerance ^
Math.Abs(c1.G - c2.G) <= tolerance ^
Math.Abs(c1.B - c2.B) <= tolerance;
}
Maybe it is a good idea to check how this is done in Paint.NET. I found a clone of it and the corresponding source code here: Pinta/Flood Tool
private static bool CheckColor (ColorBgra a, ColorBgra b, int tolerance)
{
int sum = 0;
int diff;
diff = a.R - b.R;
sum += (1 + diff * diff) * a.A / 256;
diff = a.G - b.G;
sum += (1 + diff * diff) * a.A / 256;
diff = a.B - b.B;
sum += (1 + diff * diff) * a.A / 256;
diff = a.A - b.A;
sum += diff * diff;
return (sum <= tolerance * tolerance * 4);
}

iPhone: Converting C# code to Objective-C

Can you guys help me converting this C# code to Objective-C?
I don't have a clue about C#/Visual Studio!
public static class BezierSpline
{
public static void GetCurveControlPoints(Point[] knots,
out Point[] firstControlPoints, out Point[] secondControlPoints)
{
int n = knots.Length - 1;
// Calculate first Bezier control points
// Right hand side vector
double[] rhs = new double[n];
// Set right hand side X values
for (int i = 1; i < n - 1; ++i)
rhs[i] = 4 * knots[i].X + 2 * knots[i + 1].X;
rhs[0] = knots[0].X + 2 * knots[1].X;
rhs[n - 1] = (8 * knots[n - 1].X + knots[n].X) / 2.0;
// Get first control points X-values
double[] x = GetFirstControlPoints(rhs);
// Set right hand side Y values
for (int i = 1; i < n - 1; ++i)
rhs[i] = 4 * knots[i].Y + 2 * knots[i + 1].Y;
rhs[0] = knots[0].Y + 2 * knots[1].Y;
rhs[n - 1] = (8 * knots[n - 1].Y + knots[n].Y) / 2.0;
// Get first control points Y-values
double[] y = GetFirstControlPoints(rhs);
// Fill output arrays.
firstControlPoints = new Point[n];
secondControlPoints = new Point[n];
for (int i = 0; i < n; ++i)
{
// First control point
firstControlPoints[i] = new Point(x[i], y[i]);
// Second control point
if (i < n - 1)
secondControlPoints[i] = new Point(2 * knots
[i + 1].X - x[i + 1], 2 *
knots[i + 1].Y - y[i + 1]);
else
secondControlPoints[i] = new Point((knots
[n].X + x[n - 1]) / 2,
(knots[n].Y + y[n - 1]) / 2);
}
}
private static double[] GetFirstControlPoints(double[] rhs)
{
int n = rhs.Length;
double[] x = new double[n]; // Solution vector.
double[] tmp = new double[n]; // Temp workspace.
double b = 2.0;
x[0] = rhs[0] / b;
for (int i = 1; i < n; i++) // Decomposition and forward substitution.
{
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
for (int i = 1; i < n; i++)
x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
return x;
}
}
thanks.
double[] tmp = new double[n];
tmp is an array of length n. Each value is not initialized explicitly, but it is implicitly set to the default value of the double type, which is 0. So tmp is an n length array of zeros. {0,0,0,0,0, ... 0}

Categories