Графика для 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-файл может содержать неверную информацию, поэтому функция завершает работу.