48629 (588583), страница 3

Файл №588583 48629 (Разработка программного обеспечения для фильтрации растровых изображений) 3 страница48629 (588583) страница 32016-07-29СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 3)

{if(m_pCurFilter==NULL) return;

if(!CreateCompatibleBuffer()) return;

m_EventDoTransform.SetEvent();

m_bEditable=FALSE;

InformAllViews(UM_STARTTRANSFORM);

CRaster*pSBM=GetCurrentBMPtr(),//источник

*pDBM=GetBufferBMPtr();// приёмник

// Установили в фильтр источник и приёмник преобразований

m_pCurFilter->SetBuffers(pSBM, pDBM);

for(LONG y=0; yGetBMHeight(); y++)

{// Процент выполнения

InterlockedExchange(&m_lExecutedPercent, 100*y/pSBM->GetBMHeight());

//Проверка не решили ли прервать преобразование

if(!m_EventDoTransform.Lock(0))

{InformAllViews(UM_ENDOFTRANSFORM, FALSE, 0);

m_bEditable=TRUE;

return; }

LONG x=0;

// Преобразование с использованием текущего фильтра

for(; xGetBMWidth(); x++)

m_pCurFilter->TransformPix(x, y); }

m_EventDoTransform.ResetEvent();

m_bEditable=TRUE;

SwapBM();//Сделать буфер текущим изображением

SetModifiedFlag(); //флаг “данные изменились”

InformAllViews(UM_ENDOFTRANSFORM, TRUE, 0);

return;

};

В методе TransformLoop() мы сначала "зажигаем" событие "Выполняется преобразование" - объект m_EventDoTransform класса CEvent. Затем сообщаем текущему фильтру, какое изображение будет исходным, и какое - приемным (адреса объектов CRaster). Далее в цикле прогоняем через фильтр пикселы изображения. На текущий фильтр указывает переменная m_pCurFilter, которую мы завели в классе CBMDoc специально для этих целей. Тип этой переменной - указатель на объект класса CFilter. Преобразование же данных выполняется с помощью метода Cfilter::TransformPix(), Класс СFilter как раз и является базовым для всех фильтров.

В процессе преобразования перед обработкой очередной строки пикселов вычисляется процент выполнения как процент уже обработанных строк изображения. Вычисленное значение записывается в переменную m_lExecutedPercent с помощью API-функции InterlockedExchange() - эта функция позволяет предотвратить одновременное обращение к переменной из разных потоков. Далее проверяется, по-прежнему ли установлено событие m_EventDoTransform. И только затем обрабатываются пикселы строки. Причем в нашей программе в иллюстрационных целях мы позволяем пользователю посмотреть эффект преобразования на половине изображения. Если установлен флаг m_bEditHalf, первая половина строки копируется в неизменном виде.

После того как все пикселы изображения были обработаны, скидывается флаг m_EventDoTransform, буферное изображение становится активным и во все облики направляется сообщение UM_ENDOFTRANSFORM с параметром TRUE, который говорит о том, что преобразование завершилось и надо обновить изображение в окне облика.

Для контроля количества выполненной работы фильтра в класс CBMView с помощью ClassWizard добавим метод OnTimer(). В этом методе будет выполняться запрос процента выполнения операции и обновляться информация о выполнении. Процент выполнения операции отображается в заголовке окна облика.

Приход сообщения UM_ENDOFTRANSFORM обрабатывается методом OnEndTransform(), который зависит от значения аргумента wParam:

  • TRUE - преобразование успешно закончено - выполняет обновление экрана;

  • FALSE - пользователь прервал операцию - не выполняет обновление экрана. Далее им вызывается функция OnStopTimer(), которая разрушает таймер.

Выделение операций обработки данных, которые могут выполняться длительный отрезок времени, в отдельный поток позволяет пользователю сохранить контроль над выполнением программы. В нашем приложении пользователь, запустив фильтрацию на одном из открытых изображений, может переключиться на просмотр и редактирование другого изображения. При необходимости пользователь может остановить выполнение преобразования, для этого в программе предусмотрим команду, которая бы сбрасывала флаг m_EventDoTransform. При сбросе этого флага цикл выполнения преобразования СВМDос::ТгаnsformLoop() прерывается, потоковая функция завершается и рабочий поток прекращает свое существование.

3.5 Класс “Фильтр”

Выполнение задачи подразумевает существование в программе некоторого объекта-фильтра. Фильтры выполняют разные преобразования, но с точки зрения "фильтрации" они все одинаковы и обращаться с ними она будет единообразно. Поэтому нам надо определить базовый класс CFilter для фильтра с минимальным, но основным набором методов, с помощью которых будет происходить общение. Данные класса - два указателя на объекты-картинки класса Craster:

- m_рSourseBM - адрес объекта "исходная картинка", откуда берутся данные для преобразования;

- m_рDestBM - адрес объекта "приемная картинка", куда помещаются преобразованные данные.

Методы класса:

- SetBuffers () - сообщает фильтру адреса исходного и приемного изображения;

- TransformPix() – преобразует данные одного пиксела с координатами (x,y).

Переменная-указатель на этот класс m_pCurFilter заведена в классе CBMDoc. Этой переменной присваивается адрес текущего фильтра.

Для реализации точечных методов преобразования создаём класс CdotFilter (Листинг 3.7.1).

Листинг 3.7.1 – Базовый класс для точечных фильтров CdotFilter. Файл Filter.h

//Базовый класс для точечных фильтров

class CDotFilter: public CFilter

{

protected:

//Таблицы преобразования для компонентов цвета

BYTE BGRTransTable[3][256];

public:

//Метод преобразования пиксела

BOOL TransformPix(LONG x, LONG y);};

Данными этого класса являются три таблицы преобразования компонентов RGB цвета.

Для точечного фильтра переопределён метод . Реализация метода приведена в листинге 3.7.2

Листинг 3.7.2 – Метод CDotFilter:: TransformPix (). Файл Filter.cpp

BOOL CDotFilter::TransformPix(LONG x, LONG y)

{BYTE *pDPix=NULL, *pSPix=NULL;

// Источник необходим

if(m_pSourceBM==NULL)

return FALSE;

//Если приёмник не задан, то преобразование помещаем в источник

if(m_pDestBM==NULL)

m_pDestBM=m_pSourceBM;

// Получаем указатели на пикселы в источнике и приёмнике

if((pDPix=m_pDestBM->GetPixPtr(x, y))==NULL ||

(pSPix=m_pSourceBM->GetPixPtr(x, y))==NULL)

return FALSE;

// Преобразование. Порядок BGR

*pDPix=BGRTransTable[0][*pSPix];

*(pDPix+1)=BGRTransTable[1][*(pSPix+1)];

*(pDPix+2)=BGRTransTable[2][*(pSPix+2)];

return TRUE; };

Хотя формат 24-битового цвета называют RGB, в файле формата BMP компоненты цвета хранятся в обратном порядке (Порядок BGR).

В производных от CDotFilter классах останется реализовать инициализацию таблиц преобразования.

Для реализации пространственных (матричных) методов преобразования создаём класс CMatrixFilter. Интерфейс класса приведён в листинге 3.7.3

Листинг 3.7.3 – Интерфейс базового для матричных фильтров класса CmatrixFilter. Файл Filter.h

// Пространственные (матричные фильтры)

// Базовый класс

class CMatrixFilter: public CFilter

{

protected:

int m_rangX; // размер матрицы по X и Y

int m_rangY;

const int *m_pMatrix; // указатель на матрицу

public:

//Методпреобразования пиксела

BOOL TransformPix(LONG x, LONG y); };

Данными этого класса являются размер матрицы преобразования и указатель на матрицу. Размер мртрицы определяет зону пикселов, окружающих пиксел (x,y), которая будет вовлечена в расчёт нового значения пиксела (x,y). Указателю на матрицу преобразования m_pMatrix будет присваиваться адрес матрицы, которая будет использована в преобразовании. Реализация метода CmatrixFilter:: TransformPix() приведена в листинге3.7.4

Листинг 3.7.4 – Метод CmatrixFilter:: TransformPix(). Файл Filter.cpp

// Пространственные фильтры

BOOL CMatrixFilter::TransformPix(LONG x, LONG y)

{BYTE *pDPix=NULL, *pSPix=NULL;

// Источник и приёмник необходимы

if(m_pSourceBM==NULL || m_pDestBM==NULL)

return FALSE;

// Определяем зону перекрытия изображения и матрицы. Это требуется для //обработки пикселов, находящихся на границах изображения

int x_start=0;

int dx=m_rangX/2, dy=m_rangY/2;

if(x-dx<0) x_start=dx-x;

int y_start=0;

if(y-dy<0) y_start=dy-y;

int x_finish=m_rangX;

if(x+dx>m_pSourceBM->GetBMWidth())

x_finish-=(x+dx-m_pSourceBM->GetBMWidth());

int y_finish=m_rangY;

if(y+dy>m_pSourceBM->GetBMHeight())

y_finish-=(y+dy-m_pSourceBM->GetBMHeight());

// Расчёт новых значений цвета пиксела с учётом соседей, попавших в зону //действия матрицы преобразования

int NewBGR[3];

int count=0;

for(int c=0, mx=0, my=0; c<3; c++)

{NewBGR[c]=0; count=0;

for(my=y_start; my

for(mx=x_start; mx

{if((pSPix=m_pSourceBM->GetPixPtr(x+(mx-dx), y+(my-dy)))!=NULL)

{NewBGR[c]+=(m_pMatrix[my*m_rangX+mx]*(*(pSPix+c)));

count+=m_pMatrix[my*m_rangX+mx]; }}}

// Адрес пиксела в изображении-приёмнике

pDPix=m_pDestBM->GetPixPtr(x, y);

//Установка нового значения в приёмное изображение

for(c=0; c<3; c++)

{

// Приведение значения к допустимому диапазону

if(count!=0)

NewBGR[c]=NewBGR[c]/count;

if(NewBGR[c]<0)

NewBGR[c]=0;

else if(NewBGR[c]>255)

NewBGR[c]=255;

*(pDPix+c)=NewBGR[c]; }

return TRUE; };

В методе CmatrixFilter:: TransformPix() сначала определяется область перекрытия изображения и матрицы преобразования. Этот шаг необходим в связи с тем, что на границах изображения пиксел может не иметь соседей.

Новое значение пиксела формируется с учетом значений всех пикселов и коэффициентов матрицы преобразования, попавших в область перекрытия изображения и матрицы преобразования.

3.6 Фильтр “Яркость/Контраст”

Изменение яркости заключается в изменении интенсивности цвета всех пикселов на заданное значение. Данное преобразование является точечным. Для его реализации добавим в программу класс CBrightCont, производный от класса CDotFilter. Интерфейс класса приведён в листинге 3.6.1

Листинг 3.6.1 – Интерфейс класса CBrightCont. Файл Filter.h

// Яркость/контраст

class CBrightCont: public CDotFilter

{

public:

BOOL Init(int b_offset, int c_offset);

};

Переменные b_offset, c_offset – это объекты, связанные с ползунками, могут принимать положительные и отрицательные значения, что соответствует увеличению или уменьшению яркости/контрастности изображения.

Реализация метода CBrightCont::Init() приведена в листинге 3.6.2 Этот метод инициализирует таблицы преобразования. Сначала выполняется смещение яркости на заданную величину, а затем либо "сжатие", либо "растяжение" диапазона яркости. Причем при сжатии значения яркости изменяются не равномерно, а пропорционально их удаленности от "серой середины", определенной константой CONTRAST_MEDIAN. После преобразования яркости работа по коррекции контрастности происходит со значениями таблицы преобразования, полагая при этом, что они являются индексами в таблице, полученной после коррекции яркости.

Листинг 3.6.2 – Метод CBrightCont::Init().Файл Filter.cpp

// "Серая середина" –уровень 159

#define CONTRAST_MEDIAN 159

BOOL CBrightCont::Init(int b_offset, int c_offset)

{int i=0,//Индекс цвета в таблице преобразований

t=0,//Индекс таблицы

//Индекс цвета, соответствующего нижней границе яркости

t_index=0,

// Индекс цвета, соответствующего верхней границе яркости

b_index=0,

value_offset; //Смещение значения цвета

double value=0.; //Новое значение цвета

//Изменяем яркость

for(i, t=0; t<3; t++)

for(i=0; i<256; i++)

{if(i+b_offset>255) BGRTransTable[t][i]=255;

else if(i+b_offset<0) BGRTransTable[t][i]=0;

else BGRTransTable[t][i]=i+b_offset; }

// Изменяем контрастность

if(c_offset<0)// Уменьшаем контрастность

{for(i=0, t=0; t<3; t++)

for(i=0; i<256; i++)

if(BGRTransTable[t][i]

{

//Рассчитываем смещение в зависимости от удалённости цвета от “серой середины”

value_offset=(CONTRAST_MEDIAN-BGRTransTable[t][i])*c_offset/128;

if(BGRTransTable[t][i]-value_offset>CONTRAST_MEDIAN) BGRTransTable[t][i]=CONTRAST_MEDIAN;

else BGRTransTable[t][i]-=value_offset; }

else

{

// Рассчитываем смещение в зависимости от удалённости цвета от “серой середины”

value_offset=(BGRTransTable[t][i]-CONTRAST_MEDIAN)*c_offset/128;

if(BGRTransTable[t][i]+value_offset

else BGRTransTable[t][i]+=value_offset; }

}

elseif(c_offset>0)

//Увеличиваем контрастность

{ //Расчёт нижней границы цвета

int offset_b=c_offset*CONTRAST_MEDIAN/128;

//Все значения в таблице ниже нижней границы получат значения 0

for(t=0; t<3; t++)

for(b_index=0; b_index<256; b_index++)

{ if(BGRTransTable[t][b_index]

BGRTransTable[t][b_index]=0;

else break; }

// Расчёт верхней границы цвета

int offset_t=c_offset*128/CONTRAST_MEDIAN;

// Все значения в таблице ниже нижней границы получат значения 255

for(t=0; t<3; t++)

for(t_index=255; t_index>=0; t_index--)

{ if(BGRTransTable[t][t_index]+offset_t>255)

BGRTransTable[t][t_index]=255;

else break; }

//Расчёт шага изменения интенсивности цвета

double step=256./(256-(offset_b+offset_t));

// "Растягиваем" интенсивность цветов между нижней и верхней //границами до диапазона 0-255

for(t=0; t<3; t++)

{ value=0.;

for(i=b_index; i<=t_index; i++)

{ if(BGRTransTable[t][i]>=offset_b || BGRTransTable[t][i]<256- offset_t)

{value=(int)((BGRTransTable[t][i]-offset_b)*step+0.5);

if(value>255) value=255;

BGRTransTable[t][i]=(int)(value); }}}}

return TRUE; };

3.7 Фильтр “Инверсия”

Этот фильтр реализуется с помощью таблицы преобразований. Для его реализации добавим в программу класс CInvertColors (листинг 3.7.1), производный от класса CDotFilter.

Листинг 3.7.1 – Интерфейс класса CInvertColors.Файл Filter.h

//Инверсия цветов

class CInvertColors: public CDotFilter

{

public:

CInvertColors(); };

Операция инверсии цветов не требует никаких настроечных параметров, поэтому инициализация таблиц преобразования выполняется в конструкторе класса (листинг 3.7.1).

Листинг 3.7.1 – Конструктор класса CInvertColors .Файл Filter.cpp

CInvertColors::CInvertColors()

{for(int i=0, t=0; t<3; t++)

for(i=0; i<256; i++)

{BGRTransTable[t][i]=255-i; }

};

3.8 Фильтр “Размытие”

Фильтр "Размытие" - это уже пространственное преобразование. Применение этого фильтра оказывает эффект сглаживания деталей изображения. Фильтр реализуется классом CВlur (листинг 3.8.1)

Листинг 3.8.1 – Интерфейс класса CBlur. Файл Filter.h

class CBlur: public CMatrixFilter

{public:

CBlur();

};

Листинг 3.8.2 – Конструктор класса CBlur.Файл Filter.cpp

const int BlurMatrix[25]=

{1,1,1, 1,1,

1,1,1, 1,1,

1,1,1, 1,1,

1,1,1, 1,1,

1,1,1, 1,1

};

CBlur::CBlur()

{m_pMatrix=BlurMatrix;

m_rangX=5;

m_rangY=5; };

Матрица BlurMatrix задаёт преобразование “Размытие”, а в конструкторе CBlur() запоминается её адрес и размер.

3.9 Фильтр “Резкость”

Для повышения четкости изображения в фильтре используется матрица "Размытие". Задача повышения четкости изображения заключается в том, чтобы выделить высокочастотные детали изображения. Светлые детали сделать ярче, темные - темнее. Для этого изображение сначала размывается, а затем определяется разность между размытым изображением и оригиналом. На величину этой разницы изменяется яркость оригинала. Таким образом, однородные участки изображения не подвергнутся изменениям, а те места картинки, где присутствуют высокочастотные детали, станут конрастнее. Фильтр реализуется классом CSharp (листинг 3.9.1).

Листинг 3.9.1 – Интерфейс класса CSharp. Файл Filter.h

class CSharp: public CMatrixFilter

{ public:

CSharp();

BOOL TransformPix(LONG x, LONG y); };

В классе CSharp переопределён метод TransformPix(), реализация метода приведена в листинге 3.9.1.

Листинге 3.9.1 – Методы класса CSharp. Файл Filter.cpp.

CSharp::CSharp()

{ m_pMatrix=BlurMatrix;

m_rangX=5;

m_rangY=5; };

// коэффициент увеличения резкости

#define SHARP_COEFF 3

BOOL CSharp::TransformPix(LONG x, LONG y)

{ //Размыли пиксел

if(!CMatrixFilter::TransformPix(x, y))

return FALSE;

BYTE *pDPix=NULL, *pSPix=NULL;

pSPix=m_pSourceBM->GetPixPtr(x,y);

pDPix=m_pDestBM->GetPixPtr(x, y);

int d=0;

for(int c=0; c<3; c++)

{ // Нашли разницу

d=*(pSPix+c)-*(pDPix+c);

// Усилили разницу

d*=SHARP_COEFF;

Характеристики

Тип файла
Документ
Размер
11,69 Mb
Учебное заведение
Неизвестно

Список файлов ВКР

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6525
Авторов
на СтудИзбе
301
Средний доход
с одного платного файла
Обучение Подробнее