на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Разработка программного обеспечения для фильтрации растровых изображений
p align="left">Реализуем на практике второй способ организации "фильтрации". При этом сам процесс преобразования изображения вынесем в отдельный поток (назовем его "рабочим" потоком) выполнения программы. Это даст нам возможность контролировать не только область применения фильтра, но и продолжительность выполнения операции, т.е. возможность остановить выполнение "фильтрации". Общая схема преобразования в этом случае будет выглядеть следующим образом:

Пришла команда выполнить преобразование - создаем рабочий поток.

Уведомляем объекты-облики о том, что начали преобразование. Приэтом облик запускает таймер и начинает периодически интересоваться,сколько процентов работы выполнено, показывая пользователю процентвыполнения.

В рабочем потоке выполняется преобразование и увеличивается процент выполнения.

По окончании преобразования (или если пользователь прервал выполнение) в объекты-облики посылаются сообщения о завершении работы ипоказывается преобразованная картинка.

Поскольку данными в программе ВМViewer заведует класс CBMDoc, именно в него и поместим "фильтрацию". Для создания рабочего потока потребуется добавить в класс CBMDoc несколько методов:

Transform() - создает рабочий поток;

ThreadProc () - функция потока, запускает "фильтрацию" для конкретного объекта-документа;

TransformLoop() - сама "фильтрация";

InformAllViews() - передает сообщения всем обликам документа; Рассмотрим метод TransformLoop() (Листинг 3.6.1).

Листинг 3.6.1 - Метод CBMDoc::TransformLoop(). Файл BMDoc.cpp

void CBMDoc::TransformLoop()

{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; y<pSBM->GetBMHeight(); 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(; x<pSBM->GetBMWidth(); 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)

(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<y_finish; my++)

for(mx=x_start; mx<x_finish; 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. После преобразования яркости работа по коррекции контрастности происходит со значениями таблицы преобразования, полагая при этом, что они являются индексами в таблице, полученной после коррекции яркости.

Страницы: 1, 2, 3, 4, 5, 6



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.