VintaSoft Imaging .NET SDK 15.1: Документация для .NET разработчика
В этом разделе
Пользовательская команда обработки изображения
В этом разделе
Для создания пользовательской команды обработки изображения необходимо выполнить следующие действия:
  1. Создать новый класс, который наследуется от класса ProcessingCommandBase или любой другой существующей команды обработки изображений из пространства имен Vintasoft.Imaging.ImageProcessing
  2. Переопределить метод ProcessingCommandBase.ProcessImageInPlace в своем классе
  3. Переопределить свойство ProcessingCommandBase.SupportedPixelFormats, если ваша команда поддерживает не все форматы пикселей
  4. Вызвать метод ProcessingCommandBase.RaiseProgress во время выполнения команды, если ваша команда поддерживает индикатор прогресса


Вот C#/VB.NET код, который демонстрирует, как создать команду обработки изображения, которая инвертирует цвета изображения:
/// <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

}
''' <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