/// <summary> /// Copy constructor /// </summary> /// <param name="other"></param> public XColorMatrix(XColorMatrix other) { // copy from other for (int r = 0; r < 5; r++) for (int c = 0; c < 5; c++) this.cm[r, c] = other.ColorMatrix[r, c]; }
/// <summary> /// Shear a color /// </summary> /// <param name="x"></param> /// <param name="y1"></param> /// <param name="d1"></param> /// <param name="y2"></param> /// <param name="d2"></param> /// <param name="order"></param> public void ShearColor(int x, int y1, float d1, int y2, float d2, MatrixOrder order) { XColorMatrix m = new XColorMatrix(); m.cm[y1, x] = d1; m.cm[y2, x] = d2; Multiply(m, order); }
/// <summary> /// Copy constructor /// </summary> /// <param name="other"></param> public XColorMatrix(XColorMatrix other) { // copy from other for (int r = 0; r < 5; r++) { for (int c = 0; c < 5; c++) { this.cm[r, c] = other.ColorMatrix[r, c]; } } }
/// <summary> /// Multiply given matrix by this using specified matrix order /// </summary> /// <param name="matrix"></param> /// <param name="order"></param> public void Multiply(XColorMatrix other, MatrixOrder order) { // if matrix order == Append then its other * this // otherwise its this * other float[,] temp = new float[5, 5]; if (order == MatrixOrder.Prepend) { for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { float t = 0; for (int i = 0; i < 5; i++) { t += other.ColorMatrix[y, i] * this.ColorMatrix[i, x]; } temp[y, x] = t; } } } else { for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { float t = 0; for (int i = 0; i < 5; i++) { t += this.ColorMatrix[y, i] * other.ColorMatrix[i, x]; } temp[y, x] = t; } } } for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { this.cm[y, x] = temp[y, x]; } } }
/// <summary> /// Rotate the hue of the colors /// </summary> /// <param name="phi"></param> public void RotateHue(float phi) { // ensure we are initialized for hue rotations XColorMatrix.InitHue(); // Rotate the grey vector to the blue axis. Multiply(XColorMatrix.preHue, MatrixOrder.Append); // Rotate around the blue axis RotateBlue(phi, MatrixOrder.Append); // compose with this Multiply(XColorMatrix.postHue, MatrixOrder.Append); }
/// <summary> /// Rotate the color by specifying the indices in the matrix to recieve the rotation value /// phi is the angle -180 -> +180 /// </summary> /// <param name="phi"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="order"></param> public void RotateColor(float phi, int x, int y, MatrixOrder order) { // convert degrees to radians phi *= (float)Math.PI / 180.0f; // get matrix to multiply by XColorMatrix m = new XColorMatrix(); m.cm[x, x] = m.cm[y, y] = (float)Math.Cos(phi); float s = (float)Math.Sin(phi); m.cm[y, x] = s; m.cm[x, y] = -s; Multiply(m, order); }
/// <summary> /// Set the saturation levels of ColorMatrix. 0..3.0f are useful values with 1.0f being identity /// </summary> /// <param name="saturation"></param> /// <param name="order"></param> public void SetSaturation(float saturation, MatrixOrder order) { // For the theory behind this, see the web sites at the top of this file. // In short: if saturation is 1.0f, m becomes the identity matrix, and this matrix is // unchanged. If saturation is 0.0f, each color is scaled by it's luminance weight. float satCompl = 1.0f - saturation; float satComplR = kLUMR * satCompl; float satComplG = kLUMG * satCompl; float satComplB = kLUMB * satCompl; XColorMatrix m = new XColorMatrix(); m.cm[0, 0] = satComplR + saturation; m.cm[0, 1] = satComplR; m.cm[0, 2] = satComplR; m.cm[0, 3] = 0; m.cm[0, 4] = 0; m.cm[1, 0] = satComplG; m.cm[1, 1] = satComplG + saturation; m.cm[1, 2] = satComplG; m.cm[1, 3] = 0; m.cm[1, 4] = 0; m.cm[2, 0] = satComplB; m.cm[2, 1] = satComplB; m.cm[2, 2] = satComplB + saturation; m.cm[2, 3] = 0; m.cm[2, 4] = 0; m.cm[3, 0] = 0; m.cm[3, 1] = 0; m.cm[3, 2] = 0; m.cm[3, 3] = 1; m.cm[3, 4] = 0; m.cm[4, 0] = 0; m.cm[4, 1] = 0; m.cm[4, 2] = 0; m.cm[4, 3] = 0; m.cm[4, 4] = 1; Multiply(m, order); }
/// <summary> /// Create a new YUV image from an RGB image ( alpha unchanged ) /// </summary> public static Image CreateYUVAfromRGBAImage(Image source) { // image to be returned Image newImage = null; // create image attributes to blit image into itself with. using (ImageAttributes ia = new ImageAttributes()) { // use color matrix for conversion XColorMatrix xcm = new XColorMatrix(); xcm.RGBtoYUV(); // associate matrix with attributes ia.SetColorMatrix(xcm.ColorMatrix); // create new image newImage = CreateImage(source.Width, source.Height, source.PixelFormat); // get a graphics for target image using (Graphics g = Graphics.FromImage(newImage)) { // set compositing mode to copy over g.CompositingMode = CompositingMode.SourceCopy; // turn off aliasing etc g.InterpolationMode = InterpolationMode.NearestNeighbor; g.SmoothingMode = SmoothingMode.None; // create destination rectangle Rectangle d = new Rectangle(0, 0, source.Width, source.Height); // paint into self g.DrawImage(source, d, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, ia); } } // return YUV(A) return newImage; }
/// <summary> /// Multiply given matrix by this using specified matrix order /// </summary> /// <param name="matrix"></param> /// <param name="order"></param> public void Multiply(XColorMatrix other, MatrixOrder order) { // if matrix order == Append then its other * this // otherwise its this * other float[,] temp = new float[5, 5]; if (order == MatrixOrder.Prepend) { for (int y = 0; y < 5; y++) for (int x = 0; x < 5; x++) { float t = 0; for (int i = 0; i < 5; i++) t += other.ColorMatrix[y, i] * this.ColorMatrix[i, x]; temp[y, x] = t; } } else { for (int y = 0; y < 5; y++) for (int x = 0; x < 5; x++) { float t = 0; for (int i = 0; i < 5; i++) t += this.ColorMatrix[y, i] * other.ColorMatrix[i, x]; temp[y, x] = t; } } for (int y = 0; y < 5; y++) for (int x = 0; x < 5; x++) this.cm[y, x] = temp[y, x]; }