Смекни!
smekni.com

Разработка программного обеспечения для фильтрации растровых изображений (стр. 4 из 6)

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

Листинг 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]<CONTRAST_MEDIAN)

{

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

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<CONTRAST_MEDIAN) BGRTransTable[t][i]=CONTRAST_MEDIAN;

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]<offset_b)

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;

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

if(*(pDPix+c)+d <0)

*(pDPix+c)=0;

else

if(*(pDPix+c)+d > 255)

*(pDPix+c)=255;

else

*(pDPix+c)+=d;}

return TRUE; }


4. ИНСТРУКЦИЯ ПОЛЬЗОВАТЕЛЯ

Запуск программы осуществляется при открытии файла BMViewer.exe. На экране появляется окно, представленное на рисунке 4.1.