mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-21 16:12:18 -05:00
228 lines
5.8 KiB
C#
228 lines
5.8 KiB
C#
namespace novideo_srgb
|
|
{
|
|
public class Matrix
|
|
{
|
|
private double[,] _values;
|
|
|
|
private Matrix(double[,] values)
|
|
{
|
|
_values = values;
|
|
}
|
|
|
|
public double this[int x, int y]
|
|
{
|
|
get => _values[x, y];
|
|
set => _values[x, y] = value;
|
|
}
|
|
|
|
public double this[int x]
|
|
{
|
|
get
|
|
{
|
|
if (Cols != 1)
|
|
{
|
|
throw new NotSupportedException("Matrix must be 3x1");
|
|
}
|
|
|
|
return _values[x, 0];
|
|
}
|
|
set
|
|
{
|
|
if (Cols != 1)
|
|
{
|
|
throw new NotSupportedException("Matrix must be 3x1");
|
|
}
|
|
|
|
_values[x, 0] = value;
|
|
}
|
|
}
|
|
|
|
public int Rows => _values.GetLength(0);
|
|
public int Cols => _values.GetLength(1);
|
|
|
|
public static Matrix FromValues(double[,] array)
|
|
{
|
|
if (array.GetLength(0) != 3 || !(array.GetLength(1) == 3 || array.GetLength(1) == 1))
|
|
{
|
|
throw new ArgumentException("Array must be 3x3 or 3x1");
|
|
}
|
|
|
|
var result = new Matrix(array);
|
|
return result;
|
|
}
|
|
|
|
public static Matrix Zero3x3()
|
|
{
|
|
return FromValues(new double[3, 3]);
|
|
}
|
|
|
|
public static Matrix Zero3x1()
|
|
{
|
|
return FromValues(new double[3, 1]);
|
|
}
|
|
|
|
public static Matrix One3x1()
|
|
{
|
|
return FromValues(new double[,] { { 1 }, { 1 }, { 1 } });
|
|
}
|
|
|
|
public static Matrix FromDiagonal(double[] array)
|
|
{
|
|
if (array.Length != 3)
|
|
{
|
|
throw new ArgumentException("Array must have length 3");
|
|
}
|
|
|
|
var result = new Matrix(new double[3, 3]);
|
|
for (var i = 0; i < 3; i++)
|
|
{
|
|
result._values[i, i] = array[i];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static Matrix FromDiagonal(Matrix column)
|
|
{
|
|
if (column.Cols != 1)
|
|
{
|
|
throw new ArgumentException("Matrix must be 3x1");
|
|
}
|
|
|
|
return FromDiagonal(new[] { column[0], column[1], column[2] });
|
|
}
|
|
|
|
public static Matrix operator *(Matrix a, Matrix b)
|
|
{
|
|
if (a.Cols != 3)
|
|
{
|
|
throw new ArgumentException("Left side must be 3x3");
|
|
}
|
|
|
|
var result = b.Cols == 3 ? Zero3x3() : Zero3x1();
|
|
|
|
for (var i = 0; i < 3; i++)
|
|
{
|
|
for (var j = 0; j < result.Cols; j++)
|
|
{
|
|
for (var k = 0; k < 3; k++)
|
|
{
|
|
result[i, j] += a[i, k] * b[k, j];
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static Matrix operator *(double a, Matrix b)
|
|
{
|
|
var result = b.Cols == 1 ? Zero3x1() : Zero3x3();
|
|
|
|
for (var i = 0; i < result.Rows; i++)
|
|
{
|
|
for (var j = 0; j < result.Cols; j++)
|
|
{
|
|
result[i, j] = a * b[i, j];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static Matrix operator *(Matrix a, double b)
|
|
{
|
|
return b * a;
|
|
}
|
|
|
|
public static Matrix operator /(double a, Matrix b)
|
|
{
|
|
return 1 / a * b;
|
|
}
|
|
|
|
public static Matrix operator /(Matrix a, double b)
|
|
{
|
|
return a * (1 / b);
|
|
}
|
|
|
|
public static Matrix operator +(Matrix a, Matrix b)
|
|
{
|
|
if (a.Cols != b.Cols)
|
|
{
|
|
throw new ArgumentException("Both sides must have same size");
|
|
}
|
|
|
|
var result = b.Cols == 1 ? Zero3x1() : Zero3x3();
|
|
|
|
for (var i = 0; i < result.Rows; i++)
|
|
{
|
|
for (var j = 0; j < result.Cols; j++)
|
|
{
|
|
result[i, j] = a[i, j] + b[i, j];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static Matrix operator -(Matrix a, Matrix b)
|
|
{
|
|
if (a.Cols != b.Cols)
|
|
{
|
|
throw new ArgumentException("Both sides must have same size");
|
|
}
|
|
|
|
var result = b.Cols == 1 ? Zero3x1() : Zero3x3();
|
|
|
|
for (var i = 0; i < result.Rows; i++)
|
|
{
|
|
for (var j = 0; j < result.Cols; j++)
|
|
{
|
|
result[i, j] = a[i, j] - b[i, j];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public Matrix Inverse()
|
|
{
|
|
if (Cols != 3)
|
|
{
|
|
throw new ArgumentException("Matrix must be 3x3");
|
|
}
|
|
|
|
var a = this[0, 0];
|
|
var b = this[0, 1];
|
|
var c = this[0, 2];
|
|
var d = this[1, 0];
|
|
var e = this[1, 1];
|
|
var f = this[1, 2];
|
|
var g = this[2, 0];
|
|
var h = this[2, 1];
|
|
var i = this[2, 2];
|
|
|
|
var denom = a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
|
|
return 1 / denom * FromValues(new[,]
|
|
{
|
|
{ e * i - f * h, -b * i + c * h, b * f - c * e },
|
|
{ -d * i + f * g, a * i - c * g, -a * f + c * d },
|
|
{ d * h - e * g, -a * h + b * g, a * e - b * d }
|
|
});
|
|
}
|
|
|
|
public Matrix Map(Func<double, double> func)
|
|
{
|
|
var result = Cols == 1 ? Zero3x1() : Zero3x3();
|
|
for (var i = 0; i < result.Rows; i++)
|
|
{
|
|
for (var j = 0; j < result.Cols; j++)
|
|
{
|
|
result[i, j] = func(this[i, j]);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
} |