CodeLab - первые шаги (Губка)

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

CodeLab - первые шаги (Губка)

Сообщение ReMake » 21 май 2015, 20:20

Среди фильтров Фотошопа есть фильтр Губка. Ниже представлен результат работы этого фильтра и фрагмент его интерфейса.
Изображение

Можно ли создать подобный эффект для Paint?NET? Конечно, возможно.

Итак, начнем шаг за шагом.

Шаг 1. Откройте какое-либо изображение. Добавьте новый слой.

Шаг 2. Примените к слою эффект Облака со следующими параметрами: Приближение - 24, Жесткость - 0.40.

Шаг 3. В меню Коррекция запустите эффект Кривые (Коррекция -> Кривые). Левую нижнюю точку кривой перетащите вправо до середины, установив ее значения в (127,0). Правую верхнюю точку кривой перетащите влево до середины, установив ее значения в (128,255).
Изображение

Шаг 4. Устраните светлые участки слоя, применив эффект Устранить темный/светлый.

Шаг 5. В меню Слои выберите Свойства слоя. В открывшемся диалоговом окне выберите режим смешивания Умножение или Замена темным, установите непрозрачность слоя в 25.

Ниже показан получившийся результат:
Изображение

Сравните с предыдущим рисунком. Похоже, не правда ли? Попробуйте повторить предыдущие действия для разных параметров Приближение и Жесткость эффекта Облака и непрозрачности слоя.

Теперь давайте будем создавать наш эффект. Запустите CodeLab (Эффекты -> Advanced -> Code Lab). В меню Файл выберите Новый. Выберите в выпадающем списке эффектов Облака, в выпадающем списке Режимы смешивания выберите Умножение или Замена темным. Нажмите кнопку Генерировать код. Мы получим следующий сценарий эффекта:

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

#region UICode
int Amount1 = 250; // [2,1000] Приближение
double Amount2 = 0.5; // [0,1] Четкость
BinaryPixelOp Amount3 = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Normal); // Режим смешивания
byte Amount4 = 0; // [255] Перегенерировать
#endregion

// Настройки для вызова обработки эффекта Облака
private CloudsEffect cloudsEffect = new CloudsEffect();
private PropertyCollection cloudsProps;

// Настройки для использования режима смешивания Умножение
private BinaryPixelOp multiplyOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Multiply);

// Это основной цикл функции обработки
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Вызов обработки функции Облака
    cloudsProps = cloudsEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken CloudsParameters = new PropertyBasedEffectConfigToken(cloudsProps);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.BlendMode, Amount3);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, (int)Amount4);
    cloudsEffect.SetRenderInfo(CloudsParameters, new RenderArgs(dst), new RenderArgs(src));
    // Вызов функции Облака с использованием черного и белого цветов
    cloudsEffect.Render(new Rectangle[1] {rect},0,1);

    // Теперь в основном цикле холст назначения (dst) обработан облаками
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];

            // ВЫПОЛНЕНИЕ: Добавьте здесь дополнительный код обработки пикселей

            CurrentPixel = multiplyOp.Apply(src[x,y], CurrentPixel);


            dst[x,y] = CurrentPixel;
        }
    }
}
Откройте Конструктор интерфейса (Файл -> Конструктор интерфейса), выберите в нем элемент управления Приближение и переименуйте его в Размер кисти. Установите максимальное значение в 100, значение по умолчанию установите в 25. Нажмите кнопку Обновить. Выберите второй элемент управления и переименуйте его в Шероховатость. Установите минимальное значение в 0, максимальное - 10 и значение по умолчанию - 0. В поле Тип элемента выберите Integer Slider. Нажмите кнопку Обновить. Третий и четвертый элементы управления удалите - они нам не понадобятся. Нажмите кнопку OK.

Закомментируйте или удалите следующую строку:

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

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.BlendOp, Amount3);
она нам уже не понадобится.

В строке

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

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, (int)Amount4);
вместо (int)Amount4 впишите 255.

Так как мы изменили тип переменной Amount2, нам придется внести измения в следующую строку

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

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2);
заменив Amount2 на Amount2/10.0

Сохраните этот сценарий с именем Sponge_1 (Файл -> Сохранить). Создайте одноименный DLL файл, проверьте как он работает. Итак, мы воспроизвели шаг 2, описанный выше.

Теперь давайте создадим аналог шага 3. Для этого нам понадобятся переменные R, G, B и A. Добавим их в наш сценарий:

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

 CurrentPixel = dst[x,y];
 int R = CurrentPixel.R;
 int G = CurrentPixel.G;
 int B = CurrentPixel.B;
 int A = CurrentPixel.A;
Значения всех цветовых компонент пикселя, которые меньше 128, установим в 0, значения, которые больше или равны 128, установим в 255.

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

// Преобразование в контрастное черно-белое изображение
        if (R<128) {R=0;} 
        else R=255; 
        if (G<128) {G=0;} 
        else G=255; 
        if (B<128) {B=0;} 
        else B=255;  
Восстановим значение каждого пикселя:

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

CurrentPixel.R = Int32Util.ClampToByte(R);
CurrentPixel.G = Int32Util.ClampToByte(G);
CurrentPixel.B = Int32Util.ClampToByte(B);
Для того, чтобы воспроизвести шаг 4, вставьте в сценарий эту строку:

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

 A = 255 - Math.Min(Math.Min(R,G),B);
Для воспроизведения шага 5 нам понадобится еще один элемент управления. Откройте Конструктор интерфейса. В выпадающем списке Тип элемента выберите Integer Slider. В поле Имя элемента впишите Интенсивность. Установите максимальное значение и значение по умолчанию в 255. Нажмите кнопку Добавить, затем нажмите кнопку OK. Теперь давайте добавим в наш сценарий еще одну строку:

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

CurrentPixel.A = Int32Util.ClampToByte(A + Amount3 - 255);
Наш сценарий будет выглядеть следующим образом:

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

#region UICode
int Amount1 = 25; // [2,100] Размер кисти
int Amount2 = 0; // [0,10] Шероховатость
int Amount3 = 255; // [0,255] Интенсивность
#endregion

// Настройки для вызова обработки эффекта Облака
private CloudsEffect cloudsEffect = new CloudsEffect();
private PropertyCollection cloudsProps;

// Настройки для использования режима смешивания Умножение
private BinaryPixelOp multiplyOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Multiply);

// Это основной цикл функции обработки
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Вызов обработки функции Облака
    cloudsProps = cloudsEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken CloudsParameters = new PropertyBasedEffectConfigToken(cloudsProps);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2/10.0);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, 255);
    cloudsEffect.SetRenderInfo(CloudsParameters, new RenderArgs(dst), new RenderArgs(src));
    // Вызов функции Облака с использованием черного и белого цветов
    cloudsEffect.Render(new Rectangle[1] {rect},0,1);

    // Теперь в основном цикле холст назначения (dst) обработан облаками
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];

            // ВЫПОЛНЕНИЕ: Добавьте здесь дополнительный код обработки пикселей
            CurrentPixel = dst[x,y];
            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;
            int A = CurrentPixel.A;
            
            // Преобразование в черно-белое контрастное изображение
        	if (R<128) {R=0;} 
        	else R=255; 
        	if (G<128) {G=0;} 
        	else G=255; 
        	if (B<128) {B=0;} 
        	else B=255; 

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

            // Устранение светлых участков
            A = 255 - Math.Min(Math.Min(R,G),B);

            CurrentPixel.A = Int32Util.ClampToByte(A + Amount3 - 255);

            CurrentPixel = multiplyOp.Apply(src[x,y], CurrentPixel);

            dst[x,y] = CurrentPixel;
        }
    }
}
Сохраните этот сценарий с именем Sponge_2. Создайте одноименный DLL файл, проверьте как он работает, применив различные параметры элементов управления.

Ниже приведены диапазоны параметров нашего эффекта, наиболее соответствующие результатам работы фильтра Губка в Фотошопе:
- Размер кисти - 22...32
- Шероховатость - 0...10
- Интенсивность - 10...55

Давайте внесем изменения в наш сценарий с учетом полученных результатов.
Блок кода интерфейса пользователя будет выглядеть так:

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

#region UICode
int Amount1 = 2; // [0,10] Размер кисти
int Amount2 = 7; // [0,10] Шерховатость
int Amount3 = 5; // [0,15] Интенсивность
#endregion
Измените в сценарии следующие строки:

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

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1 + 20);
CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, 1.0 - Amount2/10.0);

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

CurrentPixel.A = Int32Util.ClampToByte(A + Amount3*3 - 255);
Осталось добавить некоторую информацию:

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

// Author: ReMake
// Submenu: Artistic
// Name: Губка
// Title: Губка
// Desc: Paint.Net эффект, имитирующий рисование губкой
// Keywords: paint.net|эффект|губка
// URL: http://www.getpaint.net/redirect/plugins.html
и наш окончательный сценарий будет выглядеть так:

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

// Author: ReMake
// Submenu: Artistic
// Name: Губка
// Title: Губка
// Desc: Paint.Net эффект, имитирующий рисование губкой
// Keywords: paint.net|эффект|губка
// URL: http://www.getpaint.net/redirect/plugins.html
#region UICode
int Amount1 = 2; // [0,10] Размер кисти
int Amount2 = 7; // [0,10] Шерховатость
int Amount3 = 5; // [0,15] Интенсивность
#endregion

// Настройки вызова обработки эффекта Облака
private CloudsEffect cloudsEffect = new CloudsEffect();
private PropertyCollection cloudsProps;

// Настройки использования режима смешивания Умножение
private BinaryPixelOp multiplyOp = new UserBlendOps.MultiplyBlendOp();

// Это основной цикл функции обработки
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Вызов функции обработки Облака
    cloudsProps = cloudsEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken CloudsParameters = new PropertyBasedEffectConfigToken(cloudsProps);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1 + 22);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, 1.0 - Amount2/10.0);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, 255);
    cloudsEffect.SetRenderInfo(CloudsParameters, new RenderArgs(dst), new RenderArgs(src));
    // Вызов функции Облака с использованием черного и белого цветов
    cloudsEffect.Render(new Rectangle[1] { rect }, 0, 1);

    //ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor;

    // Теперь в основном цикле холст назначения (dst) обработан облаками
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x, y];
            // ВЫПОЛНЕНИЕ: Добавьте здесь код обработки пикселей

            CurrentPixel = dst[x,y];
            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;
            int A = CurrentPixel.A;

           // Преобразование в черно-белое контрастное изображение
                if (R<128) {R=0;} 
                else R=255; 
                if (G<128) {G=0;} 
                else G=255; 
                if (B<128) {B=0;} 
                else B=255;  
            
		CurrentPixel.R = Int32Util.ClampToByte(R);
		CurrentPixel.G = Int32Util.ClampToByte(G);
		CurrentPixel.B = Int32Util.ClampToByte(B);

            // Устранение светлых участков
            A = 255 - Math.Min(Math.Min(R,G),B);
            
            CurrentPixel.A = Int32Util.ClampToByte(A + Amount3*3 - 245);

            CurrentPixel = multiplyOp.Apply(src[x, y], CurrentPixel);

            dst[x, y] = CurrentPixel;
        }
    }
}
Сохраните сценарий с именем Sponge. Создайте для нашего эффекта подходящий значок в виде PNG файла размером 16X16 пикселей. Я создал такой значок: Изображение

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

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

А так выглядит результат работы эффекта.
Изображение

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

P.S. Для того, чтобы результат работы этого эффекта был максимально пхож на работу фотошоповского фильтра Губка, сначала примените к изображению эффект Картина, масло с параметрами: Размер кисти - 2...3 и Грубость мазков - 3... 20.

Результат работы обоих эффектов выглядит так:
Изображение

К сожалению одновременное использование двух встроенных Paint.Net эффектов в CodeLab недоступно.

Ответить

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

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

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