Работа с изображениями
Существует множество графических форматов - bmp, pcx, gif, jpeg и прочие. OpenGL напрямую не поддерживает не один из них. В OpenGL нет функций чтения/записи графических файлов. Но поддерживается работа с массивами пикселей. Вы загружаете графический файл, используя библиотеки других фирм, в память и работаете с ними средствами OpenGL. В массиве данные о пикселах могут располагаться разными способами: RGB, BGR, RGBA; могут присутствовать не все компоненты; каждый элемент массива может занимать один байт, два, четыре или восемь; выравнивание может быть по байту, слову или двойному слову. В общем, форматов расположения данных о графическом изображении в памяти очень много. Я рассмотрю один из них, наиболее часто применяемый, как мне кажется. Информация о каждом пикселе хранится в формате RGB и занимает три байта, выравнивание по байту. В Auxiliary Library есть функция auxDIBImageLoad(LPCSTR), которая загружает в память bmp-файл и возвращает указатель на структуру:
typedef struct _AUX_RGBImageRec { GLint sizeX, sizeY; unsigned char *data; } AUX_RGBImageRec;
Для простоты я буду пользоваться именно этой функцией. Среди прилагаемых программ вы найдете мою утилиту для загрузки файлов из форматов pcx. Исходный текст этой утилиты абсолютно переносим на любую платформу с компилятором ANSI C.
В OpenGL имеются функции для вывода массива пикселей на экран(glDrawPixels), копирования(glCopyPixels), масштабирования(gluScaleImage). Здесь мы рассмотрим только glDrawPixels. Все остальные функции работы с изображениями устроены похожим образом. Для того, чтобы отобразить графический файл в окне OpenGL, вы должны загрузить его в память, указать выравнивание, установить точку, с которой начинается вывод изображения, и вывести его на экран. Раздобудьте где-нибудь свою фотографию в формате BMP. Можете взять фотографию своей девушки. Создайте новый проект. Объявите глобальную переменную -
AUX_RGBImageRec *image Перед вызовом функции auxMainLoop в функции main вставьте строку:
image = auxDIBImageLoad("photo.bmp");
Выравнивание устанавливается вызывом функции glPixelStorei с параметром GL_UNPACK_ALIGNMENT и вторым параметром - целым числом, которое указывает выравнивание. Изображения выводятся прямо на экран. Поэтому все происходит в двухмерных координатах. Позиция, с которой начинается вывод изображения, указывается при помощи функции glRasterPos2d(x,y). Также вы можете установить размер пикселя, вызвав функцию glPixelZoom. Первый параметр этой функции - ширина, второй - высота пикселя. Я вызываю эту функцию с аргументами (1,1), что соответствует нормальному пикселю. Замените (1,1) на (3,2) и вы увидите, как картинка растянется в три раза по горизонтали и в два раза по вертикали. Это случилось, потому что теперь каждый пиксель изображения соответствует прямоугольнику 3х2 в окне. И наконец, вывод осуществляет функция glDrawPixels. Первые два параметра - это ширина и высота. Далее, вы указываете формат, в котором хранится информация в памяти, и тип элементов массива. Последним указывается массив данных. В функцию display вставьте следующий код:
glRasterPos2d(-4.5,-3); // нижний левый угол glPixelZoom(1,1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // выравнивание glDrawPixels(image->sizeX, image->sizeY, // ширина и высота GL_RGB, GL_UNSIGNED_BYTE, // формат и тип image->data); // сами данные
Также в OpenGL имеется функция glBitmap для отображения битовых массивов. Битовый массив - это последовательность байт, которые кодируют картинку из двух цветов. Соответственно, каждый байт кодирует 8 пикселей. Среди прилагаемых программ вы найдете мою утилиту pcx_2bpp. Она читает pcx-файл формата один бит на пиксель и направляет на стандартный вывод массив на языке Си.
Исходный файл смотрите . Исполняемый файл . Моя фотография .