Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Гущин_SDL.pdf
Скачиваний:
168
Добавлен:
17.03.2018
Размер:
1.09 Mб
Скачать

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

6. Работа с поверхностями в библиотеке SDL

Поверхности, представляемые в библиотеке SDL указателем на структуру SDL_Surface, используются при решении следующих задач:

непосредственного обеспечения отображения пикселей на мониторе (в полноэкранном режиме или в основном окне программы). Для этого в программе используется только одна поверхность, которая создается функцией SDL_SetVideoMode;

создания изображений на поверхности, не имеющей непосредственного отображения на мониторе;

загрузки в память (без отображения на мониторе) графи-ческих файлов в формате Windows BMP для их обработки (анализа и модификации) и последующего сохранения в файл (с помощью функций SDL_LoadBMP и SDL_SaveBMP);

создания изображений с помощью наложения их фрагментов (с помощью функции

SDL_BlitSurface).

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

Структура SDL_Surface, полное определение которой можно найти в заголовочном файле SDL_video.h, содержит в себе ряд полей, которые можно разделить на две группы: 1) для непосредственного доступа из программ, использующих библиотеку SDL, и 2) для доступа только самими функциями библиотеки SDL (приватные поля). Большинство полей из первой группы предназначены только для чтения (их изменение требует вызовов специальных функций библиотеки). При этом режим доступа к указателям в структуре распространяется и на все данные, доступные по этим указателям. Поскольку библиотека SDL написана на процедурном языке программирования C, не имеющем возможностей по сокрытию данных (инкапсуляции), фактически имеется доступ ко всем полям, несмотря на их разделение по группам. Но изменение полей, не предназначенных для изменения программистом-пользователем библиотеки (включая приватные поля), может приводить к непредсказуемым последствиям! Чтения данных приватных полей также следует избегать, поскольку их состав, структура и методы использования могут изменяться в каждой версии библиотеки без изменения ее документации. Приведем определение структуры, содержащей только публичные поля SDL_Surface (на основе документации к библиотеке SDL):

typedef struct SDL_Surface {

/* Поля только для чтения: */ Uint32 flags; /* Флаги поверхности. */

SDL_PixelFormat *format; /* Формат пикселей поверхности */ int w, h; /* Ширина и высота поверхности в пикселях */ Uint16 pitch; /* Число байт, соответствующих одной строке

поверхности в массиве байтов pixels*/

SDL_Rect clip_rect; /* Область обрезки (отсечения) – Используется для указания модифицируемой области при выполнении некоторых операций. Не может выходить за пределы поверхности. */

/* Поля, как правило, доступные только для чтения. Модификация требует понимания их роли в библиотеке: */

int refount; /* Счетчик ссылок –- используется при освобождении (удалении) поверхности */

/* Поля, предназначенные для программного изменения: */ void *pixels; /* Массив байтов, содержащий данные о

состоянии каждого пикселя, расположенные в соответствии с форматом пикселя поверхности */

/* Все остальные поля являются приватными. */

} SDL_surface;

30

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

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

Флаги поверхности – объединение с помощью побитовой операции ИЛИ значений отдельных флагов, установленных для данной поверхности. Они определяют расположение данных поверхности, ее предназначение, возможные способы использова-ния и интерпретацию ряда параметров поверхности в различных операциях. Часть флагов может устанавливаться при создании поверхности, часть флагов – только при создании функцией SDL_SetVideoMode поверхности для отображения на мониторе, а часть флагов устанавливается (или снимается) только в процессе выполнения отдельных специальных функций. Наличие у поверх-ности каждого конкретного флага можно проверить с помощью операции побитового И поля flags и значения конкретного флага. Сами значения флагов объявлены в заголовочном файле SDL_video.h как определения 32-разрядных шестнадцатеричных целых констант (директивой препроцессора #define). Приведем имена флагов, их назначение, а также области применения.

Флаги, передаваемые в параметре flags при вызове функций SDL_CreateRGBSurface и SDL_SetVideoMode:

SDL_SWSURFACE – поверхность (массив данных о состоянии пикселей) создается в общей памяти. Увеличивается производитель-ность операций с отдельными пикселями (как правило, не требуется блокировка поверхности), однако становятся недоступными некоторые возможности аппаратного наложения поверхностей.

SDL_HWSURFACE – поверхность (массив данных о состоянии пикселей), по возможности, создается в видеопамяти. Это позволяет библиотеке SDL использовать преимущества наложения поверх-ностей в видеопамяти, которое часто имеет аппаратное ускорение.

SDL_ASYNCBLIT – по возможности, используется асинхрон-ное обновление поверхности отображения (асинхронное наложе-ние поверхностей). Обычно уменьшает скорость на однопроцес-сорных (с одноядерными процессорами) компьютерах и может увеличивать на симметричных многопроцессорных (или с много-ядерными процессорами).

SDL_SRCOLORKEY – при наложении данной поверхности на другую пиксели, имеющие значение, равное значению format→colorkey, будут игнорироваться (рассматриваться как прозрачные). Точное поведение зависит от других параметров обеих поверхностей. Значение format→colorkey также часто назы-вают «ключевым цветом».

SDL_SRCALPHA – при наложении данной поверхности на дру-гую все пиксели рассматриваются как имеющие значение прозрач-ности, равное значению format→alpha (прозрачность поверхности). Точное поведение зависит от других параметров обеих поверх-ностей.

Флаги, передаваемые в параметре flags только при вызове функции SDL_SetVideoMode: SDL_ANYFORMAT – заставляет SDL непосредственно использовать поверхность

отображения, даже если запрошенная глубина цвета не поддерживается (выбирается ближайшая). Иначе создается «теневая» поверхность с запрошенной глубиной цвета, а при непосредственном отображении на монитор происходит прео-бразование цветов.

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

SDL_DOUBLEBUFF – разрешает двойную буферизацию для ускорения отображения. Необходима одновременная установка флага SDL_HWSURFACE.

SDL_FULLSCREEN – делается попытка использовать полно-экранный режим с заданным разрешением. Если он по какой-либо причине невозможен, то используется ближайшее большее раз-решение, а окно отображения с запрошенным разрешением раз-мещается в центре экрана на черном фоне.

SDL_RESIZEABLE – создается окно с возможностью измене-ния размера. При изменении размера окна пользователем генери-руется соответствующее событие, в обработчике которого должна быть повторно вызвана функция SDL_SetVideoMode с новым раз-мером окна.

SDL_NOFRAME – по возможности SDL создает окно без рам-ки и заголовка. При задании полноэкранного режима данный флаг устанавливается автоматически.

31

Флаги SDL_OPENGL и SDL_OPENGLBLIT применяются при совместном использовании библиотек SDL и OpenGL и в данном пособии не рассматриваются.

Независимо от флагов, переданных в параметре flags функций создания поверхности, поле flags структуры SDL_Surface содер-жит флаги, которые соответствуют ее фактическому состоянию.

Некоторые дополнительные флаги, описывающие состояние поверхности: SDL_HWACCEL – при наложении поверхностей используется аппаратное ускорение.

SDL_PREALLOC – поверхность использует массив данных о состоянии пикселей, созданный предварительно еще до ее созда-ния, и он не должен освобождаться при уничтожении поверхности (поверхность в данном случае не является владельцем массива данных о состоянии пикселей).

Поле формата пикселей поверхности описывается структурой SDL_PixelFormat, динамически создаваемой в процессе создания поверхности (конкретная создаваемая поверхность является владельцем динамически созданной структуры SDL_PixelFormat и при уничтожении поверхности автоматически будет освобождена и структура, на которую указывает поле формата пикселей). Непосредственное изменение ее содержания после создания поверхности не допускается. Она содержит следующие поля:

typedef struct SDL_PixelFormat {

SDL_Palette *palette; /* Указатель на палитру, или NULL,

если число бит на пиксель > 8. */

Uint8 BitsPerPixel; /* Глубина цвета в битах на пиксель. Обычные значения – 8, 16, 24 или 32. */

Uint8 BytesPerPixel; /* Сколько байт отводится для представления одного пикселя. Обычно от 1 до 4. */

Uint8 Rloss, Gloss, Bloss, Aloss; /* Потеря точности в каждом из цветовых каналов и канале прозрачности

(альфа-канале) – на 2 в какой степени нужно умножить представление значения компонента в данном канале, чтобы наименьшему значению соответствовал 0, а наибольшему – 255. */

Uint8 Rshift, Gshift, Bshift, Ashift; /* Сдвиг влево самого младшего бита представления значения каждого цветового канала и канала прозрачности. */

Uint32 Rmask, Gmask, Bmask, Amask; /* Битовая маска,

для выделения из представления атрибутов пикселя только битов, относящихся к данному цветовому каналу или каналу прозрачности, и принудительного обнуления остальных битов. */

Uint32 colorkey; /* Значение атрибута пикселя, которое при наложении данной поверхности на другую может позволить считать пиксель прозрачным, если установлен флаг SDL_SRCCOLORKEY. */

Uint8 alpha; /* Степень прозрачности для всей поверхности. Используется при наложении,

если установлен флаг SDL_SRCALPHA. 0 –- полностью прозрачная, 255 – полностью непрозрачная. */

} SDL_PixelFormat;

Поля данной структуры могут интерпретироваться различным способом в зависимости от используемой глубины цвета (поле BitsPerPixel). Если она равна 8 бит на пиксель, то каждый пиксель представляется ровно одним байтом, содержащим индекс в мас-сиве цветов в палитре (поле palette→colors). Элементами массива являются структуры SDL_color, поля r, g и b которой задают значения цветовых компонентов соответствующего цвета. Для изменения цветов в палитре служат функции SDL_SetPalette и SDL_SetColors, описание которых можно найти в документации. Если в формате пикселя используется палитра, то альфа-канал отсутствует.

Если используемая глубина цвета больше 8 бит на пиксель, то информация о цвете хранится непосредственно в атрибутах пик-селя, а не в палитре. Конкретное представление отдельных цветовых каналов в рамках атрибутов пикселя задается полями маски, сдвига и потери точности. При этом если маска альфа-канала Amask равна нулю, то он не используется. Поверхность, в

32

формате пикселей которой нет альфа-канала (нет индивидуального значения прозрачности каждого отдельного пикселя), в документации библиотеки SDL часто обозначается как RGB. Если же в формате пикселей поверхности присутствует альфа-канал (Amask > 0), то такие поверхности часто обозначаются в докумен-тации SDL как RGBA.

Для лучшего понимания представления различных компонен-тов в составе атрибутов пикселя приведем пример функции, выво-дящей в стандартный поток вывода значения отдельных полей формата пикселя указанной поверхности и значения отдельных каналов для пикселя с координатами (0, 0) на этой поверхности (на основе примера в документации к библиотеке SDL):

void printf_surface_pixelformat_data(SDL_Surface *surf)

{

SDL_PixelFormat *fmt; Uint32 temp, pixel;

Uint8 red, green, blue, alpha; fmt = surf->format;

printf("fmt->palette = %x\n", fmt->palette); printf("fmt->BitsPerPixel = %d\n", fmt->BitsPerPixel); printf("fmt->BytesPerPixel = %d\n", fmt->BytesPerPixel); printf("fmt->colorkey = %x\n", fmt->colorkey); printf("fmt->alpha = %x\n", fmt->alpha); SDL_LockSurface(surf);

pixel = *((Uint32*)surf->pixels); SDL_UnlockSurface(surf);

/* Получаем красный компонент: */

temp = pixel & fmt->Rmask; /* Выделяем егое по маске */ temp = temp >> fmt->Rshift; /* Сдвигаем влево до 8 бит */ temp = temp << fmt->Rloss; /* Расширяем до полного

8- разрядного числа. Если всего возможных значений компонента было менее 256, происходит их равномерное размещение между 0 и 255 домножением на 2 в степени Rloss*/

red = (Uint8)temp;

printf("fmt->Rmask = %x Rshift = %d Rloss = %d \n", fmt->Rmask, fmt->Rshift, fmt->Rloss);

/* Аналогичным образом получаем зеленый, синий компоненты и значение альфа-канала (если он есть), заменяя в именах переменных R на G, B и A соответственно и red – на green, blue и alpha. */

printf("Pixel (0,0) color -> R: %x, G: %x, B: %x, A: %x\n", red, green, blue, alpha);

}

Эта функция показывает, как можно с помощью описания формата получить полное представление о кодировании различ-ных компонентов в атрибутах пикселя конкретной поверхности как для построения значения атрибута пикселя по значениям отдельных компонентов, так и для решения обратной задачи – получения отдельных компонентов по значению атрибута пикселя. Для RGB-поверхностей первую задачу решает ранее рас-смотренная функция SDL_MapRGB, обратную задачу – функция SDL_GetRGB:

void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r, Uint8 *g, Uint8 *b);

Первый аргумент pixel – представление атрибута пикселя, рассматриваемое в соответствии с указанным вторым аргументом fmt – форматом пикселя. Полученные в результате отдельные компоненты сохраняются в памяти по адресам, заданным третьим, четвертым и пятым параметрами r, g и b, имена которых соответ-ствуют цветовым каналам. Причем при преобразовании используется весь диапазон от 0 до 255, даже если в формате пикселя для цветового компонента используется менее 8 бит – происходит масштабирование с использованием полей потери точности из аргумента fmt.

33

Следует заметить, что если глубина цвета меньше 32 бит на пиксель, то все биты, находящиеся левее (при записи двоичного целого числа слева направо от старших бит к младшим), чем младшие fmt→BitsPerPixel бит (от самого младшего разряда – бита с номером 0 и до бита с номером fmt→BitsPerPixel–1) в результате, возвращаемом функцией SDL_MapRGB, будут установлены в 0 и могут быть безопасно проигнорированы. Если функция SDL_MapRGB будет использована с форматом пикселя, имеющим альфа-канал, то все биты в нем будут установлены в 1 – полностью непрозрачный пиксель. Если с таким форматом пикселя будет использована функция SDL_GetRGB, то значение альфа-канала в аргументе pixel будет проигнорировано.

Существуют аналогичные функции, позволяющие явно рабо-тать c форматом пикселей RGBA-поверхностей (поверхностей с каналом прозрачности – альфа-каналом):

Uint32 SDL_MapRGBA(SDL_PixelFormat *fmt, Uint8 r, Uint8 g, Uint8 b, Uint8 a);

void SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);

Они отличаются от предыдущих функций наличием допол-нительного параметра, передающего в функцию (Uint8 a) или возвращающего из функции по указателю (Uint8 *a) значение компонента прозрачности (альфа-канала). Если в формате пикселя отсутствует альфаканал, то при формировании атрибута пикселя в функции SDL_MapRGBA значение аргумента a игнорируется (оно также всегда игнорируется, если используется палитра), а функция SDL_GetRGBA возвращает значение альфа-канала 255 (полностью непрозрачный пиксель).

При работе с поверхностями одна из самых широко применяе-мых операций – это наложение одной поверхности на другую или одной прямоугольной области на другую прямоугольную область на одной и той же поверхности. Наложение поверхностей может быть организовано непосредственным переносом данных из массива пикселей одной поверхности в массив пикселей другой поверхности. Но такой способ является весьма трудоемким и способствует появлению ошибок в программе. Он требует либо идентичности форматов пикселей обеих поверхностей, либо преобразования формата при переносе каждого пикселя. Также он требует явного вычисления положения данных каждого пикселя в массиве пикселей. Для обеспечения быстрого наложения поверх-ностей (с использованием возможных средств аппаратного ускорения) в основной библиотеке SDL служит функция SDL_BlitSurface, которая в рассматриваемой версии библиотеки с помощью макроподстановок может считаться объявленной так (подробности можно найти в заголовочном файле SDL_video.h):

extern DECLSPEC int SDLCALL SDL_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);

Первый параметр – указатель на накладываемую поверхность, второй – указатель на структуру SDL_Rect, в которой компонен-тами x и y задан верхний левый угол, а компонентами w и h – ши-рина и высота накладываемого фрагмента данной поверхности. При этом если компонентами второго параметра задается область, выходящая за пределы накладываемой поверхности, внутри функции они корректируются для предотвращения обращения за пределы ее области памяти и используются откорректированные значения. Однако после успешного выполнения функции в струк-туре, на которую указывал второй параметр, остаются исходные значения (а не откорректированные внутри функции). Если второй параметр равен NULL, накладывается вся поверхность. Третий параметр – целевая поверхность, на которую производится нало-жение. Если указатель хотя бы на одну из поверхностей будет равен NULL, функция завершится с ошибкой без выполнения каких-либо действий. Четвертым параметром задается указатель на структуру SDL_Rect, в которой компонентами x и y задан верхний левый угол области целевой поверхности, на которую должен быть наложен выбранный вторым параметром фрагмент накладываемой поверхности. Ширина и высота данной области определяются автоматически внутри функции таким образом, чтобы при наложении использовалась такая часть выбранного фрагмента накладываемой поверхности, которая не превосходит указанный фрагмент целевой поверхности. Поэтому значения компонентов w и h четвертого параметра могут быть произволь-ными. Если четвертый параметр равен NULL, то

34

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

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

ЕСЛИ для поверхности src установлен флаг SDL_SRCALPHA, ТО

ЕСЛИ поверхность src имеет альфа-канал (т.е. поле format→Amask не равно нулю),

ТО

Производится наложение с использованием альфа-канала накладываемой поверхности (используются значения прозрачности каждого ее пикселя), наличие флага

SDL_SCRCOLORKEY не проверяется, ключе-вой цвет (format→colorkey) и

прозрачность поверх-ности (format→alpha) игнорируются; ИНАЧЕ

ЕСЛИ для накладываемой поверхности установлен флаг SDL_SRCCOLORKEY,

ТО Производится наложение с использованием ключевого цвета накладываемой

поверхности – ее пиксели со значением, равным format→colorkey, игнорируются, состояние соответствующих им пикселей целевой поверхности не изменяется, а остальные пиксели при наложении рассматриваются как имеющие прозрачность, равную прозрачности поверхности (format→alpha);

ИНАЧЕ Производится наложение с использованием прозрачности поверхности – все ее

пиксели при наложении рассматриваются как имеющие прозрачность, равную format→alpha;

КОНЕЦ ЕСЛИ; КОНЕЦ ЕСЛИ;

ИНАЧЕ ЕСЛИ для накладываемой поверхности установлен флаг

SDL_SRCCOLORKEY,

ТО Производится наложение с использованием ключевого цвета накладываемой

поверхности – ее пиксели со значением, равным format→colorkey игнорируются, состояние соответствующих им пикселей целевой поверхности не изменяется, состояние остальных пикселей накладываемой поверхности копируется в целевую поверхность;

ИНАЧЕ Производится обычное непрозрачное прямоугольное наложение – копирование

состояния пикселей накладываемой поверхности в целевую поверхность; КОНЕЦ ЕСЛИ;

КОНЕЦ ЕСЛИ;

При успешном выполнении функция SDL_BlitSurface воз-вращает значение 0, в случае ошибки – –1. При успешном выполнении и отличном от NULL значении четвертого параметра в него записываются параметры фактически использованного фрагмента целевой поверхности.

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

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

SDL_CreateRGBSurface:

SDL_Surface * SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth,

35

Uint32 Rmask, Uint32 Gmask, Uint32, Bmask, Uint32 Amask);

Аргумент flags задает флаги для создания поверхности, аргу-менты width и height – ширину и высоту поверхности в пикселях, depth – глубину цвета в битах на пиксель. Если depth равно 8 бит на пиксель, то для поверхности создается палитра (изначально пустая), иначе используется непосредственное размещение значений цветовых компонентов в атрибутах пикселя, конкретные биты для каждого канала задаются масками Rmask, Gmask, Bmask и Amask. Для создаваемой поверхности выделяется память (для массива атрибутов пикселей pixels), которая будет освобождена при удалении поверхности функцией SDL_FreeSurface. Функция SDL_CreateRGBSurface возвращает либо указатель на созданную поверхность, либо NULL в случае какой-либо ошибки.

Если для создаваемой поверхности указано наличие альфа-канала (значение Amask не равно нулю), то для создаваемой поверх-ности автоматически устанавливается флаг SDL_SRCALPHA, независимо от его указания в атрибуте flags.

При необходимости флаги SDL_SRCCOLORKEY и SDL_SRCALPHA можно установить или сбросить после создания любой поверхности функциями SDL_SetColorKey и SDL_SetAlpha соответственно:

int SDL_SetColorKey(SDL_Surface *surface, Uint32 flags, Uint32 key);

int SDL_SetAlpha(SDL_Surface *surface, Uint32 flags, Uint8 alpha);

Первым параметром surface передается указатель на поверхность, вторым параметром – 0 для сброса соответствующего флага или сами соответствующие флаги: SDL_SRCCOLORKEY для функции SDL_SetColorKey и SDL_SRCALPHA для функции SDL_SetAlpha (иные описанные в документации флаги влияют на режимы ускорения наложения).

Третий параметр функции SDL_SetColorKey при установлен-ном в параметре flag флаге SDL_SETCOLORKEY задает ключевой цвет (считающийся прозрачным), представленный в формате пикселей поверхности, переданной первым аргументом. Как пра-вило, для обеспечения идентичности формата пикселей достаточно использовать функцию MapRGB.

Третий параметр функции SDL_SetAlpha при установленном в параметре flag флаге SDL_SRCALPHA задает значение прозрач-ности для всей поверхности (поле format→alpha): 0 (константа SDL_ALPHA_TRANSPARENT) – полностью прозрачная, 255 (константа SDL_ALPHA_OPAQUE) – полностью непрозрачная, 1..254 – промежуточные значения. При этом независимо от значения format→alpha, если для поверхности установлен флаг SDL_SRCALPHA и в формате пикселя имеется альфа-канал (format→Amask не равно нулю), то при наложении используются именно данные альфа-канала, общая прозрачность поверхности игнорируется, а данные альфа-канала целевой поверхности (при их наличии) сохраняются неизменными. Если же флаг SDL_SRCALPHA сброшен, то игнорируются все данные о прозрачности исходной поверхности. При этом если в формате пикселя обеих поверхностей присутствует альфа-канал, то его данные копируются вместе с остальными атрибутами пикселя.

Обе функции при успешном выполнении возвращают 0, при каких-либо ошибках – –1. Более подробное описание поведения данных функций можно найти в документации к SDL-1.2.15.

Поскольку при наложении поверхности они должны иметь одинаковый формат пикселей (допускается отсутствие альфа-кана-ла у одной поверхности при наличии его у другой), то перед наложением некоторой поверхности в окно программы может потребоваться преобразование ее формата. Для этого служат функции SDL_DisplayFormat и SDL_DisplayFormatAlpha:

SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);

SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface);

Обе функции создают новую поверхность по размеру поверх-ности-аргумента с форматом пикселей и набором цветов (при ис-пользовании палитры), совпадающим с отображаемой поверхностью (окном программы или всего экрана) или наиболее подходящим для быстрого наложения на отображаемую поверх-ность. Затем происходит копирование пикселей с исходной поверхности

36

на новую, при необходимости с изменением цветов (подбором ближайших цветов) или их внутреннего представления.

Функция SDL_DisplayFormat игнорирует данные альфа-канала, а функция SDL_DisplayFormatAlpha копирует данные, а также преобразует данные альфа-канала, если он был у исходной поверхности. Если у исходной поверхности альфа-канал отсут-ствовал, но был установлен флаг SDL_SRCCOLORKEY, то у пик-селей, совпадающих с ключевым цветом, устанавливается полная прозрачность (альфа=0), у остальных пикселей – полная непроз-рачность

(альфа=255).

При успешном выполнении обе функции возвращают ука-затель на новую поверхность, при ошибках преобразования или исчерпании памяти возвращают NULL.

Непосредственно для преобразования формата поверхностей функции SDL_DisplayFormat и SDL_DispalyFormatAlpha исполь-зуют функцию SDL_ConvertSurface:

SDL_Surface *SDL_ConvertSurface(SDL_Surface *src,

SDL_PixelFormat *fmt, Uint32 flags);

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

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

Данная функция, как и большинство функций SDL, может быть вызвана только после

SDL_Init.

Функция возвращает либо указатель на вновь созданную поверхность, либо NULL при ошибке.

Очевидным образом она может использоваться для копи-рования поверхности без преобразования:

SDL_Surface *orig_surf = NULL, *copy_surf = NULL;

/* Здесь как-то создается поверхность orig_surf */ copy_surf = SDL_ConvertSurface(orig_surf,

orig_surf->fmt, orig_surf->flags);

/* Возможно потребуется явно установить или сбросить у поверхности copy_surf флаги SDL_SRCCOLOR и SDL_SRCALPHA

и соответствующие им значения */

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

Создание поверхности из уже размещенных в памяти данных, описывающих состояние пикселей:

SDL_Surface * SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch,

Uint32 Rmask, Uint32 Gmask, Uint32, Bmask, Uint32 Amask);

Первым аргументом в функцию передается указатель на мас-сив данных, описывающий пиксели. При этом он интерпрети-руется последовательно по depth бит на пиксель (слева направо в строке, сверху вниз). Параметр pitch указывает, сколько байтов занимают в pixels атрибуты одной строки пикселей.

Массив данных н е к о п и р у е т с я в структуру данных по-верхности, копируется только значение указателя в соответ-ствующее поле pixels структуры SDL_Surface. При этом устанавливается флаг SDL_PREALLOC (использование предварительно выделенного буфера), и при освобождении поверхности не производится освобождение буфера.

При успешном выполнении функция SDL_CreateRGBSurface From возвращает указатель на созданную структуру SDL_Surface (поверхность), в случае ошибки возвращает NULL.

Собственно освобождение поверхности производится функ-цией SDL_FreeSurface:

37

Соседние файлы в предмете Программирование