Orajt, coś wymyśliłem... jak się jeszcze nie znużyliście, to tutaj mam kolejny, aczkolwiek tylko z pozoru duży problem. Kod [spory, ale naprawdę krótki]:
bool Bitmap::Load(LPDIRECTDRAW lpDD, IODatFile* df, std::string oname){
DDSURFACEDESC nddsd; // definicja powierzchni
objectEntry image = *(df->GetObjectByName(oname)); // tutaj mozecie nie wiedziec, jest to
std::ifstream ifile(df->fname.c_str(), std::ios::binary); // ladowanie bufora z obrazkiem z pliku *.dat
if (!ifile) return false;
int w, h;
ifile.seekg(image.offset); // porusza sie po pliku w poszukiwaniu interesujacego nas obrazka...
unsigned char *cbuf, *ubuf; // bufory: do danych skompresowanych i rozkompresowanych
cbuf = new unsigned char[image.CLength];
ifile.read((char*)cbuf, image.CLength); // czyta dane skompresowane...
ubuf = new unsigned char[image.RLength];
unsigned long real_length = image.RLength;
uncompress(ubuf, &real_length, cbuf, image.CLength); // ... i je rozkompresowuje
delete cbuf;
w = ubuf[0] << ubuf[1]; // w rozkompresowanym buforze 4 pierwsze bajty
h = ubuf[2] << ubuf[3]; // to szerokosc i dlugosc
ZeroMemory(&nddsd, sizeof(nddsd));
nddsd.dwSize = sizeof(nddsd);
nddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
nddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
nddsd.dwWidth = w; // tworzymy surface o danej szerokosci i dlugosci...
nddsd.dwHeight = h;
HRESULT ret = lpDD->CreateSurface(&nddsd, &s, NULL);
if (ret != DD_OK) return false;
ubuf += 4; // ... przesuwamy wskaznik na bufor o 4 bajty do przodu,
// jestesmy juz przy wlasciwych danych
HDC DirectDC=CreateCompatibleDC(NULL); // tworzymy dc z bitmapa
if (!DirectDC) return false; else
{
BITMAPINFO RGB32BitsBITMAPINFO; // bitmapinfoheader :P
ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
RGB32BitsBITMAPINFO.bmiHeader.biWidth=w;
RGB32BitsBITMAPINFO.bmiHeader.biHeight=h;
RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; // tworzymy bitmape...
UINT * ptPixels;
HBITMAP DirectBitmap = CreateDIBSection(DirectDC, // ...za pomoca CreateDIBSection
(BITMAPINFO *)&RGB32BitsBITMAPINFO,
DIB_RGB_COLORS,
(void **)&ptPixels,
NULL, 0);
if (!DirectBitmap) return false; else
{
SelectObject(DirectDC, DirectBitmap);
BYTE r,g,b;
for (int i=0;i<(w*h);i++) // tutaj kopiujemy piksele z bufora do bitmapy
{
r = *ubuf++;
g = *ubuf++;
b = *ubuf++;
ptPixels[i] = (0 | (b << 16) | (g << 8) | (r));
}
HDC SDC;
s->GetDC(&SDC);
BitBlt(SDC, 0, 0, w, h, DirectDC, 0, 0, SRCCOPY); // wstawiamy dc z bitmapa do dc directdraw'a
s->ReleaseDC(SDC);
}
}
return true;
}
Troche dziwnie obkomentowalem, piszcie jak cos niezrozumiałe. Otóż wykorzystuję pliki *.dat, które zawieraja zindeksowane stringami dane, skompresowane zlibem. Metoda GetObjectByName daje nam strukturę z offsetem danych przypisanych do danego stringowego indeksu, ponadto ich dwie długości: skompresowaną i rozkompresowaną, które są potrzebne w dekompresji.
No i rozkompresowuje te dane, kopiuje je do dc, wyświetla je na directdraw... tylko zawsze jakoś na skos, z przemieszczeniem, czasami w ogóle... a bajty chyba policzyłem dobrze :S. Próbowałem wcześniej z zrzucaniem bajtów bezpośrednio do pamięci karty graficznej, wskazanej przez surface, ale też coś się kisiło :/