Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Converting an Image to grayscale without using unsafe code

2.60/5 (3 votes)
17 Apr 2013CPOL 19.5K  
Convert an Image to grayscale without using unsafe code

C# Example(revised) 

Here we will build a class that will Enumerate the non inheritable class System.Drawing.Imaging.ColorMatrix. 

C#
using System;
using System.Linq;
using System.Collections;
using System.Drawing.Imaging;
using System.Collections.Generic;

namespace Chico
{
    public sealed class ColorMatrixEnumerator : IEnumerable, IEnumerable<float[]>
    {
        private ColorMatrix colorMatrix;
        public ColorMatrixEnumerator(ColorMatrix colorMatrix)
        {
            if (colorMatrix != null)
            {
                this.colorMatrix = colorMatrix;
            }
        }
        public int Count
        {
            get
            {
                if (this.colorMatrix != null)
                {
                    return 5;
                }
                return 0;
            }
        }
        public IEnumerator GetEnumerator()
        {
            if (this.colorMatrix == null)
            {
                return null;
            }
            float[][] array = new float[this.Count][];
            for (int i = 0; i < this.Count; i++)
            {
                array[i] = new float[this.Count];
                for (int j = 0; j < this.Count; j++)
                {
                    array[i][j] = this.colorMatrix[i, j];
                }
            }
            return array.GetEnumerator();
        }
        IEnumerator<float[]> IEnumerable<float[]>.GetEnumerator()
        {
            if (this.colorMatrix == null)
            {
                return null;
            }
            return this.OfType<float[]>().GetEnumerator();
        }
    }
}  

Now we have an Enumerator for our matrix class that we can use in place of GetEnumerator. Now lets have  a look at our inheritable matrix class.


C#
using System;
using System.Linq;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Imaging;

namespace Chico
{    
    
    [TypeConverter(typeof(ExpandableObjectConverter))]
    /// <summary>
    /// An Attempt to implement an inheritable <see cref="T:System.Drawing.Imaging.ColorMatrix" /> with <see cref="T:System.ComponentModel.DesignerSerializationVisibility" /> support.
    /// </summary>
    public class Matrix : ICloneable
    {

        
        protected float matrix00;
        protected float matrix01;
        protected float matrix02;
        protected float matrix03;
        protected float matrix04;
        protected float matrix10;
        protected float matrix11;
        protected float matrix12;
        protected float matrix13;
        protected float matrix14;
        protected float matrix20;
        protected float matrix21;
        protected float matrix22;
        protected float matrix23;
        protected float matrix24;
        protected float matrix30;
        protected float matrix31;
        protected float matrix32;
        protected float matrix33;
        protected float matrix34;
        protected float matrix40;
        protected float matrix41;
        protected float matrix42;
        private float matrix43;
        private float matrix44;        
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the 0 (zero) row and 0 column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the 0 row and 0 column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix00
        {
            get
            {
                return this.matrix00;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix00 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the 0 (zero) row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the 0 row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" /> .</returns>
        public float Matrix01
        {
            get
            {
                return this.matrix01;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix01 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the 0 (zero) row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the 0 row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix02
        {
            get
            {
                return this.matrix02;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix02 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the 0 (zero) row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />. Represents the alpha component.</summary>
        /// <returns>The element at the 0 row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix03
        {
            get
            {
                return this.matrix03;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix03 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the 0 (zero) row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the 0 row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix04
        {
            get
            {
                return this.matrix04;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix04 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the first row and 0 (zero) column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the first row and 0 column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix10
        {
            get
            {
                return this.matrix10;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix10 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the first row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the first row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix11
        {
            get
            {
                return this.matrix11;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix11 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the first row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the first row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix12
        {
            get
            {
                return this.matrix12;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix12 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the first row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />. Represents the alpha component.</summary>
        /// <returns>The element at the first row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix13
        {
            get
            {
                return this.matrix13;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix13 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the first row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the first row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix14
        {
            get
            {
                return this.matrix14;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix14 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the second row and 0 (zero) column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the second row and 0 column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix20
        {
            get
            {
                return this.matrix20;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix20 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the second row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the second row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix21
        {
            get
            {
                return this.matrix21;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix21 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the second row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the second row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix22
        {
            get
            {
                return this.matrix22;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix22 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the second row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the second row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix23
        {
            get
            {
                return this.matrix23;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix23 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the second row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the second row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix24
        {
            get
            {
                return this.matrix24;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix24 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the third row and 0 (zero) column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the third row and 0 column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix30
        {
            get
            {
                return this.matrix30;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix30 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the third row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the third row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix31
        {
            get
            {
                return this.matrix31;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix31 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the third row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the third row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix32
        {
            get
            {
                return this.matrix32;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix32 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the third row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />. Represents the alpha component.</summary>
        /// <returns>The element at the third row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix33
        {
            get
            {
                return this.matrix33;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix33 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the third row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the third row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix34
        {
            get
            {
                return this.matrix34;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix34 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the fourth row and 0 (zero) column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the fourth row and 0 column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix40
        {
            get
            {
                return this.matrix40;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix40 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the fourth row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the fourth row and first column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix41
        {
            get
            {
                return this.matrix41;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix41 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the fourth row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the fourth row and second column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix42
        {
            get
            {
                return this.matrix42;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix42 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the fourth row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />. Represents the alpha component.</summary>
        /// <returns>The element at the fourth row and third column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix43
        {
            get
            {
                return this.matrix43;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix43 = value;
            }
        }
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        /// <summary>Gets or sets the element at the fourth row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</summary>
        /// <returns>The element at the fourth row and fourth column of this <see cref="T:System.Drawing.Imaging.ColorMatrix" />.</returns>
        public float Matrix44
        {
            get
            {
                return this.matrix44;
            }
            set
            {
                if (this is GrayScaleMatrix)
                {
                    return;
                }
                this.matrix44 = value;
            }
        }
        public Matrix()
        {
            this.matrix00 = 1f;
            this.matrix11 = 1f;
            this.matrix22 = 1f;
            this.matrix33 = 1f;
            this.matrix44 = 1f;            
        }
        public Matrix SetMatrix(Matrix newMatrix)
        {
            if (this is GrayScaleMatrix)
            {
                return this;
            }
            this.SetMatrix(Matrix.Insure(newMatrix).GetMatrix());
            return this;
        }        
        public void ConvertToGrayscaleMatrix()
        {
            if (new GrayScaleMatrix().Equals(this))
            {
                return;
            }
            this.SetMatrix(new GrayScaleMatrix());
        }
        protected Matrix(float[][] newMatrix)
        {            
            this.SetMatrix(newMatrix);
        }
        internal void SetMatrix(float[][] newMatrix)
        {
            try
            {
                this.matrix00 = newMatrix[0][0];
                this.matrix01 = newMatrix[0][1];
                this.matrix02 = newMatrix[0][2];
                this.matrix03 = newMatrix[0][3];
                this.matrix04 = newMatrix[0][4];
                this.matrix10 = newMatrix[1][0];
                this.matrix11 = newMatrix[1][1];
                this.matrix12 = newMatrix[1][2];
                this.matrix13 = newMatrix[1][3];
                this.matrix14 = newMatrix[1][4];
                this.matrix20 = newMatrix[2][0];
                this.matrix21 = newMatrix[2][1];
                this.matrix22 = newMatrix[2][2];
                this.matrix23 = newMatrix[2][3];
                this.matrix24 = newMatrix[2][4];
                this.matrix30 = newMatrix[3][0];
                this.matrix31 = newMatrix[3][1];
                this.matrix32 = newMatrix[3][2];
                this.matrix33 = newMatrix[3][3];
                this.matrix34 = newMatrix[3][4];
                this.matrix40 = newMatrix[4][0];
                this.matrix41 = newMatrix[4][1];
                this.matrix42 = newMatrix[4][2];
                this.matrix43 = newMatrix[4][3];
                this.matrix44 = newMatrix[4][4];
            }
            catch
            {
                this.SetMatrix(default(Matrix));
            }
        }
        internal float[][] GetMatrix()
        {
            float[][] array = new float[5][];
            for (int i = 0; i < 5; i++)
            {
                array[i] = new float[5];
            }
            array[0][0] = this.matrix00;
            array[0][1] = this.matrix01;
            array[0][2] = this.matrix02;
            array[0][3] = this.matrix03;
            array[0][4] = this.matrix04;
            array[1][0] = this.matrix10;
            array[1][1] = this.matrix11;
            array[1][2] = this.matrix12;
            array[1][3] = this.matrix13;
            array[1][4] = this.matrix14;
            array[2][0] = this.matrix20;
            array[2][1] = this.matrix21;
            array[2][2] = this.matrix22;
            array[2][3] = this.matrix23;
            array[2][4] = this.matrix24;
            array[3][0] = this.matrix30;
            array[3][1] = this.matrix31;
            array[3][2] = this.matrix32;
            array[3][3] = this.matrix33;
            array[3][4] = this.matrix34;
            array[4][0] = this.matrix40;
            array[4][1] = this.matrix41;
            array[4][2] = this.matrix42;
            array[4][3] = this.matrix43;
            array[4][4] = this.matrix44;
            return array;
        }
        public static Matrix Insure(Matrix matrix)
        {
            if (matrix == null)
            {
                matrix = new Matrix();
            }
            return matrix;
        }
        public static Matrix CreateFromColorMatrix(ColorMatrix colorMatrix)
        {
            if (colorMatrix == null)
            {
                colorMatrix = new ColorMatrix();
            }        
            return Matrix.Insure(new Matrix(new ColorMatrixEnumerator(colorMatrix).ToArray()));
        }
        protected ImageAttributes Attributes
        {
            get
            {
                ImageAttributes attributes = new ImageAttributes();
                attributes.SetColorMatrix(this);
                return attributes;
            }
        }
        public void DrawImageWithMatrix(Image image)
        {
            if (image == null)
                return;
            Graphics g = Graphics.FromImage(image);
            g.DrawImage(image, new Rectangle(0,0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, this.Attributes);
            g.Dispose();
        }
        public static implicit operator ColorMatrix(Matrix matrix)
        {
            return (ColorMatrix)Matrix.Insure(matrix).Clone();
        }
        public static implicit operator Matrix(ColorMatrix matrix)
        {
            return Matrix.Insure(Matrix.CreateFromColorMatrix(matrix));
        }
        public ColorMatrixEnumerator MatrixEnumerator
        {
            get
            {
                return new ColorMatrixEnumerator(this);
            }
        }
        public object Clone()
        {
            return new ColorMatrix(this.GetMatrix());
        }
    }
}

 now that we have our inheritable Matrix class built we will take it a step further and implement our grayscale matrix derived from matrix. 

C#
using System;
using System.Drawing.Imaging;

namespace Chico
{
    public sealed class GrayScaleMatrix : Matrix
    {
        private const float grayscaleA = .3f;
        private const float grayscaleB = .59f;
        private const float grayscaleC = .11f;
        private const float Matrix1 = 1;
        private const float Matrix0 = 0;
        private static bool IsGrayscale(Matrix matrix)
        {
            if (matrix != null)
            {
                if (matrix is GrayScaleMatrix)
                {
                    return true;
                }
                else
                {
                    ColorMatrix matrix2 = matrix;
                    bool isMatrix0 = matrix2[0, 0] == grayscaleA && matrix2[0, 1] == grayscaleA && matrix2[0, 2] == grayscaleA && matrix2[0,3] == Matrix0 && matrix2[0,4] == Matrix0;
                    bool isMatrix1 = matrix2[1, 0] == grayscaleB && matrix2[1, 1] == grayscaleB && matrix2[1, 2] == grayscaleB && matrix2[1, 3] == Matrix0 && matrix2[1, 4] == Matrix0;
                    bool isMatrix2 = matrix2[2, 0] == grayscaleC && matrix2[2, 1] == grayscaleC && matrix2[2, 2] == grayscaleC && matrix2[2, 3] == Matrix0 && matrix2[2, 4] == Matrix0;
                    bool isMatrix3 = matrix2[3, 0] == Matrix0 && matrix2[3, 1] == Matrix0 && matrix2[3, 2] == Matrix0 && matrix2[3, 3] == Matrix1 && matrix2[3, 4] == Matrix0;
                    bool isMatrix4 = matrix2[4, 0] == Matrix0 && matrix2[4, 1] == Matrix0 && matrix2[4, 2] == Matrix0 && matrix2[4, 3] == Matrix0 && matrix2[4, 4] == Matrix1;
                    return isMatrix0 && isMatrix1 && isMatrix2 && isMatrix3 && isMatrix4;
                }
            }
            else
            {
                return false;
            }
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            return obj is Matrix && GrayScaleMatrix.IsGrayscale((Matrix)obj);
        } 
        public GrayScaleMatrix() : base()
        { 
            matrix00 = grayscaleA;
            matrix01 = grayscaleA;
            matrix02 = grayscaleA;
            matrix10 = grayscaleB;
            matrix11 = grayscaleB;
            matrix12 = grayscaleB;
            matrix20 = grayscaleC;
            matrix21 = grayscaleC;
            matrix22 = grayscaleC;            
        }        
    }
} 

VB Example(revised) 

Here we will build a class that will Enumerate the non inheritable class System.Drawing.Imaging.ColorMatrix. 

VB.NET
Imports System
Imports System.Linq
Imports System.Collections
Imports System.Drawing.Imaging
Imports System.Collections.Generic

Namespace Chico
	Public NotInheritable Class ColorMatrixEnumerator
		Implements IEnumerable, IEnumerable(Of Single())
		Private colorMatrix As ColorMatrix
		Public Sub New(ByVal colorMatrix As ColorMatrix)
			If colorMatrix IsNot Nothing Then
				Me.colorMatrix = colorMatrix
			End If
		End Sub
		Public ReadOnly Property Count() As Integer
			Get
				If Me.colorMatrix IsNot Nothing Then
					Return 5
				End If
				Return 0
			End Get
		End Property
		Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
			If Me.colorMatrix Is Nothing Then
				Return Nothing
			End If
			Dim array(Me.Count - 1)() As Single
			For i As Integer = 0 To Me.Count - 1
				array(i) = New Single(Me.Count - 1){}
				For j As Integer = 0 To Me.Count - 1
					array(i)(j) = Me.colorMatrix(i, j)
				Next j
			Next i
			Return array.GetEnumerator()
		End Function
		Private Function IEnumerable_GetEnumerator() As IEnumerator(Of Single()) Implements IEnumerable(Of Single()).GetEnumerator
			If Me.colorMatrix Is Nothing Then
				Return Nothing
			End If
			Return Me.OfType(Of Single())().GetEnumerator()
		End Function
	End Class
End Namespace    

 Now we have an Enumerator for our matrix class that we can use in place of GetEnumerator. Now lets have  a look at our inheritable matrix class. 

VB.NET
Imports System
Imports System.Linq
Imports System.Drawing
Imports System.ComponentModel
Imports System.Drawing.Imaging

Namespace Chico
	''' <summary>
	''' An Attempt to implement an inheritable <see cref="T:System.Drawing.Imaging.ColorMatrix" /> with <see cref="T:System.ComponentModel.DesignerSerializationVisibility" /> support.
	''' </summary>
	<TypeConverter(GetType(ExpandableObjectConverter))>
	Public Class Matrix
		Implements ICloneable

		Protected m_matrix00, m_matrix01, m_matrix02, m_matrix03, m_matrix04, m_matrix10, m_matrix11, m_matrix12, m_matrix13, m_matrix14, m_matrix20, m_matrix21, m_matrix22, m_matrix23, m_matrix24, m_matrix30, m_matrix31, m_matrix32, m_matrix33, m_matrix34, m_matrix40, m_matrix41, m_matrix42, m_matrix43, m_matrix44 As Single
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix00() As Single
			Get
				Return Me.m_matrix00
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix00 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix01() As Single
			Get
				Return Me.m_matrix01
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix01 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix02() As Single
			Get
				Return Me.m_matrix02
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix02 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix03() As Single
			Get
				Return Me.m_matrix03
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix03 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix04() As Single
			Get
				Return Me.m_matrix04
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix04 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix10() As Single
			Get
				Return Me.m_matrix10
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix10 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix11() As Single
			Get
				Return Me.m_matrix11
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix11 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix12() As Single
			Get
				Return Me.m_matrix12
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix12 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix13() As Single
			Get
				Return Me.m_matrix13
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix13 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix14() As Single
			Get
				Return Me.m_matrix14
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix14 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix20() As Single
			Get
				Return Me.m_matrix20
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix20 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix21() As Single
			Get
				Return Me.m_matrix21
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix21 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix22() As Single
			Get
				Return Me.m_matrix22
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix22 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix23() As Single
			Get
				Return Me.m_matrix23
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix23 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix24() As Single
			Get
				Return Me.m_matrix24
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix24 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix30() As Single
			Get
				Return Me.m_matrix30
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix30 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix31() As Single
			Get
				Return Me.m_matrix31
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix31 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix32() As Single
			Get
				Return Me.m_matrix32
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix32 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix33() As Single
			Get
				Return Me.m_matrix33
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix33 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix34() As Single
			Get
				Return Me.m_matrix34
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix34 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix40() As Single
			Get
				Return Me.m_matrix40
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix40 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix41() As Single
			Get
				Return Me.m_matrix41
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix41 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix42() As Single
			Get
				Return Me.m_matrix42
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix42 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix43() As Single
			Get
				Return Me.m_matrix43
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix43 = value
			End Set
		End Property
		<DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)>
		Public Property Matrix44() As Single
			Get
				Return Me.m_matrix44
			End Get
			Set(ByVal value As Single)
				If TypeOf Me Is GrayScaleMatrix Then
					Return
				End If
				Me.m_matrix44 = value
			End Set
		End Property

		Public Sub New()
			Me.m_matrix00 = 1f
			Me.m_matrix11 = 1f
			Me.m_matrix22 = 1f
			Me.m_matrix33 = 1f
			Me.m_matrix44 = 1f
		End Sub
		Public Function SetMatrix(ByVal newMatrix As Matrix) As Matrix
			If TypeOf Me Is GrayScaleMatrix Then
				Return Me
			End If
			Me.SetMatrix(Matrix.Insure(newMatrix).GetMatrix())
			Return Me
		End Function
		Public Sub ConvertToGrayscaleMatrix()
			If New GrayScaleMatrix().Equals(Me) Then
				Return
			End If
			Me.SetMatrix(New GrayScaleMatrix())
		End Sub
		Protected Sub New(ByVal newMatrix()() As Single)
			Me.SetMatrix(newMatrix)
		End Sub
		Friend Sub SetMatrix(ByVal newMatrix()() As Single)
			Try
				Me.m_matrix00 = newMatrix(0)(0)
				Me.m_matrix01 = newMatrix(0)(1)
				Me.m_matrix02 = newMatrix(0)(2)
				Me.m_matrix03 = newMatrix(0)(3)
				Me.m_matrix04 = newMatrix(0)(4)
				Me.m_matrix10 = newMatrix(1)(0)
				Me.m_matrix11 = newMatrix(1)(1)
				Me.m_matrix12 = newMatrix(1)(2)
				Me.m_matrix13 = newMatrix(1)(3)
				Me.m_matrix14 = newMatrix(1)(4)
				Me.m_matrix20 = newMatrix(2)(0)
				Me.m_matrix21 = newMatrix(2)(1)
				Me.m_matrix22 = newMatrix(2)(2)
				Me.m_matrix23 = newMatrix(2)(3)
				Me.m_matrix24 = newMatrix(2)(4)
				Me.m_matrix30 = newMatrix(3)(0)
				Me.m_matrix31 = newMatrix(3)(1)
				Me.m_matrix32 = newMatrix(3)(2)
				Me.m_matrix33 = newMatrix(3)(3)
				Me.m_matrix34 = newMatrix(3)(4)
				Me.m_matrix40 = newMatrix(4)(0)
				Me.m_matrix41 = newMatrix(4)(1)
				Me.m_matrix42 = newMatrix(4)(2)
				Me.m_matrix43 = newMatrix(4)(3)
				Me.m_matrix44 = newMatrix(4)(4)
			Catch
				Me.SetMatrix(Nothing)
			End Try
		End Sub
		Friend Function GetMatrix() As Single()()
			Dim array(4)() As Single
			For i As Integer = 0 To 4
				array(i) = New Single(4){}
			Next i
			array(0)(0) = Me.m_matrix00
			array(0)(1) = Me.m_matrix01
			array(0)(2) = Me.m_matrix02
			array(0)(3) = Me.m_matrix03
			array(0)(4) = Me.m_matrix04
			array(1)(0) = Me.m_matrix10
			array(1)(1) = Me.m_matrix11
			array(1)(2) = Me.m_matrix12
			array(1)(3) = Me.m_matrix13
			array(1)(4) = Me.m_matrix14
			array(2)(0) = Me.m_matrix20
			array(2)(1) = Me.m_matrix21
			array(2)(2) = Me.m_matrix22
			array(2)(3) = Me.m_matrix23
			array(2)(4) = Me.m_matrix24
			array(3)(0) = Me.m_matrix30
			array(3)(1) = Me.m_matrix31
			array(3)(2) = Me.m_matrix32
			array(3)(3) = Me.m_matrix33
			array(3)(4) = Me.m_matrix34
			array(4)(0) = Me.m_matrix40
			array(4)(2) = Me.m_matrix42
			array(4)(3) = Me.m_matrix42
			array(4)(4) = Me.m_matrix44
			Return array
		End Function
		Public Shared Function Insure(ByVal m_matrix As Matrix) As Matrix
			If m_matrix Is Nothing Then
				m_matrix = New Matrix()
			End If
			Return m_matrix
		End Function
		Public Shared Function CreateFromColorMatrix(ByVal colorMatrix As ColorMatrix) As Matrix
			If colorMatrix Is Nothing Then
				colorMatrix = New ColorMatrix()
			End If
			Return Matrix.Insure(New Matrix(New ColorMatrixEnumerator(colorMatrix).ToArray()))
		End Function
		Protected ReadOnly Property Attributes() As ImageAttributes
			Get
				Dim attributes As New ImageAttributes()
				attributes.SetColorMatrix(Me)
				Return attributes
			End Get
		End Property
		Public Sub DrawImageWithMatrix(ByVal image As Image)
			If image Is Nothing Then
				Return
			End If
				Dim g As Graphics = Graphics.FromImage(image)
				g.DrawImage(image, New Rectangle(0,0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, Me.Attributes)
				g.Dispose()
		End Sub
		Public Shared Widening Operator CType(ByVal m_matrix As Matrix) As ColorMatrix
			Return CType(Matrix.Insure(m_matrix).Clone(), ColorMatrix)
		End Operator
		Public Shared Widening Operator CType(ByVal m_matrix As ColorMatrix) As Matrix
			Return Matrix.Insure(Matrix.CreateFromColorMatrix(m_matrix))
		End Operator
		Public ReadOnly Property MatrixEnumerator() As ColorMatrixEnumerator
			Get
				Return New ColorMatrixEnumerator(Me)
			End Get
		End Property
		Public Function Clone() As Object Implements ICloneable.Clone
			Return New ColorMatrix(Me.GetMatrix())
		End Function
	End Class
End Namespace 

now that we have our inheritable Matrix class built we will take it a step further and implement our grayscale matrix derived from matrix.        

VB.NET
Imports System
Imports System.Drawing.Imaging

Namespace Chico
	Public NotInheritable Class GrayScaleMatrix
		Inherits Matrix
		Private Const grayscaleA As Single =.3f
		Private Const grayscaleB As Single =.59f
		Private Const grayscaleC As Single =.11f
		Private Const Matrix1 As Single = 1
		Private Const Matrix0 As Single = 0
		Private Shared Function IsGrayscale(ByVal matrix As Matrix) As Boolean
			If matrix IsNot Nothing Then
				If TypeOf matrix Is GrayScaleMatrix Then
					Return True
				Else
					Dim matrix2 As ColorMatrix = matrix
					Dim isMatrix0 As Boolean = matrix2(0, 0) = grayscaleA AndAlso matrix2(0, 1) = grayscaleA AndAlso matrix2(0, 2) = grayscaleA AndAlso matrix2(0,3) = Matrix0 AndAlso matrix2(0,4) = Matrix0
					Dim isMatrix1 As Boolean = matrix2(1, 0) = grayscaleB AndAlso matrix2(1, 1) = grayscaleB AndAlso matrix2(1, 2) = grayscaleB AndAlso matrix2(1, 3) = Matrix0 AndAlso matrix2(1, 4) = Matrix0
					Dim isMatrix2 As Boolean = matrix2(2, 0) = grayscaleC AndAlso matrix2(2, 1) = grayscaleC AndAlso matrix2(2, 2) = grayscaleC AndAlso matrix2(2, 3) = Matrix0 AndAlso matrix2(2, 4) = Matrix0
					Dim isMatrix3 As Boolean = matrix2(3, 0) = Matrix0 AndAlso matrix2(3, 1) = Matrix0 AndAlso matrix2(3, 2) = Matrix0 AndAlso matrix2(3, 3) = Matrix1 AndAlso matrix2(3, 4) = Matrix0
					Dim isMatrix4 As Boolean = matrix2(4, 0) = Matrix0 AndAlso matrix2(4, 1) = Matrix0 AndAlso matrix2(4, 2) = Matrix0 AndAlso matrix2(4, 3) = Matrix0 AndAlso matrix2(4, 4) = Matrix1
					Return isMatrix0 AndAlso isMatrix1 AndAlso isMatrix2 AndAlso isMatrix3 AndAlso isMatrix4
				End If
			Else
				Return False
			End If
		End Function
		Public Overrides Function GetHashCode() As Integer
			Return MyBase.GetHashCode()
		End Function
		Public Overrides Overloads Function Equals(ByVal obj As Object) As Boolean
			Return TypeOf obj Is Matrix AndAlso GrayScaleMatrix.IsGrayscale(CType(obj, Matrix))
		End Function
		Public Sub New()
			MyBase.New()
			m_matrix00 = grayscaleA
			m_matrix01 = grayscaleA
			m_matrix02 = grayscaleA
			m_matrix10 = grayscaleB
			m_matrix11 = grayscaleB
			m_matrix12 = grayscaleB
			m_matrix20 = grayscaleC
			m_matrix21 = grayscaleC
			m_matrix22 = grayscaleC
		End Sub
	End Class
End Namespace 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)