CodeLab - первые шаги (Насыщенность RGB)

Эта ветка форума посвящена инструкции по работе с лабораторией скриптов CodeLab от BoltBait. С её помощью можно делать свои плагины для Paint.NET. Все вопросы по CodeLab размещаются здесь.
Ответить
ReMake
Сообщения: 344
Зарегистрирован: 10 сен 2014, 01:25
Репутация: 108
Пол: Мужской
Откуда: Брест, Беларусь

CodeLab - первые шаги (Насыщенность RGB)

Сообщение ReMake » 18 мар 2015, 21:42

Вероятно вы не один раз применяли Paint.NET эффект Оттенок и насыщенность. Возможно, вы задавались вопросом - можно ли регулировать насыщенность отдельно в каждом цветовом канале? Да, это возможно.

Давайте начнем создавать в CodeLab этот простой эффект.

Запустите CodeLab: Эффекты -> Advanced -> CodeLab. Вам будет представлено диалоговое окно CodeLab со сценарием по умолчанию:

Код: Выделить всё

#region UICode
int Amount1=0; // [0,100] Слайдер 1 Описание
int Amount2=0; // [0,100] Слайдер 2 Описание
int Amount3=0; // [0,100] Слайдер 3 Описание
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    // Удалите любую из этих строк, в которой вы не нуждаетесь
    Rectangle selection = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    int CenterX = ((selection.Right - selection.Left) / 2)+selection.Left;
    int CenterY = ((selection.Bottom - selection.Top) / 2)+selection.Top;
    ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor;
    ColorBgra SecondaryColor = (ColorBgra)EnvironmentParameters.SecondaryColor;
    int BrushWidth = (int)EnvironmentParameters.BrushWidth;

    ColorBgra CurrentPixel;
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {
            CurrentPixel = src[x,y];
            // ВЫПОЛНЕНИЕ: Добавьте здесь код обработки пикселей
            // Это путь доступа к значениям RGBA. Например:
            // CurrentPixel.R = (byte)PrimaryColor.R;
            // CurrentPixel.G = (byte)PrimaryColor.G;
            // CurrentPixel.B = (byte)PrimaryColor.B;
            // CurrentPixel.A = (byte)PrimaryColor.A;
            dst[x,y] = CurrentPixel;
        }
    }
}
Удалите следующие строки

Код: Выделить всё

    // Удалите любую из этих строк, в которой вы не нуждаетесь
    Rectangle selection = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    int CenterX = ((selection.Right - selection.Left) / 2)+selection.Left;
    int CenterY = ((selection.Bottom - selection.Top) / 2)+selection.Top;
    ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor;
    ColorBgra SecondaryColor = (ColorBgra)EnvironmentParameters.SecondaryColor;
    int BrushWidth = (int)EnvironmentParameters.BrushWidth;
они нам не понадобятся.

Откройте Конструктор интерфейса: Файл -> Конструктор интерфейса. Выделите в нем верхнюю строку и в поле Имя элемента впишите Красный. Нажмите кнопку Обновить. Переименуйте следующие элементы управления в Зеленый и Синий соответственно. Теперь наш блок кода интерфейса будет выглядеть так:

Код: Выделить всё

#region UICode
int Amount1=0; // [0,100] Красный
int Amount2=0; // [0,100] Зеленый
int Amount3=0; // [0,100] Синий
#endregion
Так как мы будем настраивать составляющие цвета каждого пикселя по отдельности, нам понадобятся три переменные: R, G и B. Добавьте эти строки после CurrentPixel = src[x,y];

Код: Выделить всё

            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;
Нам потребуется еще одна переменная gray, добавьте ее ниже строк, приведенных выше.

Код: Выделить всё

            int gray = (R+G+B)/3;
Методом проб я определил формулу настройки цветового канала: Color = ((100 - AmountX)*gray + AmountX*Color)/100. Применим эту формулу к каждому из трех каналов:

Код: Выделить всё

            // ВЫПОЛНЕНИЕ: Добавьте здесь код обработки пикселей
            R = ((100 - Amount1)*gray + Amount1*R)/100;
            G = ((100 - Amount2)*gray + Amount2*G)/100;
            B = ((100 - Amount3)*gray + Amount3*B)/100;
Осталось собрать компоненты цвета пикселя воедино:

Код: Выделить всё

                CurrentPixel.R = Int32Util.ClampToByte(R);
                CurrentPixel.G = Int32Util.ClampToByte(G);
                CurrentPixel.B = Int32Util.ClampToByte(B);
Теперь наш сценарий выглядит так:

Код: Выделить всё

#region UICode
int Amount1 = 0; // [0,100] Красный
int Amount2 = 0; // [0,100] Зеленый
int Amount3 = 0; // [0,100] Синий
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    ColorBgra CurrentPixel;
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            CurrentPixel = src[x,y];
            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;
            int gray = (R+G+B)/3;

            // ВЫПОЛНЕНИЕ: Добавьте здесь код обработки пикселей
            R = ((100 - Amount1)*gray + Amount1*R)/100;
            G = ((100 - Amount2)*gray + Amount2*G)/100;
            B = ((100 - Amount3)*gray + Amount3*B)/100;

                CurrentPixel.R = Int32Util.ClampToByte(R);
                CurrentPixel.G = Int32Util.ClampToByte(G);
                CurrentPixel.B = Int32Util.ClampToByte(B);

            dst[x,y] = CurrentPixel;
        }
    }
}
Сохраните этот сценарий с именем SaturationRGB_1 (Файл -> Сохранить...) и создайте DLL файл с тем же именем (Файл -> Сохранить как DLL...). Проверьте, как работает ваш эффект.

Когда все слайдеры установлены в 0, мы получим изображение серого цвета. Если установить все слайдеры в 100, то мы получим исходное не измененное изображение.

Давайте продолжим. Замените в блоке кода интерфейса максимальные значения на 300 (эксперимент показывает, что большие значения приведут к потере деталей изображения). Минимальные значения установите в -200 (значения меньшие чем -200 также приведут к потере деталей изображения). Значения по умолчанию установите в 100. Блок кода интерфейса теперь будет выглядеть так:

Код: Выделить всё

#region UICode
int Amount1 = 100; // [-200,300] Красный
int Amount2 = 100; // [-200,300] Зеленый
int Amount3 = 100; // [-200,300] Синий
#endregion
Давайте обратимся к Using CodeLab to Build a DLL от BoltBait'а. В секции Default мы найдем некоторую полезную информацию и оформим аналогичную для нашего сценария:

// Author: ReMake - имя автора эффекта
// Name: Насыщенность RGB - название эффекта в меню
// Title: Насыщенность RGB - заголовок интерфейса UI эффекта
// Desc: Насыщенность RGB - описание эффекта
// Keywords: paint.net|эффект|насыщенность|rgb - ключевые слова, по которым ваш эффект может быть найден в интернете
// URL: http://www.getpaint.net/redirect/plugins.html - ваш адрес в сети (или на форуме)

Вставим эту информацию над блоком кода интерфейса UI:

Код: Выделить всё

// Author: ReMake
// Name: Насыщенность RGB
// Title: Насыщенность RGB
// Desc: Насыщенность RGB
// Keywords: paint.net|эффект|насыщенность|rgb
#region UICode
int Amount1 = 100; // [-200,300] Красный
int Amount2 = 100; // [-200,300] Зеленый
int Amount3 = 100; // [-200,300] Синий
#endregion
Сохраните этот сценарий с именем SaturationRGB.

И последнее, осталось оформить значок для интерфейса нашего эффекта в виде файла PNG размером 16 на 16 пикселей. Я создал вот такой значок: Изображение

Теперь давайте сохраним наш эффект как DLL файл: Файл -> Сохранить как DLL... В представленном вам диалоге сборки DLL есть почти вся необходимая информация. В настройках меню выберите пункт Коррекция. Щелкните по ссылке Выбор значка и выберите ваш значок. Нажмите кнопку Создать - ваш новый эффект готов!

Так выглядит интерфейс пользователя нашего нового эффекта.
Изображение

Я думаю, что создать этот эффект было совсем не трудно.

Это был мой первый эффект!

Результаты работы эффекта можно посмотреть в теме Насыщенность RGB.

Ответить

Вернуться в «CodeLab от BoltBait»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя