Chapter 5
Работа с картинками
5.2 Работа с изображениями
Существует множество графических форматов - 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-файл
формата один бит на пиксель и направляет на стандартный вывод массив на языке Си.
Исходный файл смотрите здесь.
Исполняемый файл здесь.
Моя фотография здесь.
|