Давайте попробуем создать эффект, иммитирующий эту технику.
Итак, пошагово.
Шаг 1. Откройте какое-либо изображение.
Шаг 2. Примените к нему эффект Эскиз (Эффекты -> Стилизация -> Эскиз) с параметрами по умолчанию.
Шаг 3. Переведите получившееся изображение в черно-белый рисунок (Коррекция -> Сделать черно-белым).
Шаг 4. В меню Коррекция запустите эффект Кривые (Коррекция -> Кривые). Левую нижнюю точку кривой перетащите вправо, установив ее значения в (231,0). Правую верхнюю точку кривой перетащите влево, установив ее значения в (232,255).
Шаг 5. Инвертируйте изображение (Коррекция -> Инвертировать цвета). В результате получится такое изображение.
Вернитесь к шагу 4. Установите значения верхней точки кривой в (240,255), нижней - в (215,0). Попробуйте двигать левую точку вправо, до значений (239,0) - вы заметите, что это изменение приводит к детализации изображения.
Теперь давайте будем создавать наш эффект. Запустите CodeLab (Эффекты -> Advanced -> Code Lab). В меню Файл выберите Новый. Выберите в выпадающем списке эффектов Эскиз. В верхнем выпадающем списке Обработка пикселя выберите Сделать черно-белым. В нижнем выпадающем списке Обработка пикселя выберите Инвертировать цвета. Нажмите кнопку Генерировать код. Мы получим следующий сценарий эффекта:
Код: Выделить всё
#region UICode
int Amount1=3; // [1,200] Толщина
int Amount2=50; // [0,100] Интенсивность
#endregion
// Настройки использования операций с пикселями
private UnaryPixelOps.Desaturate desaturateOp = new UnaryPixelOps.Desaturate();
private UnaryPixelOps.Invert invertOp = new UnaryPixelOps.Invert();
// Это основной цикл функции обработки
void Render(Surface dst, Surface src, Rectangle rect)
{
// Настройки вызова эффекта Эскиз
OutlineEffect outlineEffect = new OutlineEffect();
PropertyCollection outlineProps = outlineEffect.CreatePropertyCollection();
PropertyBasedEffectConfigToken outlineParameters = new PropertyBasedEffectConfigToken(outlineProps);
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Thickness, Amount1);
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Intensity, Amount2);
outlineEffect.SetRenderInfo(outlineParameters, new RenderArgs(dst), new RenderArgs(src));
// Вызов функции Эскиз
outlineEffect.Render(new Rectangle[1] { rect }, 0, 1);
// Теперь в основном цикле обработки холст назначения (dst) имеет эскизную версию холста источника (src)
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 = desaturateOp.Apply(CurrentPixel);
CurrentPixel = invertOp.Apply(CurrentPixel);
dst[x,y] = CurrentPixel;
}
}
}
Код: Выделить всё
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Intensity, Amount2);
Теперь давайте воспроизведем шаг 4. Между строкой
Код: Выделить всё
CurrentPixel = desaturateOp.Apply(CurrentPixel);
Код: Выделить всё
CurrentPixel = invertOp.Apply(CurrentPixel);
Код: Выделить всё
int R = CurrentPixel.R;
int G = CurrentPixel.G;
int B = CurrentPixel.B;
// Преобразование в контрастное черно-белое изображение
if (R<232) {R=0;}
else R=255;
if (G<232) {G=0;}
else G=255;
if (B<232) {B=0;}
else B=255;
CurrentPixel.R = Int32Util.ClampToByte(R);
CurrentPixel.G = Int32Util.ClampToByte(G);
CurrentPixel.B = Int32Util.ClampToByte(B);
В блоке кодов интерфейса переменную Amount1 переименуйте в Размер инструмента. Переменную Amount2 переименуйте в Детализация, установите ее значение по умолчанию в 17, минимальное значение в 1, максимальное - в 25.
Теперь наш сценарий будет выглядеть так:
Код: Выделить всё
#region UICode
int Amount1=3; // [1,200] Размер инструмента
int Amount2=17; // [1,25] Детализация
#endregion
// Настройки использования операций с пикселями
private UnaryPixelOps.Desaturate desaturateOp = new UnaryPixelOps.Desaturate();
private UnaryPixelOps.Invert invertOp = new UnaryPixelOps.Invert();
// Это основной цикл функции обработки
void Render(Surface dst, Surface src, Rectangle rect)
{
// Настройки вызова эффекта Эскиз
OutlineEffect outlineEffect = new OutlineEffect();
PropertyCollection outlineProps = outlineEffect.CreatePropertyCollection();
PropertyBasedEffectConfigToken outlineParameters = new PropertyBasedEffectConfigToken(outlineProps);
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Thickness, Amount1);
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Intensity, 50);
outlineEffect.SetRenderInfo(outlineParameters, new RenderArgs(dst), new RenderArgs(src));
// Вызов функции Эскиз
outlineEffect.Render(new Rectangle[1] { rect }, 0, 1);
// Теперь в основном цикле обработки холст назначения (dst) имеет эскизную версию холста источника (src)
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 = desaturateOp.Apply(CurrentPixel);
int R = CurrentPixel.R;
int G = CurrentPixel.G;
int B = CurrentPixel.B;
int T = Amount2 + 214;
// Преобразование в контрастное черно-белое изображение
if (R<T) {R=0;}
else R=255;
if (G<T) {G=0;}
else G=255;
if (B<T) {B=0;}
else B=255;
CurrentPixel.R = Int32Util.ClampToByte(R);
CurrentPixel.G = Int32Util.ClampToByte(G);
CurrentPixel.B = Int32Util.ClampToByte(B);
CurrentPixel = invertOp.Apply(CurrentPixel);
dst[x,y] = CurrentPixel;
}
}
}
Возможно вы захотите получить инверсную версию изображения, полученную в результате работы эффекта. Тогда давайте изменим наш интерфейс. Откройте Конструктор интерфеса (Файл -> Конструктор интерфеса). В поле Тип элемента выберите Check Box, в поле Имя элемента впишите Инвертировать, в поле По умолчанию впишите 0. Нажмите кнопку Добавить и кнопку ОК.
Измените запись в строке
Код: Выделить всё
CurrentPixel = invertOp.Apply(CurrentPixel);
Код: Выделить всё
if (!Amount3) {CurrentPixel = invertOp.Apply(CurrentPixel);}
Код: Выделить всё
// 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 = 3; // [1,10] Размер инструмента
int Amount2 = 17; // [1,25] Детализация
bool Amount3 = false; // [0,1] Инвертировать
#endregion
// Настройки использования операций с пикселями
private UnaryPixelOps.Desaturate desaturateOp = new UnaryPixelOps.Desaturate();
private UnaryPixelOps.Invert invertOp = new UnaryPixelOps.Invert();
// Это основной цикл функции обработки
void Render(Surface dst, Surface src, Rectangle rect)
{
// Настройки вызова эффекта Эскиз
OutlineEffect outlineEffect = new OutlineEffect();
PropertyCollection outlineProps = outlineEffect.CreatePropertyCollection();
PropertyBasedEffectConfigToken outlineParameters = new PropertyBasedEffectConfigToken(outlineProps);
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Thickness, Amount1);
outlineParameters.SetPropertyValue(OutlineEffect.PropertyNames.Intensity, 50);
outlineEffect.SetRenderInfo(outlineParameters, new RenderArgs(dst), new RenderArgs(src));
// Вызов функции Эскиз
outlineEffect.Render(new Rectangle[1] { rect }, 0, 1);
// Теперь в основном цикле обработки холст назначения (dst) имеет эскизную версию холста источника (src)
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 = desaturateOp.Apply(CurrentPixel);
int R = CurrentPixel.R;
int G = CurrentPixel.G;
int B = CurrentPixel.B;
int T = Amount2 + 214;
// Преобразование в контрастное черно-белое изображение
if (R<T) {R=0;}
else R=255;
if (G<T) {G=0;}
else G=255;
if (B<T) {B=0;}
else B=255;
CurrentPixel.R = Int32Util.ClampToByte(R);
CurrentPixel.G = Int32Util.ClampToByte(G);
CurrentPixel.B = Int32Util.ClampToByte(B);
if (!Amount3) {CurrentPixel = invertOp.Apply(CurrentPixel);}
dst[x,y] = CurrentPixel;
}
}
}
Теперь давайте сохраним наш эффект как DLL файл: Файл -> Сохранить как DLL... В представленном вам диалоге сборки DLL есть почти вся необходимая информация. Щелкните по ссылке Выбор значка и выберите ваш значок. Нажмите кнопку Создать - ваш новый эффект готов!
Так выглядит интерфейс пользователя нашего нового эффекта.
А так выглядит результат работы эффекта с отмеченным флажком Инвертировать.
Надеюсь создание этого эффекта затруднений у вас не вызвало.