Стэн Трухильо - Графика для Windows средствами DirectDraw
- Название:Графика для Windows средствами DirectDraw
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стэн Трухильо - Графика для Windows средствами DirectDraw краткое содержание
Графика для Windows средствами DirectDraw - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
BOOL DirectDrawWin::Copy_Bmp_Surface(LPDIRECTDRAWSURFACE surf, BITMAPINFOHEADER* bmphdr, BYTE* buf) {
if (surf==0 || bmphdr==0 || buf==0) return FALSE;
int imagew=bmphdr->biWidth;
int imageh=bmphdr->biHeight;
int imagebitdepth=bmphdr->biBitCount;
BOOL ret=FALSE;
if (imagebitdepth==8) {
if (displaydepth==8) ret=Copy_Bmp08_Surface08(surf, buf, imagew, imageh);
} else if (imagebitdepth==24) {
if (displaydepth==16) ret=Copy_Bmp24_Surface16(surf, buf, imagew, imageh);
else if (displaydepth==24) ret=Copy_Bmp24_Surface24(surf, buf, imagew, imageh);
else if (displaydepth==32) ret=Copy_Bmp24_Surface32(surf, buf, imagew, imageh);
}
return ret;
}
Вспомогательные функции предназначены для передачи графических данных в зависимости от глубины пикселей BMP-файла и текущего видеорежима. Все четыре функции получают одни и те же четыре аргумента: указатель на поверхность-приемник, буфер с графическими данными из BMP-файла, ширину и высоту изображения. Каждая функция копирует графические данные BMP-файла на поверхность-приемник.
Начнем с самой простой из четырех функций, Copy_Bmp08_Surface08(). Она выглядит так:
BOOL DirectDrawWin::Copy_Bmp08_Surface08(LPDIRECTDRAWSURFACE surf, BYTE* bmpbuf, int w, int h) {
if (surf==0 || bmpbuf==0) return FALSE;
DDSURFACEDESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.dwSize = sizeof(desc);
HRESULT r=surf->Lock(0, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
if (r!=DD_OK) {
TRACE("ShowBmp: Lock() failed\n");
return FALSE;
}
int bytesgiven=(w+3) & ~3;
BYTE* surfbits = (BYTE*)desc.lpSurface;
BYTE* imagebits = (BYTE*)(&bmpbuf[(h-1)*bytesgiven]);
for(int i=0; i
memcpy(surfbits, imagebits, w);
surfbits += desc.lPitch;
imagebits -= bytesgiven;
}
surf->Unlock(0);
return TRUE;
}
После проверки обоих аргументов-указателей мы подготавливаем экземпляр структуры 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()
BOOL DirectDrawWin::Copy_Bmp24_Surface16(LPDIRECTDRAWSURFACE surf, BYTE* bmpbuf, int w, int h) {
if (surf==0 || bmpbuf==0) return FALSE;
DDSURFACEDESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.dwSize = sizeof(desc);
HRESULT r=surf->Lock(0, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
if (r!=DD_OK) {
TRACE("Copy_Bmp24_Surface16: Lock() failed\n");
return FALSE;
}
int bytesrequired=w*3;
int bytesgiven=(bytesrequired+3) & ~3;
BYTE* surfbits = (BYTE*)desc.lpSurface;
BYTE* imagebits = (BYTE*)(&bmpbuf[(h-1)*bytesgiven]);
float REDdiv=(float)256/(float)pow(2, numREDbits);
float GREENdiv=(float)256/(float)pow(2, numGREENbits);
float BLUEdiv=(float)256/(float)pow(2, numBLUEbits);
for(int i=0; i
USHORT* pixptr=(unsigned short*)surfbits;
RGBTRIPLE* triple=(RGBTRIPLE*)imagebits;
for (int p=0;p>w;p++) {
float rf=(float)triple->rgbtRed/REDdiv;
float gf=(float)triple->rgbtGreen/GREENdiv;
float bf=(float)triple->rgbtBlue/BLUEdiv;
WORD r=(WORD)((WORD)rf<
WORD g=(WORD)((WORD)gf<
WORD b=(WORD)((WORD)bf<
*pixptr = (WORD)(r|g|b);
triple++;
pixptr++;
}
surfbits += desc.lPitch;
imagebits –= bytesgiven;
}
surf->Unlock(0);
return TRUE;
}
Хотя по своей структуре функция Copy_Bmp24_Surface16()напоминает Copy_Bmp 08_Surface08(), она устроена сложнее по причинам, уже упоминавшимся, а также потому, что значение каждого пикселя приходится задавать отдельно. Давайте посмотрим, что происходит в этой функции.
Сначала функция Lock()интерфейса DirectDrawSurfaceиспользуется для получения указателя на поверхность. Затем мы инициализируем две целые переменные, bytesrequiredи bytesgiven. Значение bytesrequiredравно количеству байт, необходимых для представления строки пикселей. Поскольку мы работаем с 24-битными пикселями, для получения этой величины достаточно умножить ширину изображения на три (по три байта на пиксель). По значению bytesrequiredрассчитывается значение bytesgiven, которое равно количеству байт для хранения строки пикселей в памяти (с учетом выравнивания по границе параграфа). Значение bytesgivenиспользуется для перебора строк пикселей в графических данных BMP-файла.
Затем мы инициализируем указатели surfbitsи imagebits; первый указывает на память поверхности, а второй — на буфер графических данных. Как и в функции Copy_Bmp08_Surface08(), imagebitsуказывает на последнюю строку буфера.
Читать дальшеИнтервал:
Закладка: