
Итак, первым делом добавьте новый пункт меню, в котором будут перечислены показанные на рисунке 1 фильтры.

Рисунок 1.
Каждому пункту меню добавьте свой обработчик. Коды этих обработчиков следуют далее
private void инвертироватьЦветаToolStripMenuItem_Click( object sender, EventArgs e)
{ProgrammDrawingEngine.Filter_0();}
ProgrammDrawingEngine.Filter_1();}
ProgrammDrawingEngine.Filter_2();}
ProgrammDrawingEngine.Filter_3();}
ProgrammDrawingEngine.Filter_4();}
Как видно из кода, мы обращаемся к классу ProgrammDrawingEngine, а именно к функциям, реализованным в нем – filter_0, filter_1 и т.д.
Инвертирование.
Это самый простой фильтр. Функция будет вызывать функцию Inrevrs из класса слоев для данного класса, в результате чего цвета в слое будут инвертированы.
// вызываем функцию инвертирования класса anLayer}
((anLayer)Layers[ActiveLayerNom]).Invers();
Реализация функции Inverse
// циклами переберам все пиксели изображения}
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];
Следующие фильтры будут немного сложнее в реализации.
В классе движка мы будем указывать матрицу для обработки изображения, после чего вызывать функцию осуществления преобразования на основе матрицы и дополнительных параметров, которые мы рассмотрим позднее (при рассмотрение работы самой функции).
Реализация фильтров.
Обратите внимание на то, что теснение мы выполним немного по другому (ни так как в теории) но вы можете попробовать реализовать оба варианта.
// собираем матрицу}
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 );
// собираем матрицу}
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 );
// собираем матрицу}
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 );
// собираем матрицу}
// для данного фильтра нам необзодимо будет произвести 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 и наша работа с фильтрами завершена.
Данная функция проводит все необходимые преобразования (см. комментарии)
// функция обработки слоя изображения на основе полученной матрицы и дополнитлеьных параметров
// 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];}
}
}
Примеры работы программы лучше смотрите сами, т.к. необходимо видеть, что было до и что стало после. Размытие можно применить несколько раз, т.к. оно очень плавно меняет изображение. Потом несколько раз применить резкость, чтобы посмотреть что получится.
Обсуждение данного урока: Создание графических фильтров для обработки изображений с помощью OpenGL.
Далее: 8.1 Теоретическое введение - cплайны.