Трухильо Стэн
Шрифт:
После проверки обоих аргументов-указателей мы подготавливаем экземпляр структуры DDSURFACEDESC(desc) и используем его при вызове функции Lock интерфейса DirectDrawSurface. После возвращения из функции Lock поле lpSurface содержит указатель на память поверхности, и мы можем спокойно изменять содержимое поверхности через этот указатель до вызова Unlock. Безопасная работа с поверхностью стала возможной только потому, что мы указали флаг DDLOCK_WRITEONLY. Если вы собираетесь осуществлять и чтение, и запись, не устанавливайте этот флаг.
Далее мы инициализируем целую переменную bytesgiven. Присваиваемое значение определяется шириной изображения (w), выровненного по границе параграфа. Получившаяся величина равна объему памяти, необходимой для хранения одной строки пикселей. Если ширина изображения кратна четырем, переменная bytesgiven совпадает с w.
Указатель на поверхность (surfbits) инициализируется значением поля lpSurface. Этот указатель используется для обращений к памяти поверхности. Указатель на графические данные (imagebits) инициализируется адресом последней строки пикселей BMP-файла, поскольку в формате BMP изображение хранится в перевернутом виде.
Затем мы в цикле перебираем все строки пикселей изображения. Благодаря тому, что формат графических данных BMP-файла совпадает с форматом поверхности, для копирования можно воспользоваться функцией memcopy. Для поверхностей остальных типов такая удобная возможность часто отсутствует. Поле lPitch определяет смещение для указателя на поверхность при переходе к следующей строке. Вспомните, что в этом поле хранится шаг поверхности, который может не совпадать с ее шириной. Целая переменная bytesgiven аналогичным образом используется для перехода к следующей строке буфера графических данных. Поскольку чтение начинается с конца буфера, указатель imagebits уменьшается с каждой очередной итерацией.
Наконец, мы вызываем функцию Unlock интерфейса DirectDrawSurface и в качестве аргумента передаем ей ноль. С помощью этого аргумента можно сбалансировать вызовы Lock и Unlock при многократной блокировке одной поверхности. Для сценариев с однократной блокировкой (включая наш) можно просто передать ноль.
Загрузка 8-битных изображений выполняется достаточно просто. Давайте перейдем к 16-битным поверхностям, с ними дело обстоит значительно сложнее. Помимо учета разных типов 16-битных форматов пикселей нам придется сокращать количество цветов. 24-битные данные передаются на 16-битную поверхность, поэтому во время передачи необходимо «урезать» каждую цветовую составляющую. Функция Copy_Bmp24_Surface16 приведена в листинге 5.2.
Листинг 5.2. Функция Copy_Bmp24_Surface16