/**************/ /* bitmap.c */ /***************************************************************************** PROGRAM: bitmap.c Windows: Win 3.1 (& WIN32??) PURPOSE: Aliohjelmia bittikarttojen käsittelyyn Editor: Vesa Lappalainen 15.10.1994 muuntanut CHAP13\SHOWDIB.C -- Show DIB in Window (c) Charles Petzold, 1992 PROJECT: + ALI\bitmap.c Muutoksia: 24.9.1995: BitmapCache -funktiot Vikoja: Toistaiseksi ei osaa liian monivärisiä kuvia. Miksi? Selityksiä: =========== DIB = Device Independent Bitmap. Tavalliset BitBltissa käytettävät bittikartat ovat laiteriippuvia. Funktiot: ========= bmHDIB bmReadDib(LPCSTR szFileName) - lukee tiedostosta DIB bittikartan, NULL = virhe - täytyy lopuksi tuhota bmDeleteDib(lpdib); int bmDeleteDib(bmHDIB lpDib) - vapauttaa DIBiä varten varatun muistin WORD bmGetDibWidth(bmHDIB lpDib) - palauttaa DIB bittikartan leveyden WORD bmGetDibHeight(bmHDIB lpDib) - palauttaa DIB bittikartan korkeuden int bmDrawDib(HDC hDC,bmHDIB lpDib,int x,int y) - piirtää DIBin fyysiselle laitteelle. hDC EI saa olla muistilaiteyhteys (eli esim. bittikarttaa varten tehty) HBITMAP bmFileLoadBitmap(LPCSTR name) - luo tavallisen bittikartan lukemalla sen tiedostosta HBITMAP bmFileOrResLoadBitmap(HINSTANCE hInst,LPCSTR name) - luo tavallisen bittikartan lukemalla sen tiedostosta jos nimessä on . \ tai : ja muuten resursseista. Tällä voidaan korvata esim kaikki LoadBitmap -kutsut, jos halutaan lukea bittikarttoja molemmista paikoista. typedef struct { tOneBitmap *first; tOneBitmap *last; } tbmBitmapCache; - tietue, jonne voidaan ladata joukko bittikuvia, jotta seuraavat piirrot ovat helpompia HBITMAP bmFindBitmap(HINSTANCE hInst,const char *name, tbmBitmapCache *bc); - etsii tai lataa bittikartan. JOs joudutaan lataamaan, laitetaan se bc-tietueeseen jemmaan int bmDeleteBitmapCache(tbmBitmapCache *bc); - tuhotaan bittikartta cache int bmDrawBitmap(HDC hDC,HBITMAP hBitmap,int x,int y); - piirtää yhden bittikartam int bmDrawBitmapName(HINSTANCE hInstance, HDC hDC,const char *name, int x,int y, tbmBitmapCache *bc); - etsii ja tarvittaessa lataa ja piirtää bittikartan *****************************************************************************/ #include #include #include #include #include "bitmap.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) /****************************************************************************/ /* Functions for extracting information from DIB memory blocks */ #define pInfoHeader(lpDib) ((BITMAPINFOHEADER far *)lpDib) #define pCoreHeader(lpDib) ((BITMAPCOREHEADER far *)lpDib) static DWORD bmGetDibInfoHeaderSize(bmHDIB lpDib) { return pInfoHeader(lpDib)->biSize; } static int bmInfoInCore(bmHDIB lpDib) { return bmGetDibInfoHeaderSize(lpDib) == sizeof(BITMAPCOREHEADER); } WORD bmGetDibWidth(bmHDIB lpDib) { if ( bmInfoInCore(lpDib) ) return (WORD)(pCoreHeader(lpDib)->bcWidth); else return (WORD)(pInfoHeader(lpDib)->biWidth); } WORD bmGetDibHeight(bmHDIB lpDib) { if ( bmInfoInCore(lpDib) ) return (WORD)(pCoreHeader(lpDib)->bcHeight); else return (WORD)(pInfoHeader(lpDib)->biHeight); } static BYTE huge *bmGetDibBitsAddr(bmHDIB lpDib) { DWORD dwNumColors, dwColorTableSize; WORD wBitCount; DWORD bmihsize = bmGetDibInfoHeaderSize(lpDib); if ( bmInfoInCore(lpDib) ) { wBitCount = pCoreHeader(lpDib)->bcBitCount; if (wBitCount != 24) dwNumColors = 1L << wBitCount; else dwNumColors = 0; dwColorTableSize = dwNumColors * sizeof(RGBTRIPLE); } else { wBitCount = pInfoHeader(lpDib)->biBitCount; if ( bmihsize >= 36) dwNumColors = pInfoHeader(lpDib)->biClrUsed; else dwNumColors = 0; if (dwNumColors == 0) if (wBitCount != 24) dwNumColors = 1L << wBitCount; else dwNumColors = 0; dwColorTableSize = dwNumColors * sizeof(RGBQUAD); } return lpDib + bmihsize + dwColorTableSize; } /****************************************************************************/ int bmDeleteDib(bmHDIB lpDib) { if ( lpDib == NULL ) return -1; (void)GlobalFreePtr(lpDib); return 0; } /****************************************************************************/ bmHDIB bmReadDib(LPCSTR szFileName) /* Read a DIB from a file into memory */ { BITMAPFILEHEADER bmfh ; bmHDIB lpDib; DWORD dwDibSize, dwOffset, dwHeaderSize; int hFile; WORD wDibRead; int fhsize = sizeof(BITMAPFILEHEADER); if ( -1 == (hFile = _lopen(szFileName, OF_READ | OF_SHARE_DENY_WRITE)) ) return NULL; if (_lread(hFile, (LPSTR)&bmfh,fhsize) != fhsize ) { _lclose(hFile); return NULL; } if ( bmfh.bfType != *(WORD *)"BM" ) { _lclose(hFile); return NULL; } dwDibSize = bmfh.bfSize - fhsize; lpDib = (bmHDIB)GlobalAllocPtr(GMEM_MOVEABLE, dwDibSize); if (lpDib == NULL) { _lclose(hFile); return NULL; } dwOffset = 0 ; while (dwDibSize > 0) { wDibRead = (WORD)MIN(32768ul,dwDibSize) ; if ( wDibRead != _lread(hFile,(LPSTR)((char huge *)lpDib + dwOffset), wDibRead) ) { _lclose (hFile); bmDeleteDib(lpDib); return NULL; } dwDibSize -= wDibRead; dwOffset += wDibRead; } _lclose (hFile); dwHeaderSize = bmGetDibInfoHeaderSize(lpDib); if ( dwHeaderSize < 12 || ( dwHeaderSize > 12 && dwHeaderSize < 16 ) ) { bmDeleteDib(lpDib); return NULL; } return lpDib; } /****************************************************************************/ int bmDrawDib(HDC hDC,bmHDIB lpDib,int x,int y) { BYTE huge *lpDibBits; short cxDib, cyDib; int i; if ( !lpDib ) return NULL; lpDibBits = bmGetDibBitsAddr(lpDib); cxDib = bmGetDibWidth(lpDib); cyDib = bmGetDibHeight(lpDib); SetStretchBltMode(hDC, COLORONCOLOR); i = SetDIBitsToDevice(hDC, x, y, cxDib, cyDib, 0, 0, 0, cyDib, (LPSTR)lpDibBits, (LPBITMAPINFO)lpDib, DIB_RGB_COLORS); return i; } /****************************************************************************/ HBITMAP bmFileLoadBitmap(LPCSTR name) { BYTE huge *lpDibBits ; bmHDIB lpDib; HBITMAP hBitmap = NULL; HDC hDC; lpDib = bmReadDib(name); if ( !lpDib ) return NULL; hDC = GetDC(NULL); lpDibBits = bmGetDibBitsAddr(lpDib); hBitmap = CreateDIBitmap(hDC, pInfoHeader(lpDib), CBM_INIT, (void far *)lpDibBits,(BITMAPINFO FAR *)lpDib, DIB_RGB_COLORS); ReleaseDC(NULL,hDC); ret: (void)GlobalFreePtr(lpDib) ; return hBitmap; } /****************************************************************************/ HBITMAP bmFileOrResLoadBitmap(HINSTANCE hInst,LPCSTR name) /* Jos nimessä on \:. , ladataan tiedostosta ja muuten resursseista */ { int i; for (i=0; name[i]; i++) if ( strchr("\\:.",name[i] ) ) return bmFileLoadBitmap(name); return LoadBitmap(hInst,name); } /****************************************************************************/ HBITMAP bmFindBitmap(HINSTANCE hInst,const char *name, tbmBitmapCache *bc) { tOneBitmap *bm; HBITMAP hBitmap; for (bm = bc->first; bm; bm = bm->next) if ( strcmp(bm->name,name) == 0 ) return bm->hBitmap; hBitmap = bmFileOrResLoadBitmap(hInst,name); if ( hBitmap == NULL ) return NULL; bm = malloc(sizeof(*bm)); if ( bm == NULL ) { DeleteObject(hBitmap); return NULL; } if ( bc->first == NULL ) bc->first = bm; else bc->last->next = bm; bc->last = bm; bm->next = NULL; bm->hBitmap = hBitmap; strncpy(bm->name,name,sizeof(bm->name)); bm->name[sizeof(bm->name)-1] = 0; return bm->hBitmap; } /****************************************************************************/ int bmDeleteBitmapCache(tbmBitmapCache *bc) { tOneBitmap *bm,*temp; for (bm = bc->first; bm; ) { temp = bm; bm = bm->next; DeleteObject(temp->hBitmap); free(temp); } bc->first = NULL; bc->last = NULL; return 0; } /***************************************************************************/ int bmDrawBitmap(HDC hDC,HBITMAP hBitmap,int x,int y) /* Piirretään bittikartta alkaen paikasta x,y */ { HDC hDCBitmap = CreateCompatibleDC(hDC); HGDIOBJ hOld = SelectObject(hDCBitmap,hBitmap); BITMAP bm; GetObject(hBitmap,sizeof(bm),&bm); BitBlt(hDC,x,y,bm.bmWidth,bm.bmHeight,hDCBitmap,0,0,SRCCOPY); SelectObject(hDCBitmap,hOld); DeleteDC(hDCBitmap); return 0; } /***************************************************************************/ int bmDrawBitmapName(HINSTANCE hInstance, HDC hDC,const char *name, int x,int y, tbmBitmapCache *bc) { HBITMAP hBitmap = bmFindBitmap(hInstance,name,bc); if ( hBitmap == NULL ) return -1; return bmDrawBitmap(hDC,hBitmap,x,y); }