VintaSoft Imaging .NET SDK 10.0
In This Topic
    Custom processing command
    In This Topic

    The following steps must be made if the custom image processing command must be created:

    1. Create new class, which is inherited from ProcessingCommandBase or any other existing image processing command from Vintasoft.Imaging.ImageProcessing namespace
    2. Override the ProcessingCommandBase.ProcessImageInPlace method in your class
    3. Override the ProcessingCommandBase.SupportedPixelFormats property if your command does not support all pixel formats
    4. Call the ProcessingCommandBase.RaiseProgress method during execution of your command if your command supports progress


    Here is an example that shows how to create the image processing command that inverts image colors:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    
    ''' <summary>
    ''' Inverts colors of an image.
    ''' </summary>
    Public Class CustomInvertCommand
            Inherits Vintasoft.Imaging.ImageProcessing.ProcessingCommandWithRegion
    
            #Region "Constructors"
    
            ''' <summary>
            ''' Initializes a new instance of the  class.
            ''' </summary>
            Public Sub New()
                    MyBase.New()
            End Sub
    
            #End Region
    
    
    
            #Region "Properties"
    
            ''' <summary>
            ''' Gets the name of the command.
            ''' </summary>
            Public Overrides ReadOnly Property Name() As String
                    Get
                            Return "Invert"
                    End Get
            End Property
    
            ''' <summary>
            ''' Gets a list of supported native pixel formats for this processing command.
            ''' </summary>
            Public Overrides ReadOnly Property SupportedNativePixelFormats() As System.Collections.ObjectModel.ReadOnlyCollection(Of Vintasoft.Imaging.PixelFormat)
                    Get
                            Dim supportedNativePixelFormats__1 As New System.Collections.Generic.List(Of Vintasoft.Imaging.PixelFormat)()
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.BlackWhite)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Indexed1)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Indexed4)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Indexed8)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Gray8)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Gray16)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Bgr24)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Bgr32)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Bgr48)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Bgra32)
                            supportedNativePixelFormats__1.Add(Vintasoft.Imaging.PixelFormat.Bgra64)
                            Return supportedNativePixelFormats__1.AsReadOnly()
                    End Get
            End Property
    
            #End Region
    
    
    
            #Region "Methods"
    
            ''' <summary>
            ''' Returns the pixel format of output image (image after processing)
            ''' for input image with specified pixel format.
            ''' </summary>
            ''' <param name="inputPixelFormat">Pixel format of input image.</param>
            ''' <returns>Pixel format of output image.</returns>
            Public Overrides Function GetOutputPixelFormat(inputPixelFormat As Vintasoft.Imaging.PixelFormat) As Vintasoft.Imaging.PixelFormat
                    If IsPixelFormatSupported(inputPixelFormat) Then
                            Return inputPixelFormat
                    End If
                    Return Vintasoft.Imaging.PixelFormat.Undefined
            End Function
    
            ''' <summary>
            ''' Creates a new <see cref="CustomInvertCommand"/> that is a copy of the current
            ''' instance.
            ''' </summary>
            ''' <returns>A new <see cref="CustomInvertCommand"/> that is a copy of this
            ''' instance.</returns>
            Public Overrides Function Clone() As Object
                    Return New CustomInvertCommand()
            End Function
    
            ''' <summary>
            ''' Processes the image in-place.
            ''' </summary>
            ''' <param name="image">Image to process.</param>
            ''' <returns>
            ''' <b>true</b> if image is processed;
            ''' <b>false</b> if processing is canceled or not necessary.
            ''' </returns>
            ''' <remarks>
            ''' This method changes the <i>image</i>.
            ''' </remarks>
            Protected Overrides Function ProcessImageInPlace(image As Vintasoft.Imaging.VintasoftImage) As Boolean
                    Dim rect As System.Drawing.Rectangle = Me.GetSafeRegionOfInterest(image)
    
                    Dim cancel As Boolean = False
    
                    Dim height As Integer = rect.Height
    
                    Dim pixelManipulator As Vintasoft.Imaging.PixelManipulator
                    Dim rowData As Byte()
                    Dim rowLength As Integer
    
                    Dim progress As Single = 0
                    Dim progressDelta As Single = 100F / height
    
                    Select Case image.PixelFormat
                            Case Vintasoft.Imaging.PixelFormat.BlackWhite, Vintasoft.Imaging.PixelFormat.Indexed1, Vintasoft.Imaging.PixelFormat.Indexed4, Vintasoft.Imaging.PixelFormat.Indexed8, Vintasoft.Imaging.PixelFormat.Gray8
                                    If Not RegionOfInterest.IsEmpty Then
                                            Throw New Vintasoft.Imaging.ImageProcessing.ImageProcessingException(String.Format("{0}: this processing command does not support RegionOfInterest for palette images.", Name))
                                    End If
    
                                    image.Palette.Invert()
                                    Exit Select
    
                            Case Vintasoft.Imaging.PixelFormat.Gray16
                                    pixelManipulator = image.OpenPixelManipulator()
                                    pixelManipulator.LockPixels(rect, Vintasoft.Imaging.BitmapLockMode.ReadWrite)
                                    rowLength = rect.Width * 2
                                    rowData = New Byte(rowLength - 1) {}
                                    For y As Integer = 0 To height - 1
                                            pixelManipulator.ReadRowDataUnsafe(y, rowData, 0, rowLength)
                                            For x As Integer = 0 To rowLength - 1 Step 2
                                                    rowData(x) = rowData(x) Xor &Hff
                                                    rowData(x + 1) = rowData(x + 1) Xor &H3f
                                            Next
                                            pixelManipulator.WriteRowData(y, rowData, 0, rowLength)
    
                                            ' change the progress
                                            progress += progressDelta
                                            ' raise the progress event
                                            If Not RaiseProgress(progress, True) Then
                                                    cancel = True
                                                    Exit For
                                            End If
                                    Next
                                    pixelManipulator.UnlockPixels()
                                    ' close the pixel manipulator
                                    image.ClosePixelManipulator(True)
                                    Exit Select
    
                            Case Vintasoft.Imaging.PixelFormat.Bgr24, Vintasoft.Imaging.PixelFormat.Bgr48
                                    pixelManipulator = image.OpenPixelManipulator()
                                    pixelManipulator.LockPixels(rect, Vintasoft.Imaging.BitmapLockMode.ReadWrite)
                                    rowLength = rect.Width * 3
                                    rowData = New Byte(rowLength - 1) {}
                                    For y As Integer = 0 To height - 1
                                            pixelManipulator.ReadRowDataUnsafe(y, rowData, 0, rowLength)
                                            For x As Integer = 0 To rowLength - 1
                                                    rowData(x) = rowData(x) Xor &Hff
                                            Next
                                            pixelManipulator.WriteRowDataUnsafe(y, rowData, 0, rowLength)
    
                                            ' change the progress
                                            progress += progressDelta
                                            ' raise the progress event
                                            If Not RaiseProgress(progress, True) Then
                                                    cancel = True
                                                    Exit For
                                            End If
                                    Next
                                    pixelManipulator.UnlockPixels()
                                    ' close the pixel manipulator
                                    image.ClosePixelManipulator(True)
                                    Exit Select
    
                            Case Vintasoft.Imaging.PixelFormat.Bgr32, Vintasoft.Imaging.PixelFormat.Bgra32, Vintasoft.Imaging.PixelFormat.Bgra64
                                    pixelManipulator = image.OpenPixelManipulator()
                                    pixelManipulator.LockPixels(rect, Vintasoft.Imaging.BitmapLockMode.ReadWrite)
                                    rowLength = rect.Width * 4
                                    rowData = New Byte(rowLength - 1) {}
                                    For y As Integer = 0 To height - 1
                                            pixelManipulator.ReadRowDataUnsafe(y, rowData, 0, rowLength)
                                            For x As Integer = 0 To rowLength - 1 Step 4
                                                    rowData(x) = rowData(x) Xor &Hff
                                                    rowData(x + 1) = rowData(x + 1) Xor &Hff
                                                    rowData(x + 2) = rowData(x + 2) Xor &Hff
                                            Next
                                            pixelManipulator.WriteRowDataUnsafe(y, rowData, 0, rowLength)
    
                                            ' change the progress
                                            progress += progressDelta
                                            ' raise the progress event
                                            If Not RaiseProgress(progress, True) Then
                                                    cancel = True
                                                    Exit For
                                            End If
                                    Next
                                    pixelManipulator.UnlockPixels()
                                    ' close the pixel manipulator
                                    image.ClosePixelManipulator(True)
                                    Exit Select
                    End Select
    
                    Return Not cancel
            End Function
    
            #End Region
    
    End Class
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    
    /// <summary>
    /// Inverts colors of an image.
    /// </summary>
    public class CustomInvertCommand : Vintasoft.Imaging.ImageProcessing.ProcessingCommandWithRegion
    {
    
        #region Constructors
    
        /// <summary>
        /// Initializes a new instance of the  class.
        /// </summary>
        public CustomInvertCommand()
            : base()
        {
        }
    
        #endregion
    
    
    
        #region Properties
    
        /// <summary>
        /// Gets the name of the command.
        /// </summary>
        public override string Name
        {
            get
            {
                return "Invert";
            }
        }
    
        /// <summary>
        /// Gets a list of supported native pixel formats for this processing command.
        /// </summary>
        public override System.Collections.ObjectModel.ReadOnlyCollection<Vintasoft.Imaging.PixelFormat> SupportedNativePixelFormats
        {
            get
            {
                System.Collections.Generic.List<Vintasoft.Imaging.PixelFormat> supportedNativePixelFormats =
                    new System.Collections.Generic.List<Vintasoft.Imaging.PixelFormat>();
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.BlackWhite);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Indexed1);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Indexed4);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Indexed8);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Gray8);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Gray16);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgr24);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgr32);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgr48);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgra32);
                supportedNativePixelFormats.Add(Vintasoft.Imaging.PixelFormat.Bgra64);
                return supportedNativePixelFormats.AsReadOnly();
            }
        }
    
        #endregion
    
    
    
        #region Methods
    
        /// <summary>
        /// Returns the pixel format of output image (image after processing)
        /// for input image with specified pixel format.
        /// </summary>
        /// <param name="inputPixelFormat">Pixel format of input image.</param>
        /// <returns>Pixel format of output image.</returns>
        public override Vintasoft.Imaging.PixelFormat GetOutputPixelFormat(
            Vintasoft.Imaging.PixelFormat inputPixelFormat)
        {
            if (IsPixelFormatSupported(inputPixelFormat))
                return inputPixelFormat;
            return Vintasoft.Imaging.PixelFormat.Undefined;
        }
    
        /// <summary>
        /// Creates a new <see cref="CustomInvertCommand"/> that is a copy of the current
        /// instance.
        /// </summary>
        /// <returns>A new <see cref="CustomInvertCommand"/> that is a copy of this
        /// instance.</returns>
        public override object Clone()
        {
            return new CustomInvertCommand();
        }
    
        /// <summary>
        /// Processes the image in-place.
        /// </summary>
        /// <param name="image">Image to process.</param>
        /// <returns>
        /// <b>true</b> if image is processed;
        /// <b>false</b> if processing is canceled or not necessary.
        /// </returns>
        /// <remarks>
        /// This method changes the <i>image</i>.
        /// </remarks>
        protected override bool ProcessImageInPlace(Vintasoft.Imaging.VintasoftImage image)
        {
            System.Drawing.Rectangle rect = this.GetSafeRegionOfInterest(image);
    
            bool cancel = false;
    
            int height = rect.Height;
    
            Vintasoft.Imaging.PixelManipulator pixelManipulator;
            byte[] rowData;
            int rowLength;
    
            float progress = 0;
            float progressDelta = 100f / height;
    
            switch (image.PixelFormat)
            {
                case Vintasoft.Imaging.PixelFormat.BlackWhite:
                case Vintasoft.Imaging.PixelFormat.Indexed1:
                case Vintasoft.Imaging.PixelFormat.Indexed4:
                case Vintasoft.Imaging.PixelFormat.Indexed8:
                case Vintasoft.Imaging.PixelFormat.Gray8:
                    if (!RegionOfInterest.IsEmpty)
                        throw new Vintasoft.Imaging.ImageProcessing.ImageProcessingException(
                            string.Format("{0}: this processing command does not support RegionOfInterest for palette images.", Name));
    
                    image.Palette.Invert();
                    break;
    
                case Vintasoft.Imaging.PixelFormat.Gray16:
                    pixelManipulator = image.OpenPixelManipulator();
                    pixelManipulator.LockPixels(rect, Vintasoft.Imaging.BitmapLockMode.ReadWrite);
                    rowLength = rect.Width * 2;
                    rowData = new byte[rowLength];
                    for (int y = 0; y < height; y++)
                    {
                        pixelManipulator.ReadRowDataUnsafe(y, rowData, 0, rowLength);
                        for (int x = 0; x < rowLength; x += 2)
                        {
                            rowData[x] ^= 0xFF;
                            rowData[x + 1] ^= 0x3F;
                        }
                        pixelManipulator.WriteRowData(y, rowData, 0, rowLength);
    
                        // change the progress
                        progress += progressDelta;
                        // raise the progress event
                        if (!RaiseProgress(progress, true))
                        {
                            cancel = true;
                            break;
                        }
                    }
                    pixelManipulator.UnlockPixels();
                    // close the pixel manipulator
                    image.ClosePixelManipulator(true);
                    break;
    
                case Vintasoft.Imaging.PixelFormat.Bgr24:
                case Vintasoft.Imaging.PixelFormat.Bgr48:
                    pixelManipulator = image.OpenPixelManipulator();
                    pixelManipulator.LockPixels(rect, Vintasoft.Imaging.BitmapLockMode.ReadWrite);
                    rowLength = rect.Width * 3;
                    rowData = new byte[rowLength];
                    for (int y = 0; y < height; y++)
                    {
                        pixelManipulator.ReadRowDataUnsafe(y, rowData, 0, rowLength);
                        for (int x = 0; x < rowLength; x++)
                        {
                            rowData[x] ^= 0xFF;
                        }
                        pixelManipulator.WriteRowDataUnsafe(y, rowData, 0, rowLength);
    
                        // change the progress
                        progress += progressDelta;
                        // raise the progress event
                        if (!RaiseProgress(progress, true))
                        {
                            cancel = true;
                            break;
                        }
                    }
                    pixelManipulator.UnlockPixels();
                    // close the pixel manipulator
                    image.ClosePixelManipulator(true);
                    break;
    
                case Vintasoft.Imaging.PixelFormat.Bgr32:
                case Vintasoft.Imaging.PixelFormat.Bgra32:
                case Vintasoft.Imaging.PixelFormat.Bgra64:
                    pixelManipulator = image.OpenPixelManipulator();
                    pixelManipulator.LockPixels(rect, Vintasoft.Imaging.BitmapLockMode.ReadWrite);
                    rowLength = rect.Width * 4;
                    rowData = new byte[rowLength];
                    for (int y = 0; y < height; y++)
                    {
                        pixelManipulator.ReadRowDataUnsafe(y, rowData, 0, rowLength);
                        for (int x = 0; x < rowLength; x += 4)
                        {
                            rowData[x] ^= 0xFF;
                            rowData[x + 1] ^= 0xFF;
                            rowData[x + 2] ^= 0xFF;
                        }
                        pixelManipulator.WriteRowDataUnsafe(y, rowData, 0, rowLength);
    
                        // change the progress
                        progress += progressDelta;
                        // raise the progress event
                        if (!RaiseProgress(progress, true))
                        {
                            cancel = true;
                            break;
                        }
                    }
                    pixelManipulator.UnlockPixels();
                    // close the pixel manipulator
                    image.ClosePixelManipulator(true);
                    break;
            }
    
            return !cancel;
        }
    
        #endregion
    
    }