Графика для Windows средствами DirectDraw | страница 102
Давайте посмотрим, как реализована функция CreateSurface() (см. листинг 5.1).
Листинг 5.1. Функция CreateSurface()
>LPDIRECTDRAWSURFACE DirectDrawWin::CreateSurface(LPCTSTR filename, BOOL installpalette) {
> int imagew, imageh;
> GetBmpDimensions(filename, imagew, imageh);
> LPDIRECTDRAWSURFACE surf=CreateSurface(imagew, imageh);
> if (surf==0) {
> TRACE("CreateSurface(filename) failed to create surface\n");
> return 0;
> }
> ifstream bmp(filename, ios::binary | ios::nocreate);
> if (!bmp.is_open()) {
> TRACE("LoadSurface: cannot open Bmp file\n");
> return 0;
> }
> BITMAPFILEHEADER bmpfilehdr;
> bmp.read((char*)&bmpfilehdr, sizeof(bmpfilehdr));
> char* ptr=(char*)&bmpfilehdr.bfType;
> if (*ptr!='B' || *++ptr!='M') {
> TRACE("invalid bitmap\n");
> return 0;
> }
> BITMAPINFOHEADER bmpinfohdr;
> bmp.read((char*)&bmpinfohdr, sizeof(bmpinfohdr));
> bmp.seekg(sizeof(bmpfilehdr)+bmpinfohdr.biSize, ios::beg);
> int imagebitdepth=bmpinfohdr.biBitCount;
> int imagesize=bmpinfohdr.biSizeImage;
> if (imagesize==0) imagesize=((imagew*(imagebitdepth/8)+3) & ~3)*imageh;
> if (bmpinfohdr.biCompression!=BI_RGB) {
> TRACE("compressed BMP format\n");
> return 0;
> }
> TRACE("loading '%s': width=%d height=%d depth=%d\n", filename, imagew, imageh, imagebitdepth);
> if (imagebitdepth==8) {
> int ncolors;
> if (bmpinfohdr.biClrUsed==0) ncolors=256;
> else ncolors=bmpinfohdr.biClrUsed;
> RGBQUAD* quad=new RGBQUAD[ncolors];
> bmp.read((char*)quad, sizeof(RGBQUAD)*ncolors);
> if (installpalette) CreatePalette(quad, ncolors);
> delete[] quad;
> }
> BYTE* buf=new BYTE[imagesize];
> bmp.read(buf, imagesize);
> if (!Copy_Bmp_Surface(surf, &bmpinfohdr, buf)) {
> TRACE("copy failed\n");
> delete[] buf;
> surf->Release();
> return 0;
> }
> delete[] buf;
> return surf;
>}
Сначала эта функция определяет размеры изображения из BMP-файла с помощью функции GetBmpDimensions() — простой функции класса DirectDrawWin, которая открывает BMP-файл и извлекает из заголовка ширину и высоту изображения. На основании полученных данных создается новая поверхность с использованием версии CreateSurface(), которая создает поверхность по ее размерам. Новая поверхность заполнена случайными пикселями, но мы не стираем ее, потому что вскоре значение каждого пикселя будет задано в соответствии с содержимым BMP-файла.
Затем мы открываем BMP-файл с помощью класса ifstream и извлекаем из него данные заголовка. Далее проверяется сигнатура файла; если проверка дает отрицательный результат, BMP-файл может содержать неверную информацию, поэтому функция завершает работу.