19 using System.Threading.Tasks;
31 public double R1 {
get;
set; }
36 public double R2 {
get;
set; }
41 public double R3 {
get;
set; }
46 public double R4 {
get;
set; }
51 public double R5 {
get;
set; }
56 public double G1 {
get;
set; }
61 public double G2 {
get;
set; }
66 public double G3 {
get;
set; }
71 public double G4 {
get;
set; }
76 public double G5 {
get;
set; }
81 public double B1 {
get;
set; }
86 public double B2 {
get;
set; }
91 public double B3 {
get;
set; }
96 public double B4 {
get;
set; }
101 public double B5 {
get;
set; }
106 public double A1 {
get;
set; }
111 public double A2 {
get;
set; }
116 public double A3 {
get;
set; }
121 public double A4 {
get;
set; }
126 public double A5 {
get;
set; }
135 public double this[
int y,
int x]
155 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
172 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
189 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
206 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
223 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
227 throw new ArgumentOutOfRangeException(nameof(y), y,
"Coordinate out of range!");
254 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
277 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
300 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
323 throw new ArgumentOutOfRangeException(nameof(x), x,
"Coordinate out of range!");
328 throw new ArgumentOutOfRangeException(nameof(y), y,
"Coordinate out of range!");
336 public static ColourMatrix Identity =
new ColourMatrix(
new double[,] { { 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0 }, { 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
341 public static ColourMatrix GreyScale =
new ColourMatrix(
new double[,] { { 0.2126, 0.7152, 0.0722, 0, 0 }, { 0.2126, 0.7152, 0.0722, 0, 0 }, { 0.2126, 0.7152, 0.0722, 0, 0 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
346 public static ColourMatrix Pastel =
new ColourMatrix(
new double[,] { { 0.75, 0.25, 0.25, 0, 0 }, { 0.25, 0.75, 0.25, 0, 0 }, { 0.25, 0.25, 0.75, 0, 0 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
351 public static ColourMatrix Inversion =
new ColourMatrix(
new double[,] { { -1, 0, 0, 0, 1 }, { 0, -1, 0, 0, 1 }, { 0, 0, -1, 0, 1 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
356 public static ColourMatrix AlphaInversion =
new ColourMatrix(
new double[,] { { 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0 }, { 0, 0, 1, 0, 0 }, { 0, 0, 0, -1, 1 }, { 0, 0, 0, 0, 1 } });
361 public static ColourMatrix InvertedAlphaShift =
new ColourMatrix(
new double[,] { { 1, 0, 0, -1, 1 }, { 0, 1, 0, -1, 1 }, { 0, 0, 1, -1, 1 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
373 return new ColourMatrix(
new double[,] { { 0, 0, 0, 0, colour.
R }, { 0, 0, 0, 0, colour.
G }, { 0, 0, 0, 0, colour.
B }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
377 return new ColourMatrix(
new double[,] { { 0, 0, 0, 0, colour.
R }, { 0, 0, 0, 0, colour.
G }, { 0, 0, 0, 0, colour.
B }, { 0, 0, 0, 0, colour.
A }, { 0, 0, 0, 0, 1 } });
391 return new ColourMatrix(
new double[,] { { 0.2126 * colour.
R, 0.7152 * colour.
R, 0.0722 * colour.
R, 0, 0 }, { 0.2126 * colour.
G, 0.7152 * colour.
G, 0.0722 * colour.
G, 0, 0 }, { 0.2126 * colour.
B, 0.7152 * colour.
B, 0.0722 * colour.
B, 0, 0 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1 } });
395 return new ColourMatrix(
new double[,] { { 0.2126 * colour.
R, 0.7152 * colour.
R, 0.0722 * colour.
R, 0, 0 }, { 0.2126 * colour.
G, 0.7152 * colour.
G, 0.0722 * colour.
G, 0, 0 }, { 0.2126 * colour.
B, 0.7152 * colour.
B, 0.0722 * colour.
B, 0, 0 }, { 0.2126 * colour.
A, 0.7152 * colour.
A, 0.0722 * colour.
A, 0, 0 }, { 0, 0, 0, 0, 1 } });
408 return new ColourMatrix(
new double[,] { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0.2126, 0.7152, 0.0722, 0, 0 }, { 0, 0, 0, 0, 1 } });
412 return new ColourMatrix(
new double[,] { { 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0 }, { 0, 0, 1, 0, 0 }, { 0.2126, 0.7152, 0.0722, 0, 0 }, { 0, 0, 0, 0, 1 } });
423 return new ColourMatrix(
new double[,] { {
R1,
R2,
R3,
R4,
R5 }, {
G1,
G2,
G3,
G4,
G5 }, {
B1,
B2,
B3,
B4,
B5 }, {
A1 * alpha,
A2 * alpha,
A3 * alpha,
A4 * alpha,
A5 * alpha }, { 0, 0, 0, 0, 1 } });
434 double[,] tbr =
new double[5, 5];
436 for (
int i = 0; i < 5; i++)
438 for (
int j = 0; j < 5; j++)
440 for (
int k = 0; k < 5; k++)
442 tbr[i, j] += matrix1[i, k] * matrix2[k, j];
456 for (
int i = 0; i < 4; i++)
458 for (
int j = 0; j < 5; j++)
460 this[i, j] = matrix[i, j];
472 double[] col =
new double[] { colour.
R, colour.
G, colour.
B, colour.
A, 1 };
474 double[] tbr =
new double[5];
476 for (
int i = 0; i < tbr.Length; i++)
478 for (
int j = 0; j < tbr.Length; j++)
480 tbr[i] +=
this[i, j] * col[j];
495 public void Apply(ref
byte R, ref
byte G, ref
byte B, ref
byte A)
497 byte r = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.R1 + G *
this.R2 + B *
this.R3 + A *
this.R4 +
this.R5 * 255)));
498 byte g = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.G1 + G *
this.G2 + B *
this.G3 + A *
this.G4 +
this.G5 * 255)));
499 byte b = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.B1 + G *
this.B2 + B *
this.B3 + A *
this.B4 +
this.B5 * 255)));
500 byte a = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.A1 + G *
this.A2 + B *
this.A3 + A *
this.A4 +
this.A5 * 255)));
515 public void Apply(ref
byte R, ref
byte G, ref
byte B)
517 byte r = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.R1 + G *
this.R2 + B *
this.R3 + 255 *
this.R4 +
this.R5 * 255)));
518 byte g = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.G1 + G *
this.G2 + B *
this.G3 + 255 *
this.G4 +
this.G5 * 255)));
519 byte b = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.B1 + G *
this.B2 + B *
this.B3 + 255 *
this.B4 +
this.B5 * 255)));
538 public void Apply(
byte R,
byte G,
byte B,
byte A, out
byte r, out
byte g, out
byte b, out
byte a)
540 r = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.R1 + G *
this.R2 + B *
this.R3 + A *
this.R4 +
this.R5 * 255)));
541 g = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.G1 + G *
this.G2 + B *
this.G3 + A *
this.G4 +
this.G5 * 255)));
542 b = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.B1 + G *
this.B2 + B *
this.B3 + A *
this.B4 +
this.B5 * 255)));
543 a = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.A1 + G *
this.A2 + B *
this.A3 + A *
this.A4 +
this.A5 * 255)));
556 public void Apply(
byte R,
byte G,
byte B, out
byte r, out
byte g, out
byte b)
558 r = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.R1 + G *
this.R2 + B *
this.R3 + 255 *
this.R4 +
this.R5 * 255)));
559 g = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.G1 + G *
this.G2 + B *
this.G3 + 255 *
this.G4 +
this.G5 * 255)));
560 b = (byte)Math.Min(255, Math.Max(0, Math.Round(R *
this.B1 + G *
this.B2 + B *
this.B3 + 255 *
this.B4 +
this.B5 * 255)));
592 IntPtr tbrData = System.Runtime.InteropServices.Marshal.AllocHGlobal(image.
Width * image.
Height * (image.
HasAlpha ? 4 : 3));
595 int width = image.
Width;
596 int height = image.
Height;
598 int pixelSize = image.
HasAlpha ? 4 : 3;
599 int stride = image.
Width * pixelSize;
601 int threads = Math.Min(8, Environment.ProcessorCount);
606 byte* output = (
byte*)tbrData;
614 for (
int x = 0; x < width; x++)
616 this.
ColourMatrix.
Apply(input[y * stride + x * 4], input[y * stride + x * 4 + 1], input[y * stride + x * 4 + 2], input[y * stride + x * 4 + 3], out output[y * stride + x * 4], out output[y * stride + x * 4 + 1], out output[y * stride + x * 4 + 2], out output[y * stride + x * 4 + 3]);
624 for (
int x = 0; x < width; x++)
626 this.
ColourMatrix.
Apply(input[y * stride + x * 4], input[y * stride + x * 4 + 1], input[y * stride + x * 4 + 2], out output[y * stride + x * 4], out output[y * stride + x * 4 + 1], out output[y * stride + x * 4 + 2]);
633 for (
int y = 0; y < height; y++)
640 ParallelOptions options =
new ParallelOptions() { MaxDegreeOfParallelism = threads };
642 Parallel.For(0, height, options, yLoop);