Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

RedBook_OpenGL

.pdf
Скачиваний:
702
Добавлен:
02.04.2015
Размер:
7 Мб
Скачать
☆

Цветовые таблицы задаются тем же образом, что и одномерные изображения. Как показано на рисунке 8-15, существует 3 цветовые таблицы для изменения цветовых величин, и все они задаются командой glColorTable().

void glColorTable (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data);

Если target равно GL_COLOR_TABLE, GL_POST_CONVOLUTION_COLOR_TABLE или

GL_POST_COLOR_MATRIX_COLOR_TABLE, настраивает соответствующую цветовую таблицу, а если GL_PROXY_COLOR_TABLE, GL_PROXY_POST_CONVOLUTION_COLOR_TABLE или GL_ PROXY_POST_COLOR_MATRIX_COLOR_TABLE – проверяет, что заданная цветовая таблица может быть размещена в доступных ресурсах. Аргумент internalFormat используется, чтобы указать внутреннее представление данных в OpenGL. Он может принимать следующие символические значения – GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16, GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, GL_LUMINANCE12, GL_LUMINANCE16, GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_8ALPHA8, GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12, GL_LUMINANCE16_ALPHA16, GL_INTENSITY, GL_INTENSITY4, GL_INTENSITY8, GL_INTENSITY12, GL_INTENSITY16, GL_RGB, GL_R3_G3_B2, GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10, GL_RGB12, GL_RGB16, GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGBA12, GL_RGBA16. Параметр width, который должен быть степенью 2, индицирует количество пикселей в цветовой таблице. Аргументы format и type описывают формат и тип данных цветовой таблицы. Они имеют такое же значение, как и эквивалентные параметры команды glDrawPixels().

Внутренний формат таблицы определяет то, какие компоненты пикселей изображения будут заменены. Например, если вы задаете GL_RGB в качестве формата, то красный,

зеленый и синий компоненты каждого входящего пикселя будут искаться в соответствующей цветовой таблице и заменяться значениями оттуда. Таблица 8-8 описывает, какие компоненты пикселей будут заменяться при различных внутренних форматах.

Таблица 8-8 Замена значений пикселей цветовой таблицей

Базовый внутренний

Красный

Зеленый

Синий

Альфа

формат

компонент

компонент

компонент

компонент

GL_ALPHA

не изменяется

не изменяется

не изменяется

 

GL_LUMINANCE

 

 

 

не изменяется

GL_LUMINANCE_ALPHA

 

 

 

 

GL_INTENSITY

 

 

 

 

GL_RGB

 

 

 

не изменяется

GL_RGBA

 

 

 

 

 

 

 

 

 

В таблице 8-8 величины представляют собой светлоту в цветовой таблице, которая

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

После того как таблица была применена к изображению, пиксели могут быть смасштабированы и скошены, после чего, их значения приводятся к диапазону [0; 1].

Факторы GL_COLOR_TABLE_SCALE и GL_COLOR_TABLE_BIAS для каждой таблицы устанавливаются с помощью команды glColorTableParameter*().

void glColorTableParameter{if}v (GLenum target, GLenum pname, TYPE *param);

Устанавливаетпараметры GL_COLOR_TABLE_SCALE и GL_COLOR_TABLE_BIAS для каждой таблицы. target может быть равно GL_COLOR_TABLE, GL_POST_CONVOLUTION_COLOR_TABLE или GL_POST_COLOR_MATRIX_COLOR_TABLE и

задает целевую таблицу, для которой устанавливаются параметры. Возможными значениями для pnamee являются GL_COLOR_TABLE_SCALE и GL_COLOR_TABLE_BIAS.

Величина param указывает на массив из 4-ех величин, представляющих, соответственно, модификаторы для красного, зеленого, синего и альфа компонент.

Пример 8-5 показывает, как изображение может быть инвертировано посредством цветовой таблицы. Таблица настраивается таким образом, чтобы она заменяла каждый цвет на его инверсию. Пример инвертированного цветовой таблицей изображения приведен на рисунке 8-16.

Рисунок 8-16. Исходное изображение айсберга (слева) и то же изображение, инвертированное с помощью цветовой таблицы (справа))

Пример 8-5. Замена пикселей с использованием цветовой таблицы: файл colortable.cpp

#include <glut.h> #include <GL/glaux.h> #include "glext.h"

//Массив для исходного изображения

AUX_RGBImageRec *image;

//Тип и указатель для функции цветовой таблицы (EXTENSION) typedef void (APIENTRY * GLCOLORTABLE)

(GLenum target,GLenum internalFormat,GLsizei width, GLenum format, GLenum type, const GLvoid *data);

GLCOLORTABLE glColorTable=NULL;

void init()

{

int i;

GLubyte colorTable[256][3];

//Загрузить исходное изображение из 24-разрядного файла BMP

//(библиотека GLAUX) image=auxDIBImageLoad("peak.bmp");

//Получить адрес функции цветовой таблицы

//с помощью функции специфической для реализации OpenGL для

Windows glColorTable=(GLCOLORTABLE)wglGetProcAddress("glColorTable");

if (glColorTable==NULL)

{

MessageBox(NULL, "Function [glColorTable] from [GL_ARB_imaging] extension not supported!",

"Pixel Replacement Using Color Tables", MB_OK|MB_ICONSTOP);

exit(1);

}

glPixelStorei(GL_UNPACK_ALIGNMENT,1); glClearColor(0,0,0,0);

//Инвертирующая цветовая таблица for(i=0;i<256;++i)

{

colorTable[i][0]=255-i; colorTable[i][1]=255-i; colorTable[i][2]=255-i;

}

glColorTable(GL_COLOR_TABLE,GL_RGB,256, GL_RGB,GL_UNSIGNED_BYTE,colorTable);

glEnable(GL_COLOR_TABLE);

}

void deinit()

{

//Очислитьпамять delete image;

}

void reshape(int w, int h)

{

glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,500,0,500);

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT); glRasterPos2i(1,1); glDrawPixels(image->sizeX, image->sizeY,

GL_RGB,GL_UNSIGNED_BYTE,image->data);

glFlush();

}

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE

hPrevInstance,

LPSTR

lpCmdLine,

int

nCmdShow)

{

 

char* argv="";

 

int argc=0;

 

glutInit(&argc,&argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(540,405);

glutCreateWindow("Pixel Replacement Using Color Tables"); init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMainLoop();

deinit(); return 0;

}

Замечание: Поскольку загрузка изображения должна производиться способом, зависящим от вашей оконной системы, а также потому, что в GLUT нет подобных функций, в данном примере используется функция auxDIBImageLoad() из библиотеки GLAUX для Windows.

Вместо того, чтобы задавать цветовую таблицу непосредственно из вашего приложения, вам может понадобиться использовать в качестве нее изображение, созданное в буфере кадра. Команда glCopyColorTable() позволяет вам задать ряд пикселей, которые считываются из буфера кадра и используются в качестве цветовой таблицы.

void glCopyColorTable (GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width);

Создает цветовую таблицу, используя данные из буфера кадра в качестве данных для цветовой таблицы. Пиксели считываются из текущего буфера для чтения (GL_READ_BUFFER) и обрабатываются так же как при вызове glCopyPixels(), но без последней конверсии. Учтите, что производятся также операции, заданные glPixelTransfer*(). Параметры target и internalFormat имеют то же значение, что и для glColorTable(). Цветовой массив будет состоять из width пикселей вправо, начиная с (x, y) буфера кадра.

8.2.5.1.2Замена всей цветовой таблицы или ее части

Если вам требуется заменить часть цветовой таблицы, вы можете загрузить ее секцию с помощью команд glColorSubTable() и glCopyColorSubTable().

void glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);

Заменяет вхождения [start;start+count-1] цветовой таблица на величины, находящиеся в data. Параметр target может принимать значения GL_COLOR_TABLE, GL_POST_CONVOLUTION_COLOR_TABLE, GL_POST_COLOR_MATRIX_COLOR_TABLE.

Параметры format и type идентичны соответствующим параметрам glColorTable().

void glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei count);

Заменяет вхождения [start;start+count-1] цветовой таблица на countцветовых величин пикселей из ряда буфера кадра, начинающегося с позиции (x; y). Пиксели конвертируются в internalFormat оригинальной таблицы.

8.2.5.1.3Запрос величин цветовых таблиц

Величины пикселей, сохраненные в цветовой таблице, могут быть получены с помощью команды glGetColorTable().

8.2.5.1.4Проверка цветовых таблиц

Прокси цветовых таблиц позволяют заставить OpenGL выяснить, достаточно ли в системе ресурсов для размещения вашей цветовой таблицы. Если glColorTable() вызывается с одним из следующих аргументов:

∙GL_PROXY_COLOR_TABLE

∙GL_PROXY_POST_CONVOLUTION_COLOR_TABLE

∙GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE

OpenGL проверяет, есть ли ресурсы для размещения соответствующей таблицы. Если таблица не влезает, ее величины width, format и type устанавливаются в 0. Если вы хотите выяснить, достаточно ли ресурсов – проверьте одну из этих величин. Например, так:

glColorTable(GL_PROXY_COLOR_TABLE, GL_RGB, 1024, GL_RGB, GL_UNSIGNED_BYTE, NULL);

glGetColorTableParameteriv(GL_PROXY_COLOR_TABLE, GL_COLOR_TABLE_WIDTH, &width);

if(width==0)

/*цветовая таблица не умещается*/

8.2.5.2Весовые модификаторы

Весовые модификаторы (convolutions) работают в качестве фильтров, заменяя каждый

пиксель изображения на взвешенное среднее соседствующих с ним пикселей и его самого. Размытие изображения, нахождение ребер и изменение контраста являются примерами применения весовые модификаторы.

На рисунке 8-18 показано, как пиксель и соседние с ним обрабатываются весовым модификатором размера 3x3 для получения пикселя .

Рисунок 8-17. Операция пиксельной фильтрации

Весовые модификаторы – это массивы весов пикселей, и работают они только на RGBA пикселях. Фильтр, также известный как kernel, является простым двумерным массивом весов. Каждый пиксель изображения – результата создается умножением группы

входящих пикселей на весовые коэффициенты фильтра и суммированием

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

void glConvolutionFilter2D (GLenum target,GLenum internalFormat,GLsizei width,GLsizei height,

GLenum format,GLenum type,const GLvoid *image);

Задает двумерный фильтр. Параметр filter должен быть равен GL_CONVOLUTION_3D. internalFormat задает, над какими компонентами пикселей будет производиться фильтрация и может принимать одно из 38 значений, перечисленных для аргумента internalFormat команды glColorTable(). Аргументы width и height задают размеры

фильтра в пикселях. Максимальная ширина и высота для фильтров может быть получена с помощью команды glGetConvolutionParameter*(). Как и в случае glDrawPixels(), аргументы format и type задают формат пикселей, сохраненных в массиве, на который указывает image.

Как и для цветовых таблиц, внутренний формат фильтра определяет то, с какими компонентами пикселей требуется работать. Таблица 8-9 описывает, как различные

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

GL_LUMINANCE, а -- величину интенсивности фильтра GL_INTENSITY. Наконец, , , и представляют красный, зеленый, синий и альфа компоненты фильтра.

Таблица 8-9. Влияние фильтров на RGBA компоненты пикселей

Базовый формат

Результат по

Результат по

Результат по

Результат по

красному

зеленому

синему

альфа

фильтра

компоненту

компоненту

компоненту

компоненту

 

GL_ALPHA

не изменяется

не изменяется

не изменяется

 

GL_LUMINANCE

 

 

 

не изменяется

GL_LUMINANCE_ALPHA

 

 

 

 

GL_INTENSITY

 

 

 

 

GL_RGB

 

 

 

не изменяется

GL_RGBA

 

 

 

 

 

 

 

 

 

Чтобы активизировать 2D фильтрацию, используйте glEnable (GL_CONVOLUTION_2D).

Пример 8-6 демонстрирует использование нескольких 2D фильтров GL_LUMINANCE размером 3x3 для поиска ребер в RGBизображении. Клавиши ‘h’, ‘v’ и ‘l’ переключают режимы.

Результат работы программы можно увидеть на рисунке 8-18 (яркость и контрастность изображений увеличена для наглядности). Слева вверху находится исходное изображение пирамиды, справа вверху – то же изображение, обработанное фильтром, позволяющим обнаружить горизонтальные ребра, внизу слева – похожий фильтр, но на этот раз вертикальный, справа внизу – изображение обработанное фильтром Лапласа.

Рисунок 8-18. Пример обработки изображения двумерным фильтром для обнаружения

ребер

Пример 8-6. Использование двумерных фильтров: файл convolution.cpp

#include <windows.h> #include <glut.h> #include <GL/glaux.h> #include "glext.h"

//Указатель на память, где будет содержаться картинка

AUX_RGBImageRec *image;

//Определить фильтры

GLfloat horizontal[3][3]={{0,-1,0},{0,1,0},{0,0,0}}; GLfloat vertical[3][3]= {{0,0,0},{-1,1,0},{0,0,0}}; GLfloat laplacian[3][3]= {{-0.125,-0.125,-0.125},

{-0.125,1,-0.125}, {-0.125,-0.125,-0.125}};

//Тип и указатель для фильтра (если конечно расширение поддерживается)

typedef void (APIENTRY * GLCONVOLUTIONFILTER2D)

(GLenum target,GLenum internalFormat,GLsizei width, GLsizei height,GLenum format, GLenum type, const GLvoid

*data);

GLCONVOLUTIONFILTER2D glConvolutionFilter2D=NULL;

void init()

{

//Проверяем, присутствует ли расширение GL_ARB_imaging (imaging subset)

if (glutExtensionSupported("GL_ARB_imaging")==0)

{

MessageBox(NULL,"ARB_imaging extension not supported", "Using Two-Dimensional Convolution

Filters",MB_OK|MB_ICONHAND); exit(1);

}

//Получаем указатель на функцию расширения glConvolutionFilter2D=(GLCONVOLUTIONFILTER2D)

wglGetProcAddress("glConvolutionFilter2D");

//Загружаем любую непалитровую картинку BMP image=auxDIBImageLoad("peak.bmp"); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glClearColor(0,0,0,0);

}

void deinit()

{

//Освобождаемпамять delete image;

}

void keyboard(unsigned char key, int x, int y)

{

switch(key)

{

case 'h':

MessageBox(NULL,"Using horizontal filter", "Using Two-Dimensional Convolution

Filters",MB_OK);

glConvolutionFilter2D(GL_CONVOLUTION_2D,GL_LUMINANCE,3,3,

GL_LUMINANCE,GL_FLOAT,horizontal); glEnable(GL_CONVOLUTION_2D); break;

case 'v':

MessageBox(NULL,"Using vertical filter", "Using Two-Dimensional Convolution

Filters",MB_OK);

glConvolutionFilter2D(GL_CONVOLUTION_2D,GL_LUMINANCE,3,3,

GL_LUMINANCE,GL_FLOAT,vertical); glEnable(GL_CONVOLUTION_2D); break;

case 'l':

MessageBox(NULL,"Using laplacian filter", "Using Two-Dimensional Convolution

Filters",MB_OK);

glConvolutionFilter2D(GL_CONVOLUTION_2D,GL_LUMINANCE,3,3,

GL_LUMINANCE,GL_FLOAT,laplacian); glEnable(GL_CONVOLUTION_2D); break;

case 'r':

MessageBox(NULL,"No filter used", "Using Two-Dimensional Convolution

Filters",MB_OK);

glDisable(GL_CONVOLUTION_2D);

break; case 27:

exit(0);

}

glutPostRedisplay();

}

void reshape(int w, int h)

{

glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,540,0,405);

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT); glRasterPos2i(1,1); glDrawPixels(image->sizeX,image->sizeY,GL_RGB,

GL_UNSIGNED_BYTE,image->data);

glFlush();

}

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE

hPrevInstance,

LPSTR

lpCmdLine,

int

nCmdShow)

{

 

char* argv=""; int argc=0;

glutInit(&argc,&argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(540,405);

glutCreateWindow("Using Two-Dimensional Convolution Filters"); init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutKeyboardFunc(keyboard);

glutMainLoop();

deinit(); return 0;

}

Как и в случае с цветовыми таблицами, вы можете задать фильтр с помощью пиксельных величин, взятых из буфера кадра. Команда glCopyConvolutionFilter2D() копирует прямоугольник пикселей из текущего буфера для чтения (GL_READ_BUFFER) для использования в качестве данных фильтра. Если в качестве внутреннего формата используется GL_LUMINANCE или GL_INTENSITY, то в качестве величин фильтра берутся красные компоненты пикселей.

void glCopyConvolutionFilter2D (GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height);

Задает двумерный фильтр, инициализируя его пикселями из цветового буфера кадра. Аргумент target должен иметь значение GL_CONVOLUTION_2D, а internalFormat должен быть установлен в одно из значений, допустимых для glConvolutionFilter2D().

Прямоугольник пикселей с левым нижним углом в точке (x; y) и размерами width и height считывается из буфера кадра и конвертируется в internalFormat.

8.2.5.2.1Разделяемые двумерные фильтры

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]