Итак, первым делом добавьте новый пункт меню, в котором будут перечислены показанные на рисунке 1 фильтры.
Рисунок 1. Меню с различными фильтрами.
Каждому пункту меню добавьте свой обработчик. Коды этих обработчиков следуют далее:
/*http://esate.ru, Anvi*/
private void инвертироватьЦветаToolStripMenuItem_Click( object sender, EventArgs e)
{
ProgrammDrawingEngine.Filter_0();
}
private void применитьФильтрToolStripMenuItem_Click( object sender, EventArgs e)
{
ProgrammDrawingEngine.Filter_1();
}
private void размытиеToolStripMenuItem_Click_1( object sender, EventArgs e)
{
ProgrammDrawingEngine.Filter_2();
}
private void тиснениеToolStripMenuItem_Click( object sender, EventArgs e)
{
ProgrammDrawingEngine.Filter_3();
}
private void акварелизацияToolStripMenuItem_Click( object sender, EventArgs e)
{
ProgrammDrawingEngine.Filter_4();
}
Как видно из кода, мы обращаемся к классу ProgrammDrawingEngine, а именно к функциям, реализованным в нем – filter_0, filter_1 и т.д.
Инвертирование
Это самый простой фильтр. Функция будет вызывать функцию Inrevrs из класса слоев для данного класса, в результате чего цвета в слое будут инвертированы.
/*http://esate.ru, Anvi*/
// фильтр для инвертирования цветов
public void Filter_0()
{
// вызываем функцию инвертирования класса anLayer
((anLayer)Layers[ActiveLayerNom]).Invers();
}
Реализация функции Inverse:
/*http://esate.ru, Anvi*/
// инвертирование цветов
public void Invers()
{
// циклами перебираем все пиксели изображения
for ( int Y = 0; Y < Heigth; Y++)
{
for ( int X = 0; X < Width; X++)
{
// и инвертируем цвет установленный в RGB составляющих на обратный (255-R) (255-G) (255-B)
DrawPlace[X, Y, 0] = 255-DrawPlace[X, Y, 0];
DrawPlace[X, Y, 1] = 255-DrawPlace[X, Y, 1];
DrawPlace[X, Y, 2] = 255-DrawPlace[X, Y, 2];
}
}
}
Следующие фильтры будут немного сложнее в реализации. В классе движка мы будем указывать матрицу для обработки изображения, после чего вызывать функцию осуществления преобразования на основе матрицы и дополнительных параметров, которые мы рассмотрим позднее (при рассмотрение работы самой функции).
Реализация фильтров
Обратите внимание на то, что тиснение мы выполним по-другому (не так, как в теории), но вы можете попробовать реализовать оба варианта:
/*http://esate.ru, Anvi*/
public void Filter_1()
{
// собираем матрицу
float [] mat = new float [9]; mat[0] = -0.1f;
mat[1] = -0.1f;
mat[2] = -0.1f;
mat[3] = -0.1f;
mat[4] = 1.8f;
mat[5] = -0.1f;
mat[6] = -0.1f;
mat[7] = -0.1f;
mat[8] = -0.1f;
//вызываем функцию обработки, передавая туда матрицу и дополнительные параметры.
((anLayer)Layers[ActiveLayerNom]).PixelTransformation(mat, 0, 1, false );
}
public void Filter_2()
{
// собираем матрицу
float [] mat = new float [9];
mat[0] = 0.05f;
mat[1] = 0.05f;
mat[2] = 0.05f;
mat[3] = 0.05f;
mat[4] = 0.6f;
mat[5] = 0.05f;
mat[6] = 0.05f;
mat[7] = 0.05f;
mat[8] = 0.05f;
//вызываем функцию обработки, передавая туда матрицу и дополнительные параметры.
((anLayer)Layers[ActiveLayerNom]).PixelTransformation(mat, 0, 1, false );
}
public void Filter_3()
{
// собираем матрицу
float [] mat = new float [9];
mat[0] = -1.0f;
mat[1] = -1.0f;
mat[2] = -1.0f;
mat[3] = -1.0f;
mat[4] = 8.0f;
mat[5] = -1.0f;
mat[6] = -1.0f;
mat[7] = -1.0f;
mat[8] = -1.0f;
//вызываем функцию обработки, передавая туда матрицу и дополнительные параметры.
((anLayer)Layers[ActiveLayerNom]).PixelTransformation(mat, 0, 2, true );
}
public void Filter_4()
{
// собираем матрицу
// для данного фильтра нам необходимо будет произвести 2 преобразования
float [] mat = new float [9];
mat[0] = 0.50f;
mat[1] = 1.0f;
mat[2] = 0.50f;
mat[3] = 1.0f;
mat[4] = 2.0f;
mat[5] = 1.0f;
mat[6] = 0.50f;
mat[7] = 1.0f;
mat[8] = 0.50f;
//вызываем функцию обработки, передавая туда матрицу и дополнительные параметры.
((anLayer)Layers[ActiveLayerNom]).PixelTransformation(mat, 0, 2, true );
mat[0] = -0.5f;
mat[1] = -0.5f;
mat[2] = -0.5f;
mat[3] = -0.5f;
mat[4] = 6.0f;
mat[5] = -0.5f;
mat[6] = -0.5f;
mat[7] = -0.5f;
mat[8] = -0.5f;
//вызываем функцию обработки, передавая туда матрицу и дополнительные параметры.
((anLayer)Layers[ActiveLayerNom]).PixelTransformation(mat, 0, 1, false );
}
Теперь нам осталось рассмотреть работу функции PixelTransformation, и наша работа с фильтрами завершена.
Данная функция проводит все необходимые преобразования (см. комментарии):
/*http://esate.ru, Anvi*/
// функция обработки слоя изображения на основе полученной матрицы и дополнительных параметров
// corr - коррекция составляющей цвета - после обработки каждого пикселя к каждой его составляющей будет
// прибавлено данное значение
// COEFF - коэффициент, реализующий усиление работы фильтра
// need_count_correction - необходимость корректировки значения полученного пикселя после прохода фильтра.
// если данный параметра установлен, то каждая составляющая цвета, перед тем как быть приведенной к виду 0-255,
// будет разделена на количество произошедших с ней преобразований. Необходимо для корректной работы некоторых фильтров.
public void PixelTransformation( float [] mat, int corr, float COEFF, bool need_count_correction)
{
// массив для получения результирующего пикселя
float [] resault_RGB = new float [3];
int count = 0;
// проходим циклом по всем пикселям слоя
for ( int Y = 0; Y < Heigth; Y++)
{
for ( int X = 0; X < Width; X++)
{
// цикл по всем составляющим (0-2, т.е. R G B)
for ( int c = 0, ax = 0, bx = 0; c < 3; c++)
{
// обнуление составляющей результата
resault_RGB[c] = 0;
// обнуление счетчика обработок
count = 0;
// 2 цикла для захвата области 3х3 вокруг обрабатываемого пикселя
for (bx = -1; bx < 2; bx++)
{
for (ax = -1; ax < 2; ax++)
{
// если мы не попали в рамки, просто используем центральный пиксель, и продолжаем цикл
if (X + ax < 0 || X + ax > Width-1 || Y + bx < 0 || Y + bx > Heigth-1)
{
// считаем составляющую в одной из точек, используя коэффициент в матрице (под номером текущей итерации),
// коэффициент усиления (COEFF) и прибавляем коррекцию (corr)
resault_RGB[c] += ( float )(DrawPlace[X, Y, c]) * mat[count] * COEFF + corr;
// счетчик обработок = ячейке матрицы с необходимым коэффициентом
count++;
// продолжаем цикл
continue;
}
// иначе, если мы укладываемся в изображение (не пересекаем границы), используем
// соседние пиксели, корректируя ячейку массива параметрами ax, bx
resault_RGB[c] += ( float )(DrawPlace[X + ax, Y + bx, c]) * mat[count] * COEFF + corr;
// счетчик обработок = ячейке матрицы с необходимым коэффициентом
count++;
}
}
}
// теперь для всех составляющих корректируем цвет
for ( int c = 0; c < 3; c++)
{
// если требуется разделить результат до приведения к 0-255,
// разделив на количество проведенных операций.
if( count != 0 && need_count_correction)
{
// выполняем данное деление
resault_RGB[c] /= count;
}
// если значение меньше нуля,
if (resault_RGB[c] < 0)
{
// приравниваем к нулю
resault_RGB[c] = 0;
}
// если больше 255,
if (resault_RGB[c] > 255)
{
// приравниваем к 255
resault_RGB[c] = 255;
}
// записываем в массив цветов слоя новое значение
DrawPlace[X, Y, c] = ( int )resault_RGB[c];
}
}
}
}
Примеры работы программы лучше смотрите сами, т.к. необходимо видеть, что было до и что стало после. Размытие можно применить несколько раз, т.к. оно очень плавно меняет изображение. Потом несколько раз применить резкость, чтобы посмотреть, что получится.