/****************************************************************************** * CreateCompatibleBitmap [GDI32.@] * * Creates a bitmap compatible with the DC. * * PARAMS * hdc [I] Handle to device context * width [I] Width of bitmap * height [I] Height of bitmap * * RETURNS * Success: Handle to bitmap * Failure: 0 */ HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height) { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *bi = (BITMAPINFO *)buffer; DIBSECTION dib; TRACE("(%p,%d,%d)\n", hdc, width, height); if (GetObjectType( hdc ) != OBJ_MEMDC) return CreateBitmap( width, height, GetDeviceCaps(hdc, PLANES), GetDeviceCaps(hdc, BITSPIXEL), NULL ); switch (GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(dib), &dib )) { case sizeof(BITMAP): /* A device-dependent bitmap is selected in the DC */ return CreateBitmap( width, height, dib.dsBm.bmPlanes, dib.dsBm.bmBitsPixel, NULL ); case sizeof(DIBSECTION): /* A DIB section is selected in the DC */ bi->bmiHeader = dib.dsBmih; bi->bmiHeader.biWidth = width; bi->bmiHeader.biHeight = height; if (dib.dsBmih.biCompression == BI_BITFIELDS) /* copy the color masks */ memcpy(bi->bmiColors, dib.dsBitfields, sizeof(dib.dsBitfields)); else if (dib.dsBmih.biBitCount <= 8) /* copy the color table */ GetDIBColorTable(hdc, 0, 256, bi->bmiColors); return CreateDIBSection( hdc, bi, DIB_RGB_COLORS, NULL, NULL, 0 ); default: return 0; } }
// The following code was taken from http://support.microsoft.com/kb/158898 BOOL CImage::LoadBitmapFromBMPFile(LPTSTR szFileName) { CAutoLock lock(&m_csLock); BITMAP bm; // Use LoadImage() to get the image loaded into a DIBSection m_hBitmap = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE ); if( m_hBitmap == NULL ) return FALSE; // Get the color depth of the DIBSection GetObject(m_hBitmap, sizeof(BITMAP), &bm ); // If the DIBSection is 256 color or less, it has a color table if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 ) { HDC hMemDC = NULL; HBITMAP hOldBitmap = NULL; RGBQUAD rgb[256]; LPLOGPALETTE pLogPal = NULL; WORD i = 0; // Create a memory DC and select the DIBSection into it hMemDC = CreateCompatibleDC( NULL ); hOldBitmap = (HBITMAP)SelectObject( hMemDC, m_hBitmap ); // Get the DIBSection's color table GetDIBColorTable( hMemDC, 0, 256, rgb ); // Create a palette from the color tabl pLogPal = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + (256*sizeof(PALETTEENTRY)) ); pLogPal->palVersion = 0x300; pLogPal->palNumEntries = 256; for(i=0; i<256; i++) { pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed; pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen; pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue; pLogPal->palPalEntry[i].peFlags = 0; } m_hPalette = CreatePalette( pLogPal ); // Clean up free( pLogPal ); SelectObject( hMemDC, hOldBitmap ); DeleteDC( hMemDC ); } else // It has no color table, so use a halftone palette { HDC hRefDC = NULL; hRefDC = GetDC( NULL ); m_hPalette = CreateHalftonePalette( hRefDC ); ReleaseDC( NULL, hRefDC ); } return TRUE; }
int BMPanvas::CheckColorType() { int ret=0; RGBQUAD pal[256]; int i,k,j; switch(INFO.bmiHeader.biBitCount) { case 32: ColorType=RGBA; break; case 24: ColorType=TRUE_COLOR; break; case 8: GetDIBColorTable(hdc,0,256,pal); for(i=0,k=0,j=0; i<256; i++) { if(pal[i].rgbBlue==i && pal[i].rgbGreen==i && pal[i].rgbRed==i) k++; if(pal[i].rgbBlue==0 && pal[i].rgbGreen==0 && pal[i].rgbRed==0) j++; } ColorType=COLOR_PAL; if(k==256) ColorType=GRAY_PAL; if(j==255) ColorType=BW; break; case 1: ColorType=BW; break; default: ColorType=COL_ERROR; } return ret; }
ULONG FASTCALL WG32GetDIBColorTable(PVDMFRAME pFrame) { ULONG ul = 0; RGBQUAD * prgb; register PGETDIBCOLORTABLE16 parg16; GETARGPTR(pFrame, sizeof(GETDIBCOLORTABLE16), parg16); GETMISCPTR(parg16->f4,prgb); ul = (ULONG)GetDIBColorTable(HDC32(parg16->f1), parg16->f2, parg16->f3, prgb); WOW32APIWARN(ul, "GetDIBColorTable"); if (ul) FLUSHVDMPTR(parg16->f4,sizeof(RGBQUAD) * ul,prgb); FREEMISCPTR(prgb); FREEARGPTR(parg16); return(ul); }
int BMPanvas::CopyPallete(BMPanvas *src) { int ret=0; ret+=GetDIBColorTable(src->hdc,0,256,INFO.bmiColors); ret+=SetDIBColorTable(hdc,0,256,INFO.bmiColors); CheckColorType(); return ret; }
// Copy from DIB section color table to DIB color table UINT KDIBSection::GetColorTable(void) { int width, height; if ( (GetDepth()>8) || ! Prepare(width, height) ) // create memory DC return 0; return GetDIBColorTable(m_hMemDC, 0, m_nClrUsed, m_pRGBQUAD); }
////////////////// // Helper to get color table. Does all the mem DC voodoo. // UINT CDib::GetColorTable(RGBQUAD* colorTab, UINT nColors) { CWindowDC dcScreen(NULL); CDC memdc; memdc.CreateCompatibleDC(&dcScreen); CBitmap* pOldBm = memdc.SelectObject(this); nColors = GetDIBColorTable(memdc, 0, nColors, colorTab); memdc.SelectObject(pOldBm); return nColors; }
///////////////////////////////////////////////////////////////////////////// // // Helper to get color table. Does all the mem DC voodoo. // ///////////////////////////////////////////////////////////////////////////// UINT ZDib::GetColorTable( RGBQUAD *colorTab, UINT nColors ) { CWindowDC dcScreen( 0 ); CDC memDC; memDC.CreateCompatibleDC( &dcScreen ); CBitmap *pOldBmp = memDC.SelectObject( this ); nColors = GetDIBColorTable( memDC, 0, nColors, colorTab ); memDC.SelectObject( pOldBmp ); return( nColors ); }
bool GetPalette(CSBitmap* pBitmap, int StartColor, int NumColors, RGBQUAD* pColors) { assert(HasBitmap(pBitmap)); assert(GetChannels(pBitmap) == 1); assert(StartColor >= 0); assert(StartColor + NumColors <= 256); // Zero the destination array to make sure all bytes get cleared, even if // the function fails. memset(pColors, 0, sizeof(RGBQUAD) * NumColors); int GotCount = GetDIBColorTable(GetDrawSurface(pBitmap), StartColor, NumColors, pColors); return GotCount == NumColors; }
void WIZARD::SetGraphic (int idbGraphic16, int idbGraphic256) { LPRGBQUAD pargb = NULL; RGBQUAD argb[256]; m_idbGraphic16 = idbGraphic16; m_idbGraphic256 = idbGraphic256; if (m_bmpGraphic16 != NULL) { DeleteObject (m_bmpGraphic16); m_bmpGraphic16 = NULL; } if (m_bmpGraphic256 != NULL) { DeleteObject (m_bmpGraphic256); m_bmpGraphic256 = NULL; } if (m_palGraphic != NULL) { DeleteObject (m_palGraphic); m_palGraphic = NULL; } m_bmpGraphic16 = (HBITMAP)TaLocale_LoadImage (idbGraphic16, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); if ((m_bmpGraphic256 = (HBITMAP)TaLocale_LoadImage (idbGraphic256, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION)) != NULL) { BITMAP bm; GetObject (m_bmpGraphic256, sizeof(BITMAP), &bm); if ((bm.bmBitsPixel * bm.bmPlanes) == 8) { HDC hdc = CreateCompatibleDC (NULL); HBITMAP bmpOld = (HBITMAP)SelectObject (hdc, m_bmpGraphic256); GetDIBColorTable (hdc, 0, 256, argb); pargb = argb; SelectObject (hdc, bmpOld); DeleteDC (hdc); } } GeneratePalette (pargb); if (m_fShowing) { Refresh (REFRESH_LEFT_PANE); } }
HBITMAP WINAPI CreateCompatibleBitmap( HDC hDC, INT Width, INT Height) { PDC_ATTR pDc_Attr; if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr)) return NULL; if (!Width || !Height) return GetStockObject(DEFAULT_BITMAP); if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION)) { return NtGdiCreateCompatibleBitmap(hDC, Width, Height); } else { HBITMAP hBmp = NULL; struct { BITMAP bitmap; BITMAPINFOHEADER bmih; RGBQUAD rgbquad[256]; } buffer; DIBSECTION* pDIBs = (DIBSECTION*) &buffer; BITMAPINFO* pbmi = (BITMAPINFO*) &buffer.bmih; hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP); if (GetObjectA(hBmp, sizeof(DIBSECTION), pDIBs) != sizeof(DIBSECTION)) return NULL; if (pDIBs->dsBm.bmBitsPixel <= 8) GetDIBColorTable(hDC, 0, 256, buffer.rgbquad); pDIBs->dsBmih.biWidth = Width; pDIBs->dsBmih.biHeight = Height; return CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, NULL, NULL, 0); } return NULL; }
bool CScreenBuffer::Create(HDC hDev,const RECT & rc,LPCTSTR szName ) { TrackDebugOut; Destroy(); m_hMemDC = CreateCompatibleDC(hDev); if(m_hMemDC == NULL){ DebugOutF(filelog::log_error,("CreateCompatibleDC failed with %d"),GetLastError() ); return false; } RECT rcscreen = GetDCRect(hDev); RECT rcdest; IntersectRect(&rcdest,&rcscreen,&rc); LONG lWidth = rcdest.right - rcdest.left; LONG lHeight = rcdest.bottom - rcdest.top; LONG lBitsPPix = 32;//GetDeviceCaps(hDev,BITSPIXEL); LONG dwImageSize = lHeight*CalculatePitch(CalculateLine(lWidth,lBitsPPix)); // save [bmp file header] + [bmp info header] + [bmp data] to the file mapping object //DWORD filesize = 0; LONG biClrUsed = 0; RGBQUAD rgbquad[256]; if (lBitsPPix < 16) { TrackDebugOut; biClrUsed = GetDIBColorTable(hDev,0,256,rgbquad); } if(!CFileMappingBitmap::Create(lWidth,lHeight,lBitsPPix,biClrUsed,rgbquad,szName)) { return false; } m_hBmp = CreateDIBSection(m_hMemDC,(BITMAPINFO*)InfoHeader(),DIB_RGB_COLORS, (void**)&m_pBuff, GetHandle(), FileHeader()->bfOffBits); if(m_hBmp == NULL){ DebugOutF(filelog::log_error,("CreateDIBSection failed %d"),GetLastError() ); return false; } SelectObject(m_hMemDC,m_hBmp); //HDC hdc = GetDC(0); BitBlt(m_hMemDC,0,0,rcdest.right-rcdest.left,rcdest.bottom-rcdest.top,hDev,rcdest.left,rcdest.top,SRCCOPY|CAPTUREBLT); //ReleaseDC(0,hdc); return true; }
int BMPanvas::LoadBitmapArray(int hmin,int hmax) { int ret=0; if(hmin==MIN_SCANLINE) hmin=0; if(hmax==MAX_SCANLINE) hmax=h-1; if(hmax<hmin) { int t=hmax; hmax=hmin; hmin=t; } UnloadBitmapArray(); arr_size=(wbyte)*(hmax-hmin+1)+1; arr=new BYTE[arr_size]; ret=GetDIBits(hdc,hbmp,h-1-hmax,hmax-hmin+1,arr,lpbi,DIB_RGB_COLORS); GetDIBColorTable(hdc,0,256,INFO.bmiColors); return ret; }
void CImgBitsDIB::GetColors(long iFirst, long cColors, RGBQUAD* prgb) { if(_hbmImg) { HDC hdcMem; HBITMAP hbmSav; hdcMem = GetMemoryDC(); hbmSav = (HBITMAP)SelectObject(hdcMem, _hbmImg); GetDIBColorTable(hdcMem, iFirst, cColors, prgb); SelectObject(hdcMem, hbmSav); ReleaseMemoryDC(hdcMem); } else { if(iFirst < 0) { memset(prgb, 0, sizeof(RGBQUAD)*-iFirst); prgb -= iFirst; cColors += iFirst; iFirst = 0; } if(iFirst+cColors > _cColors) { memset(prgb+_cColors, 0, sizeof(RGBQUAD)*(iFirst+cColors-_cColors)); cColors = _cColors - iFirst; } if(_fPalColors) { memcpy(prgb, g_rgbHalftone+iFirst, sizeof(RGBQUAD)*cColors); } else { memcpy(prgb, (RGBQUAD*)(_pbmih+1)+iFirst, sizeof(RGBQUAD)*cColors); } } }
HRESULT CTextureHolder::CopyBitmapToSurface(){ // Get a DDraw object to create a temporary surface LPDIRECTDRAW7 pDD; m_pddsSurface->GetDDInterface( (VOID**)&pDD ); // Get the bitmap structure (to extract width, height, and bpp) BITMAP bm; GetObject( m_hbmBitmap, sizeof(BITMAP), &bm ); // Setup the new surface desc DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); m_pddsSurface->GetSurfaceDesc( &ddsd ); ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT| DDSD_TEXTURESTAGE; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY; ddsd.ddsCaps.dwCaps2 = 0L; ddsd.dwWidth = bm.bmWidth; ddsd.dwHeight = bm.bmHeight; // Create a new surface for the texture LPDIRECTDRAWSURFACE7 pddsTempSurface; HRESULT hr; if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) ) { pDD->Release(); return hr; } // Get a DC for the bitmap HDC hdcBitmap = CreateCompatibleDC( NULL ); if( NULL == hdcBitmap ) { pddsTempSurface->Release(); pDD->Release(); return hr; // bug? return E_FAIL? } SelectObject( hdcBitmap, m_hbmBitmap ); // Handle palettized textures. Need to attach a palette if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) { LPDIRECTDRAWPALETTE pPalette; DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256; DWORD pe[256]; WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe ); // Create the color table for( WORD i=0; i<wNumColors; i++ ) { pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) ); // Handle textures with transparent pixels if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) { // Set alpha for opaque pixels if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK ) { if( pe[i] != 0x00000000 ) pe[i] |= 0xff000000; } else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE ) { if( pe[i] != 0x00ffffff ) pe[i] |= 0xff000000; } } } // Add DDPCAPS_ALPHA flag for textures with transparent pixels if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) dwPaletteFlags |= DDPCAPS_ALPHA; // Create & attach a palette pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL ); pddsTempSurface->SetPalette( pPalette ); m_pddsSurface->SetPalette( pPalette ); SAFE_RELEASE( pPalette ); } // Copy the bitmap image to the surface. HDC hdcSurface; if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) ) { BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0, SRCCOPY ); pddsTempSurface->ReleaseDC( hdcSurface ); } DeleteDC( hdcBitmap ); // Copy the temp surface to the real texture surface m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL ); // Done with the temp surface pddsTempSurface->Release(); // For textures with real alpha (not palettized), set transparent bits if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask ) { if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) { // Lock the texture surface DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) == DDERR_WASSTILLDRAWING ); DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask; DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask | ddsd.ddpfPixelFormat.dwGBitMask | ddsd.ddpfPixelFormat.dwBBitMask ); DWORD dwColorkey = 0x00000000; // Colorkey on black if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE ) dwColorkey = dwRGBMask; // Colorkey on white // Add an opaque alpha value to each non-colorkeyed pixel for( DWORD y=0; y<ddsd.dwHeight; y++ ) { WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); for( DWORD x=0; x<ddsd.dwWidth; x++ ) { if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 ) { if( ( *p16 &= dwRGBMask ) != dwColorkey ) *p16 |= dwAlphaMask; p16++; } if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 ) { if( ( *p32 &= dwRGBMask ) != dwColorkey ) *p32 |= dwAlphaMask; p32++; } } } m_pddsSurface->Unlock( NULL ); } else if( m_bHasMyAlpha ){ DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) == DDERR_WASSTILLDRAWING ); DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask | ddsd.ddpfPixelFormat.dwGBitMask | ddsd.ddpfPixelFormat.dwBBitMask ); DWORD rMask = ddsd.ddpfPixelFormat.dwRBitMask; DWORD gMask = ddsd.ddpfPixelFormat.dwGBitMask; DWORD bMask = ddsd.ddpfPixelFormat.dwBBitMask; DWORD aMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask; DWORD rShift = GetShift( rMask ); DWORD gShift = GetShift( gMask ); DWORD bShift = GetShift( bMask ); DWORD aShift = GetShift( aMask ); DWORD maxRVal = rMask >> rShift; DWORD maxGVal = gMask >> gShift; DWORD maxBVal = bMask >> bShift; DWORD maxAVal = aMask >> aShift; DWORD rVal, gVal, bVal, aVal; FLOAT min, max; // Add an opaque alpha value to each non-colorkeyed pixel for( DWORD y=0; y<ddsd.dwHeight; y++ ){ WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); for( DWORD x=0; x<ddsd.dwWidth; x++ ){ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 ){ *p32 &= dwRGBMask; // set alpha to zero if( *p32 == 0 ){} // black is 100% transparent, so leave alpha at 0% else if( *p32 == dwRGBMask ){ // white is opaque, so set alpha to 100% *p32 |= aMask; } else{ // set alpha to equal intensity of brightest hue rVal = ( *p32 & rMask ) >> rShift; gVal = ( *p32 & gMask ) >> gShift; bVal = ( *p32 & bMask ) >> bShift; max = max( (FLOAT)rVal / maxRVal, max( (FLOAT)gVal / maxGVal, (FLOAT)bVal / maxBVal ) ); // min = min( (FLOAT)rVal / maxRVal, min( (FLOAT)gVal / maxGVal, (FLOAT)bVal / maxBVal ) ); aVal = max * 255; //if( rVal == gVal && gVal == bVal ){ // white fading to black // *p32 = dwRGBMask; // set color to white //} // maximize luminosity and saturation rVal /= max; gVal /= max; bVal /= max; *p32 = ( aVal << aShift ) | ( rVal << rShift ) | ( gVal << gShift ) | ( bVal << bShift ); } p32++; } else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 ){ *p16 &= dwRGBMask; // set alpha to zero if( *p16 == 0 ){} // black is 100% transparent, so leave alpha at 0% else if( *p16 == dwRGBMask ){ // white is opaque, so set alpha to 100% *p16 |= aMask; } else{ // set alpha to equal intensity of brightest hue rVal = ( *p16 & rMask ) >> rShift; gVal = ( *p16 & gMask ) >> gShift; bVal = ( *p16 & bMask ) >> bShift; aVal = STATSTEXTURE_ALPHA * max( (FLOAT)rVal / maxRVal, max( (FLOAT)gVal / maxGVal, (FLOAT)bVal / maxBVal ) ); if( aVal < STATSTEXTURE_ALPHA ){ // semi-tranparent white *p16 = dwRGBMask; } *p16 |= aVal << aShift; } p16++; } } }
/*********************************************************************** * WinGGetDIBColorTable (WING32.@) */ UINT WINAPI WinGGetDIBColorTable( HDC hdc, UINT start, UINT end, RGBQUAD *colors ) { return GetDIBColorTable( hdc, start, end, colors ); }
/******************************************************************************* // extracts the dimensional information, pixel array, and color table from an // HBITMAP. // hBitmap can be a handle to a DIB or a DDB. This function assumes that DDBs // will not have a palette. If you create a DDB on a 256-color graphics card, // then the DDB will have a palette and this function will fail. // // returns BMK_OK if successfull, and error state otherwise. ********************************************************************************/ BMGError GetDataFromBitmap( HBITMAP hBitmap, struct BMGImageStruct *img, int remove_alpha ) { unsigned int DIBScanWidth; DIBSECTION DS; HWND hWnd = GetForegroundWindow(); HDC hDC = NULL; HDC hMemDC = NULL; unsigned char red, green, blue; int FreelpBits = 0; unsigned int numBytes; size_t soDIBSECTION = sizeof(DIBSECTION); size_t soBITMAP = sizeof(BITMAP); unsigned char *p, *q, *lpBits, alpha; jmp_buf err_jmp; int error; BMGError bmgerr; /* error handler */ error = setjmp( err_jmp ); if ( error != 0 ) { if ( hMemDC != NULL ) DeleteDC( hMemDC ); if ( hDC != NULL ) ReleaseDC( hWnd, hDC ); if ( FreelpBits ) free( lpBits ); FreeBMGImage( img ); SetLastBMGError( (BMGError)error ); return (BMGError)error; } SetLastBMGError( BMG_OK ); /* check for valid bitmap*/ if ( !hBitmap ) longjmp( err_jmp, (int)errInvalidBitmapHandle ); /* Extract DIBSECTION info from the HBITMAP. numBytes will equal // soDIBSECTION (84) if hBitmap is a handle to a DIBSECTION (DIB). // numBytes will equal soBITMAP (24) if hBitmap is a handle to a // BITMAP (DDB). */ numBytes = GetObject( hBitmap, sizeof(DIBSECTION), &DS ); if ( numBytes == 0 ) longjmp( err_jmp, (int)errWindowsAPI ); img->opt_for_bmp = 1; if ( numBytes == soDIBSECTION ) { img->width = DS.dsBmih.biWidth; img->height = DS.dsBmih.biHeight; img->bits_per_pixel = (unsigned char)DS.dsBmih.biBitCount; if ( img->bits_per_pixel <= 8 && DS.dsBmih.biClrUsed > 0 ) img->palette_size = (unsigned short)DS.dsBmih.biClrUsed; lpBits = (unsigned char *)DS.dsBm.bmBits; } /* this may be a DDB which must be handled differently */ else if ( numBytes == soBITMAP ) { BITMAP bm; BITMAPINFO bmi; if ( GetObject( hBitmap, sizeof(BITMAP), &bm ) == 0 ) longjmp( err_jmp, (int)errWindowsAPI ); /* DDB with a palette */ if ( bm.bmBitsPixel <= 8 ) longjmp( err_jmp, (int)errInvalidPixelFormat ); img->width = bm.bmWidth; img->height = bm.bmHeight; img->bits_per_pixel = (unsigned char)bm.bmBitsPixel; bmi = InternalCreateBMI( bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, BI_RGB ); lpBits = (unsigned char *)calloc( bm.bmHeight * bm.bmWidthBytes, sizeof(unsigned char) ); if ( lpBits == 0 ) longjmp( err_jmp, (int)errMemoryAllocation ); FreelpBits = 1; hDC = GetDC( hWnd ); if ( GetDIBits(hDC, hBitmap, 0, bm.bmHeight, (void *)lpBits, &bmi, DIB_RGB_COLORS ) == 0 ) longjmp( err_jmp, (int)errWindowsAPI ); ReleaseDC( hWnd, hDC ); hDC = NULL; } else /* I have no idea what this is */ longjmp( err_jmp, (int)errInvalidBitmapHandle ); /* allocate memory */ bmgerr = AllocateBMGImage( img ); if ( bmgerr != BMG_OK ) longjmp( err_jmp, (int)bmgerr ); /* dimensions */ DIBScanWidth = ( img->width * img->bits_per_pixel + 7 )/8; if ( DIBScanWidth % 4 ) DIBScanWidth += 4 - DIBScanWidth % 4; p = img->bits; for ( q = lpBits; q < lpBits + DIBScanWidth * img->height; p += img->scan_width, q += DIBScanWidth ) { memcpy( (void *)p, (void *)q, DIBScanWidth ); } /* "un-blend" the image if requested. NOTE: unblending only works with // bland backgrounds */ if ( remove_alpha > 0 && img->bits_per_pixel == 32 && numBytes == soDIBSECTION ) { unsigned char *color = GetBackgroundColor(); red = color[2]; green = color[1]; blue = color[0]; for ( p = img->bits; p < img->bits + img->scan_width * img->height; p += 4 ) { alpha = p[3]; p[2] = InverseAlphaComp( p[2], alpha, blue); p[1] = InverseAlphaComp( p[1], alpha, green); p[0] = InverseAlphaComp( p[0], alpha, red); } } /* 32-bit DDBs must have the alpha channel set to 0xFF before they are // saved to a file. This may not be true for all devices that generate // 32-bit DDBs. I have only created 32-bit DDBs using an Intense3D Wildcat // 4110 card. The alpha channel was always 0. */ if (img->bits_per_pixel == 32 && numBytes == soBITMAP ) { for ( p = img->bits + 3; p < img->bits + img->scan_width * img->height; p += 4 ) { *p = 0xFF; } } /* create palette if necessary */ if ( img->bits_per_pixel <= 8 ) { hDC = GetDC( hWnd ); hMemDC = CreateCompatibleDC( hDC ); SelectObject( hMemDC, hBitmap ); if ( !GetDIBColorTable( hMemDC, 0, img->palette_size, (RGBQUAD *)img->palette ) ) { longjmp( err_jmp, (int)errWindowsAPI ); } DeleteDC( hMemDC ); ReleaseDC( hWnd, hDC ); } if ( FreelpBits ) free( lpBits ); return BMG_OK; }
/*! Draw current selected card // \param ATL_DRAWINFO& di : */ HRESULT CAxJpgCard::OnDraw(ATL_DRAWINFO& di) { RECT& rc = *(RECT*)di.prcBounds; HDC hdcComp = CreateCompatibleDC(di.hdcDraw); short iType; m_hCurrentImage->get_Type(&iType); ATLASSERT(iType == PICTYPE_BITMAP); //CreateDib(hdcComp); //SelectObject(hdcComp, (HBITMAP)m_hCurrentImage); SelectObject(hdcComp, m_hCurrentBitmap); // draw a contour rectangle if (m_eCardStatus != CSW_ST_MAZZO) Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); rc.left += e_OverLine; rc.right -= e_OverLine; rc.top += e_OverLine; rc.bottom -= e_OverLine; m_rc = rc; switch (m_eCardStatus) { case CSW_ST_DRAWFIRST: // first draw GetDIBColorTable(hdcComp, 0, 256, m_pColors ); //DrawEmpty(rc, di.hdcDraw, hdcComp); //m_eCardStatus = CSW_ST_EMPTY; DrawNormal(rc, di.hdcDraw, hdcComp); m_eCardStatus = CSW_ST_DRAWNORMAL; //DrawAsMazzo(rc, di.hdcDraw, hdcComp); //m_eCardStatus = CSW_ST_MAZZO; //DrawRotated(rc, di.hdcDraw, hdcComp); //m_eCardStatus = CSW_ST_ROTATE90; //::OutputDebugString("Draw First\n"); break; case CSW_ST_MAZZO: // deck draw (mazzo) DrawAsMazzo(rc, di.hdcDraw, hdcComp); //::OutputDebugString("Draw Mazzo\n"); case CSW_ST_DRAWNORMAL: // usual draw DrawNormal(rc, di.hdcDraw, hdcComp); //::OutputDebugString("Draw Normal\n"); break; case CSW_ST_ANIMATETOBLACK: // animate bitmap color to black AnimateToBlack(rc, di.hdcDraw, hdcComp); m_eCardStatus = CSW_ST_EMPTY; //::OutputDebugString("Animate to black\n"); break; case CSW_ST_INVISIBLE: DrawInvisibile(rc, di.hdcDraw, hdcComp); m_eOldStatus = CSW_ST_INVISIBLE; //::OutputDebugString("Control invisible\n"); break; case CSW_ST_ROTATE90: DrawRotated(rc, di.hdcDraw, hdcComp); //::OutputDebugString("Draw rotate 90\n"); break; case CSW_ST_EMPTY: DrawEmpty(rc, di.hdcDraw, hdcComp); //::OutputDebugString("Draw Empty\n"); break; case CSW_ST_RESTORE: DrawOriginalColors(rc, di.hdcDraw, hdcComp); m_eCardStatus = CSW_ST_DRAWNORMAL; //::OutputDebugString("Draw restore\n"); break; case CSW_ST_SELECTED1: DrawSelected(rc, di.hdcDraw, hdcComp,1); m_eCardStatus = CSW_ST_SELECTED1; break; case CSW_ST_SELECTED2: DrawSelected(rc, di.hdcDraw, hdcComp,2); m_eCardStatus = CSW_ST_SELECTED2; break; default: _ASSERT(0); } DeleteDC(hdcComp); return S_OK; }
int BMPanvas::GetPallete(RGBQUAD **pColors, int first,int total) { if(*pColors==NULL) *pColors=new RGBQUAD[total]; return GetDIBColorTable(hdc,first,total,*pColors); }
int CLitePrint::PrintBitmap(CString sPath, EAlign fmt, CSize* dest) { // This code shows how to print a resource bitmap or a .bmp file using StretchDIBits. // The bitmap must not be compressed (BI_RGB compression type, check MSDN). LPBITMAPINFO info; // Structure for storing the DIB information, // it will be used by 'StretchDIBits()' HBITMAP hbit; // Handle to the bitmap to print BITMAP bm; // Structure used for obtaining information // about the bitmap (size, color depth...) int nColors = 0; // Used to store the number of colors the DIB has int sizeinfo = 0; // Will contain the size of info RGBQUAD rgb[256]; // Used to store the DIB color table // The following line loads the bitmap from a file hbit = (HBITMAP) LoadImage(0, sPath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE); // The following line loads the bitmap from resource bitmap //hbit = (HBITMAP) LoadImage(AfxGetInstanceHandle(), // MAKEINTRESOURCE(ResourceIDColor), // IMAGE_BITMAP, // 0, // 0, // LR_CREATEDIBSECTION); // Obtain information about 'hbit' and store it in 'bm' GetObject(hbit, sizeof(BITMAP), (LPVOID) &bm); nColors = (1 << bm.bmBitsPixel); if(nColors > 256) nColors=0; // This is when DIB is 24 bit. // In this case there is not any color table information // Now we need to know how much size we have to give for storing "info" in memory. // This involves the proper BITMAPINFO size and the color table size. // Color table is only needed when the DIB has 256 colors or less. sizeinfo = sizeof(BITMAPINFO) + (nColors * sizeof(RGBQUAD)); // This is the size required info = (LPBITMAPINFO) malloc(sizeinfo); // Storing info in memory // Before 'StretchDIBits()' we have to fill some "info" fields. // This information was stored in 'bm'. info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info->bmiHeader.biWidth = bm.bmWidth; info->bmiHeader.biHeight = bm.bmHeight; info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = bm.bmBitsPixel * bm.bmPlanes; info->bmiHeader.biCompression = BI_RGB; info->bmiHeader.biSizeImage = bm.bmWidthBytes * bm.bmHeight; info->bmiHeader.biXPelsPerMeter = 0; info->bmiHeader.biYPelsPerMeter = 0; info->bmiHeader.biClrUsed = 0; info->bmiHeader.biClrImportant = 0; int xx,yy; if (dest == NULL) { xx = bm.bmWidth; yy = bm.bmHeight; } else { xx = dest->cx; yy = dest->cy; } int xpos; if (fmt == FORMAT_LEFT) xpos = m_info.m_Margins.left; else if (fmt == FORMAT_RIGHT) xpos = m_info.m_DimDraw.cx-m_info.m_Margins.right-xx; else xpos = m_info.m_DimDraw.cx/2 - xx/2; // If the bitmap is a compressed bitmap (BI_RLE for example), the 'biSizeImage' can not // be calculated that way. A call to 'GetDIBits()' will fill the 'biSizeImage' field with // the correct size. // Now for 256 or less color DIB we have to fill the "info" color table parameter if(nColors <= 256) { HBITMAP hOldBitmap; HDC hMemDC = CreateCompatibleDC(NULL); // Creating an auxiliary device context hOldBitmap = (HBITMAP) SelectObject(hMemDC, hbit); // Select 'hbit' in 'it' GetDIBColorTable(hMemDC, 0, nColors, rgb); // Obtaining the color table information // Now we pass this color information to "info" for(int iCnt = 0; iCnt < nColors; ++iCnt) { info->bmiColors[iCnt].rgbRed = rgb[iCnt].rgbRed; info->bmiColors[iCnt].rgbGreen = rgb[iCnt].rgbGreen; info->bmiColors[iCnt].rgbBlue = rgb[iCnt].rgbBlue; } SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); } // Let's get 'StretchDIBiting'! 'pDC' is the printer DC HDC hdc = m_DC.GetSafeHdc(); // Getting a safe handle // Stretching all the bitmap on a destination rectangle of size (size_x, size_y) // and upper left corner at (initial_pos_x, initial_pos_y) StretchDIBits(hdc, xpos, //initial_pos_x, m_info.m_y,//initial_pos_y, xx,//size_x, yy,//size_y, 0, 0, bm.bmWidth, bm.bmHeight, bm.bmBits, info, DIB_RGB_COLORS, SRCCOPY); // This mode, DIB_RGB_COLORS indicate the color table are pure RGB values // The mode DIB_PAL_COLORS indicate the color table items are index to the local palette items DeleteObject(hbit); free(info); return 1; }
/****************************************************************************** * CreateCompatibleBitmap [GDI32.@] * * Creates a bitmap compatible with the DC. * * PARAMS * hdc [I] Handle to device context * width [I] Width of bitmap * height [I] Height of bitmap * * RETURNS * Success: Handle to bitmap * Failure: 0 */ HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height) { HBITMAP hbmpRet = 0; TRACE("(%p,%d,%d) =\n", hdc, width, height); if (GetObjectType( hdc ) != OBJ_MEMDC) { hbmpRet = CreateBitmap(width, height, GetDeviceCaps(hdc, PLANES), GetDeviceCaps(hdc, BITSPIXEL), NULL); } else /* Memory DC */ { DIBSECTION dib; HBITMAP bitmap = GetCurrentObject( hdc, OBJ_BITMAP ); INT size = GetObjectW( bitmap, sizeof(dib), &dib ); if (!size) return 0; if (size == sizeof(BITMAP)) { /* A device-dependent bitmap is selected in the DC */ hbmpRet = CreateBitmap(width, height, dib.dsBm.bmPlanes, dib.dsBm.bmBitsPixel, NULL); } else { /* A DIB section is selected in the DC */ BITMAPINFO *bi; void *bits; /* Allocate memory for a BITMAPINFOHEADER structure and a color table. The maximum number of colors in a color table is 256 which corresponds to a bitmap with depth 8. Bitmaps with higher depths don't have color tables. */ bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); if (bi) { bi->bmiHeader.biSize = sizeof(bi->bmiHeader); bi->bmiHeader.biWidth = width; bi->bmiHeader.biHeight = height; bi->bmiHeader.biPlanes = dib.dsBmih.biPlanes; bi->bmiHeader.biBitCount = dib.dsBmih.biBitCount; bi->bmiHeader.biCompression = dib.dsBmih.biCompression; bi->bmiHeader.biSizeImage = 0; bi->bmiHeader.biXPelsPerMeter = dib.dsBmih.biXPelsPerMeter; bi->bmiHeader.biYPelsPerMeter = dib.dsBmih.biYPelsPerMeter; bi->bmiHeader.biClrUsed = dib.dsBmih.biClrUsed; bi->bmiHeader.biClrImportant = dib.dsBmih.biClrImportant; if (bi->bmiHeader.biCompression == BI_BITFIELDS) { /* Copy the color masks */ CopyMemory(bi->bmiColors, dib.dsBitfields, 3 * sizeof(DWORD)); } else if (bi->bmiHeader.biBitCount <= 8) { /* Copy the color table */ GetDIBColorTable(hdc, 0, 256, bi->bmiColors); } hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0); HeapFree(GetProcessHeap(), 0, bi); } } } TRACE("\t\t%p\n", hbmpRet); return hbmpRet; }
void CImgBitsDIB::Optimize() { RGBQUAD rgbSolid; if(_iTrans>=0 && !_pvMaskBits) { if(!!ComputeTransMask(0, _yHeightValid, _iTrans, _iTrans)) { return; } } if(!_pvMaskBits) { // If we still don't have a mask, it means there were no transparent bits, so dump _iTrans _iTrans = -1; // check 8-bit images to see if they're solid if(_iBitCount==8 && _pvImgBits) { DWORD dwTest; DWORD* pdw; int cdw; int cLines; dwTest = *(BYTE*)_pvImgBits; dwTest = dwTest | dwTest << 8; dwTest = dwTest | dwTest << 16; pdw = (DWORD*)_pvImgBits; for(cLines=_yHeight; cLines; cLines-=1) { cdw = CbLine() / 4; for(;;) { if(cdw == 1) { // Assumes little endian; shift in other direction for big endian if((dwTest^*pdw) << (8*(3-(0x3&(_xWidth-1))))) { goto NotSolid; } pdw += 1; break; } else if(*pdw != dwTest) { goto NotSolid; } cdw -= 1; pdw += 1; } } // It's solid! So extract the color dwTest &= 0xFF; if(_pbmih) { rgbSolid = ((RGBQUAD*)(_pbmih+1))[dwTest]; } else if(_fPalColors) { rgbSolid = g_rgbHalftone[dwTest]; } else if(_hbmImg) { HDC hdcMem; HBITMAP hbmSav; hdcMem = GetMemoryDC(); if(!hdcMem) { goto NotSolid; } hbmSav = (HBITMAP) SelectObject(hdcMem, _hbmImg); GetDIBColorTable(hdcMem, dwTest, 1, &rgbSolid); SelectObject(hdcMem, hbmSav); ReleaseMemoryDC(hdcMem); } else { goto NotSolid; } // And set up the data _fSolid = TRUE; _crSolid = (rgbSolid.rgbRed) | (rgbSolid.rgbGreen<<8) | (rgbSolid.rgbBlue<<16); FreeMemory(); } } else { // If we have a mask, check to see if the entire image is transparent; if so, dump the data int cdw; int cLines; DWORD* pdw; DWORD dwLast; BYTE bLast; Assert(!(CbLineMask() & 0x3)); bLast = (0xFF << (7-(0x7&(_xWidth-1)))); // Assumes little endian; shift in other direction for big endian dwLast = (unsigned)(0x00FFFFFF | (bLast<<24))>>(8*(3-(0x3&(((7+_xWidth)>>3)-1)))); pdw = (DWORD*)_pvMaskBits; for(cLines=_yHeight; cLines; cLines-=1) { cdw = CbLineMask() / 4; for(;;) { if(cdw == 1) { // Assumes little endian; shift in other direction for big endian if(*pdw & dwLast) { goto NotAllTransparent; } pdw += 1; break; } else if(*pdw) { goto NotAllTransparent; } cdw -= 1; pdw += 1; } } FreeMemory(); return; } NotSolid: NotAllTransparent: ; }
/** * Grabs a frame from gdi (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the grabbed frame * @return frame size in bytes */ static int gdigrab_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct gdigrab *gdigrab = s1->priv_data; HDC dest_hdc = gdigrab->dest_hdc; HDC source_hdc = gdigrab->source_hdc; RECT clip_rect = gdigrab->clip_rect; AVRational time_base = gdigrab->time_base; int64_t time_frame = gdigrab->time_frame; BITMAPFILEHEADER bfh; int file_size = gdigrab->header_size + gdigrab->frame_size; int64_t curtime, delay; /* Calculate the time of the next frame */ time_frame += INT64_C(1000000); /* Run Window message processing queue */ if (gdigrab->show_region) gdigrab_region_wnd_update(s1, gdigrab); /* wait based on the frame rate */ for (;;) { curtime = av_gettime(); delay = time_frame * av_q2d(time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(time_base)) { time_frame += INT64_C(1000000); } break; } if (s1->flags & AVFMT_FLAG_NONBLOCK) { return AVERROR(EAGAIN); } else { av_usleep(delay); } } if (av_new_packet(pkt, file_size) < 0) return AVERROR(ENOMEM); pkt->pts = curtime; /* Blit screen grab */ if (!BitBlt(dest_hdc, 0, 0, clip_rect.right - clip_rect.left, clip_rect.bottom - clip_rect.top, source_hdc, clip_rect.left, clip_rect.top, SRCCOPY | CAPTUREBLT)) { WIN32_API_ERROR("Failed to capture image"); return AVERROR(EIO); } if (gdigrab->draw_mouse) paint_mouse_pointer(s1, gdigrab); /* Copy bits to packet data */ bfh.bfType = 0x4d42; /* "BM" in little-endian */ bfh.bfSize = file_size; bfh.bfReserved1 = 0; bfh.bfReserved2 = 0; bfh.bfOffBits = gdigrab->header_size; memcpy(pkt->data, &bfh, sizeof(bfh)); memcpy(pkt->data + sizeof(bfh), &gdigrab->bmi.bmiHeader, sizeof(gdigrab->bmi.bmiHeader)); if (gdigrab->bmi.bmiHeader.biBitCount <= 8) GetDIBColorTable(dest_hdc, 0, 1 << gdigrab->bmi.bmiHeader.biBitCount, (RGBQUAD *) (pkt->data + sizeof(bfh) + sizeof(gdigrab->bmi.bmiHeader))); memcpy(pkt->data + gdigrab->header_size, gdigrab->buffer, gdigrab->frame_size); gdigrab->time_frame = time_frame; return gdigrab->header_size + gdigrab->frame_size; }
int SmartStretchDIBits( HDC hdc, int xD, int yD, int dxD, int dyD, int xS, int yS, int dxS, int dyS, LPVOID lpBits, LPBITMAPINFO lpbi, UINT wUsage, DWORD rop) { LPBYTE lpBitsNew; UINT bpp; RGBQUAD rgb; LPBITMAPINFOHEADER lpbiNew = NULL; int i; /* * thunk to USER32 */ UserAssert(rop == SRCCOPY); UserAssert(wUsage == DIB_RGB_COLORS); UserAssert(xS == 0 && yS == 0); if ((GetDIBColorTable(hdc, 0, 1, &rgb) != 1) && (dxD != dxS || dyD != dyS) && // 1:1 stretch just call GDI (dxD >= dxS/2) && (dyD >= dyS/2) && // less than 1:2 shrink call GDI (lpbi->bmiHeader.biCompression == 0) && // must be un-compressed (lpbi->bmiHeader.biBitCount == 4 || // input must be 4,8,24 lpbi->bmiHeader.biBitCount == 8 || lpbi->bmiHeader.biBitCount == 24)) { bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); bpp = (bpp > 8 ? 24 : 8); lpbiNew = (LPBITMAPINFOHEADER)UserLocalAlloc(0, sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)) + (UINT)((((dxD * bpp) / 8) + 3) & ~3) * (UINT)dyD); if (lpbiNew) { *lpbiNew = lpbi->bmiHeader; lpbiNew->biWidth = dxD; lpbiNew->biHeight = dyD; lpbiNew->biBitCount = bpp; lpBitsNew = (LPBYTE)lpbiNew + sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)); if (ScaleDIB((LPBITMAPINFOHEADER)lpbi, (LPVOID)lpBits, lpbiNew, lpBitsNew)) { lpbi = (LPBITMAPINFO)lpbiNew; lpBits = lpBitsNew; dxS = dxD; dyS = dyD; } } } i = StretchDIBits(hdc, xD, yD, dxD, dyD, xS, yS, dxS, dyS, lpBits, lpbi, wUsage, rop); if (lpbiNew) UserLocalFree(lpbiNew); return i; }
HRESULT CImgBitsDIB::SaveAsBmp(IStream* pStm, BOOL fFileHeader) { HRESULT hr = S_OK; HBITMAP hbmSavDst = NULL; HDC hdcDibDst = NULL; int adjustedwidth; DIBSECTION ds; DWORD dw; int nColors; DWORD dwColors; DWORD dwImage; int cBitsPerPix; CImgBitsDIB* pibd = NULL; HBITMAP hbm; // 1. Get a DIBSECTION structure even if it means allocating another CImgBitsDIB hbm = _hbmImg; if(!hbm || !GetObject(_hbmImg, sizeof(DIBSECTION), &ds)) { RECT rc; int iBitCount; RGBQUAD* prgb; int nColors; // Otherwise, duplicate what we have. iBitCount = _iBitCount; if(_pbmih && iBitCount<=8) { prgb = (RGBQUAD*)(_pbmih + 1); nColors = _pbmih->biClrUsed ? _pbmih->biClrUsed : (1<<iBitCount); } else if(iBitCount == 8) { prgb = g_rgbHalftone; nColors = 256; } else { prgb = NULL; nColors = 0; } pibd = new CImgBitsDIB(); if(!pibd) { goto OutOfMemory; } hr = pibd->AllocDIBSection(iBitCount, _xWidth, _yHeight, prgb, nColors, _iTrans); if(hr) { goto Cleanup; } hbm = pibd->GetHbm(); Assert(hbm); hdcDibDst = GetMemoryDC(); if(!hdcDibDst) { goto OutOfMemory; } rc.left = 0; rc.top = 0; rc.right = _xWidth; rc.bottom = _yHeight; hbmSavDst = (HBITMAP)SelectObject(hdcDibDst, hbm); StretchBlt(hdcDibDst, &rc, &rc, SRCCOPY, DRAWIMAGE_NHPALETTE|DRAWIMAGE_NOTRANS); if(!GetObject(hbm, sizeof(DIBSECTION), &ds)) { goto OutOfMemory; } } // 2. Save it out cBitsPerPix = ds.dsBmih.biBitCount; Assert(cBitsPerPix==1 || cBitsPerPix==4 || cBitsPerPix==8 || cBitsPerPix==16 || cBitsPerPix==24 || cBitsPerPix==32); adjustedwidth = ((ds.dsBmih.biWidth * cBitsPerPix + 31) & ~31) / 8; nColors = ds.dsBmih.biClrUsed; if((nColors==0) && (cBitsPerPix<=8)) { nColors = 1 << cBitsPerPix; } Assert(ds.dsBmih.biCompression!=BI_BITFIELDS || nColors==0); dwColors = nColors*sizeof(RGBQUAD) + (ds.dsBmih.biCompression==BI_BITFIELDS?3*sizeof(DWORD):0); dwImage = ds.dsBmih.biHeight * adjustedwidth; if(fFileHeader) { BITMAPFILEHEADER bf; bf.bfType = 0x4D42; // "BM" bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwColors; bf.bfSize = bf.bfOffBits + dwImage; bf.bfReserved1 = 0; bf.bfReserved2 = 0; hr = pStm->Write(&bf, sizeof(bf), &dw); if(hr) { goto Cleanup; } } hr = pStm->Write(&(ds.dsBmih), sizeof(BITMAPINFOHEADER), &dw); if(hr) { goto Cleanup; } if(nColors > 0) { RGBQUAD argb[256]; if(!hdcDibDst) { hdcDibDst = GetMemoryDC(); if(!hdcDibDst) { goto OutOfMemory; } hbmSavDst = (HBITMAP)SelectObject(hdcDibDst, hbm); } GetDIBColorTable(hdcDibDst, 0, min(256, nColors), argb); hr = pStm->Write(argb, dwColors, &dw); if(hr) { goto Cleanup; } } else if(ds.dsBmih.biCompression == BI_BITFIELDS) { hr = pStm->Write(ds.dsBitfields, dwColors, &dw); if(hr) { goto Cleanup; } } hr = pStm->Write(ds.dsBm.bmBits, dwImage, &dw); Cleanup: if(hbmSavDst) { SelectObject(hdcDibDst, hbmSavDst); } if(hdcDibDst) { ReleaseMemoryDC(hdcDibDst); } if(pibd) { delete pibd; } RRETURN(hr); OutOfMemory: hr = E_OUTOFMEMORY; goto Cleanup; }
static int MyPaintSplash (HWND pmSplashWindow, BOOL pmDraw) { SplashWindowInfoPtr myInfo; HDC myDisplayContext, myMemDC; PAINTSTRUCT myPaintStruct; BITMAP myBitmap; HBITMAP myOldBitmap; HPALETTE myPalette, myOldPalette; POINT myPoint, myOrigin; int myY; myInfo = MyGetSplashWindowInfo (pmSplashWindow); myDisplayContext = BeginPaint (pmSplashWindow, &myPaintStruct); if (pmDraw && myInfo -> usePicture) { myMemDC = CreateCompatibleDC (NULL); myOldBitmap = SelectBitmap (myMemDC, myInfo -> picture); GetObject (myInfo -> picture, sizeof(BITMAP), (LPSTR) &myBitmap); myPoint.x = myBitmap.bmWidth; myPoint.y = myBitmap.bmHeight; DPtoLP (myDisplayContext, &myPoint, 1); myOrigin.x = 0; myOrigin.y = 0; DPtoLP (myMemDC, &myOrigin, 1); // // We need to perform all sorts of stuff to get the palette right... // // If the DIBSection is 256 color or less, it has a color table if ((myBitmap.bmBitsPixel * myBitmap.bmPlanes) <= 8) { RGBQUAD myClrTbl [256]; LPLOGPALETTE myLogPal; WORD cnt; // Get the DIBSection's color table GetDIBColorTable (myMemDC, 0, 256, myClrTbl); // Create a palette from the color tabl myLogPal = (LOGPALETTE *) malloc (sizeof(LOGPALETTE) + (256 * sizeof(PALETTEENTRY))); myLogPal -> palVersion = 0x300; myLogPal -> palNumEntries = 256; for (cnt = 0 ; cnt < 256 ; cnt++) { myLogPal -> palPalEntry [cnt].peRed = myClrTbl [cnt].rgbRed; myLogPal -> palPalEntry [cnt].peGreen = myClrTbl [cnt].rgbGreen; myLogPal -> palPalEntry [cnt].peBlue = myClrTbl [cnt].rgbBlue; myLogPal -> palPalEntry [cnt].peFlags = 0; } myPalette = CreatePalette (myLogPal); free (myLogPal); // Select Palette myOldPalette = SelectPalette (myDisplayContext, myPalette, FALSE); RealizePalette (myDisplayContext); } if (gProgram.isTuring) { BitBlt (myDisplayContext, 0, 0, myPoint.x, myPoint.y, myMemDC, myOrigin.x, myOrigin.y, SRCCOPY); } else { BitBlt (myDisplayContext, MARGIN, 0, myPoint.x, myPoint.y, myMemDC, myOrigin.x, myOrigin.y, SRCCOPY); } SelectObject (myMemDC, myOldBitmap); if ((myBitmap.bmBitsPixel * myBitmap.bmPlanes) <= 8) { SelectPalette (myDisplayContext, myOldPalette, FALSE); DeleteObject (myPalette); } DeleteDC (myMemDC); } // Place Ministry message over top of the Sun if (gProgram.assistedByIBM && gProgram.isTuring) { // // Output "Ministry of Education License Message" // myY = LARGE_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> versionFont, myInfo -> miniEdMsg [0], &myY, pmDraw, FALSE); myY += SMALL_GAP; MyDrawStrings (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, &myInfo -> miniEdMsg [1], 9, &myY, pmDraw, FALSE); } // if (gProgram.assistedByIBM) if (myInfo -> usePicture) { // The starting Y position myY = myInfo -> bitmapHeight + MARGIN; } else { myY = SMALL_GAP; MyDrawStrings (myInfo, myDisplayContext, myInfo -> productNameFont, myInfo -> productNameMsg, myInfo -> productNameLines, &myY, pmDraw, TRUE); myY += LARGE_GAP; } // // Output "Created By Holt Software Associates Inc." // MyDrawString (myInfo, myDisplayContext, myInfo -> createdByFont, myInfo -> createdByMsg, &myY, pmDraw, TRUE); if (gProgram.assistedByIBM && gProgram.isJava) { // // Output "Development Assisted by IBM Corp." // MyDrawString (myInfo, myDisplayContext, myInfo -> createdByFont, myInfo -> assistedByMsg, &myY, pmDraw, TRUE); } // if (gProgram.assistedByIBM) // // // Output "Lead Programmer: Tom West" // if (gProgram.isJava) { MyDrawString (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> leadProgrammerMsg, &myY, pmDraw, TRUE); } // if (gProgram.isJava) // // Output version number // myY += SMALL_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> versionFont, myInfo -> versionString, &myY, pmDraw, TRUE); // // Output install kind specific info if (gProgram.miniVersion) { // // Output: Licensed to xxx. // This version cannot compile programs of greater than 100 lines in length // myY += SMALL_GAP; MyDrawStrings (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> miniMsg, 3, &myY, pmDraw, TRUE); } else if (gProgram.installKind == INSTALL_KIND_EVAL) { // // Output: This version is for personal evaluation purposes only. // It may not be redistributed or used for teaching purposes. // See the "Help" menu for information on obtaining Ready. // This version is time limited and will not execute Java programs after xxx // or // // Output: This version is for personal evaluation purposes only. // It may not be redistributed or used for teaching purposes. // See the "Help" menu for information on obtaining Ready. // This demonstration version of the software is restricted and // (1) Cannot save programs, // (2) Cannot compile programs of greater than 100 lines in length, and // (3) Will not execute programs after xxx // myY += SMALL_GAP; if (gProgram.restrictedVersion) { MyDrawStrings (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> evalMsg, 3, &myY, pmDraw, TRUE); myY += SMALL_GAP; MyDrawStrings (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> restrictMsg, 4, &myY, pmDraw, TRUE); } else { MyDrawStrings (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> evalMsg, 4, &myY, pmDraw, TRUE); } } else if (gProgram.installKind == INSTALL_KIND_BETA) { // // Output: This version is for personal beta test purposes only. // It may not be redistributed or used for teaching purposes. // Please report all bugs found in this software to [email protected] // This version of the software will not execute programs after xxx // myY += SMALL_GAP; MyDrawStrings (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> betaMsg, 4, &myY, pmDraw, TRUE); } else if (gProgram.installKind == INSTALL_KIND_PERSONAL) { myY += SMALL_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> personalMsg, &myY, pmDraw, TRUE); } else if (gProgram.installKind == INSTALL_KIND_SITE) { myY += SMALL_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> siteMsg, &myY, pmDraw, TRUE); } else if (gProgram.installKind == INSTALL_KIND_REDISTRIB) { myY += SMALL_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> chiefProgrammerFont, myInfo -> redistribMsg, &myY, pmDraw, TRUE); } if (gProgram.isJava) { // // Output "Using IBM's Jikes Java Compiler" // myY += SMALL_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> usingJikesFont, myInfo -> usingJikesMsg, &myY, pmDraw, TRUE); myY += SMALL_GAP; if (gProgram.operatingSystem == WIN_95) { MyDrawString (myInfo, myDisplayContext, myInfo -> trademarkFont, myInfo -> win95Msg, &myY, pmDraw, TRUE); } else { MyDrawString (myInfo, myDisplayContext, myInfo -> trademarkFont, myInfo -> jreLevelMsg, &myY, pmDraw, TRUE); } // // Output trademark information // myY += SMALL_GAP; MyDrawString (myInfo, myDisplayContext, myInfo -> trademarkFont, myInfo -> trademarkMsg, &myY, pmDraw, TRUE); } // if (gProgram.isJava) EndPaint (pmSplashWindow, &myPaintStruct); return myY; } // MyPaintSplash
HRESULT CImgBitsDIB::AllocCopyBitmap(HBITMAP hbm, BOOL fPalColors, LONG lTrans) { HRESULT hr; LONG iBitCount; struct { BITMAPINFOHEADER bmih; union { RGBQUAD rgb[256]; WORD windex[256]; DWORD dwbc[3]; }; } header; HDC hdc; hdc = GetMemoryDC(); if(!hdc) { return E_OUTOFMEMORY; } memset(&header, 0, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256); header.bmih.biSize = sizeof(BITMAPINFOHEADER); GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO*)&header, fPalColors?DIB_PAL_COLORS:DIB_RGB_COLORS); // A second call to GetDIBits should get the color table if any, but it doesn't work on Win95, so we use // GetDIBColorTable instead (dbau) if(header.bmih.biBitCount <= 8) { HBITMAP hbmSav; hbmSav = (HBITMAP)SelectObject(hdc, hbm); GetDIBColorTable(hdc, 0, 1<<header.bmih.biBitCount, header.rgb); SelectObject(hdc, hbmSav); } iBitCount = header.bmih.biBitCount; if(iBitCount == 16) { if(header.bmih.biCompression!=BI_BITFIELDS || header.dwbc[0]!=MASK565_0 || header.dwbc[1]!=MASK565_1 || header.dwbc[2]!=MASK565_2) { iBitCount = 15; } } BOOL fColorTable = (!fPalColors && iBitCount<=8); if(fColorTable) { hr = AllocDIB(iBitCount, header.bmih.biWidth, header.bmih.biHeight, header.rgb, 1<<iBitCount, lTrans, lTrans==-1); } else { hr = AllocDIB(iBitCount, header.bmih.biWidth, header.bmih.biHeight, NULL, 0, -1, TRUE); } GetDIBits(hdc, hbm, 0, header.bmih.biHeight, GetBits(), (BITMAPINFO*)&header, fPalColors?DIB_PAL_COLORS:DIB_RGB_COLORS); ReleaseMemoryDC(hdc); return S_OK; }
// Draw the src rect of the specified image into the dest rect of the hdc void CImgBitsDIB::StretchBlt(HDC hdc, RECT* prcDst, RECT* prcSrc, DWORD dwRop, DWORD dwFlags) { HDC hdcDib = NULL; HBITMAP hbmSav = NULL; int xDst = prcDst->left; int yDst = prcDst->top; int xDstWid = prcDst->right - xDst; int yDstHei = prcDst->bottom - yDst; int xSrc = prcSrc->left; int ySrc = prcSrc->top; int xSrcWid = prcSrc->right - xSrc; int ySrcHei = prcSrc->bottom - ySrc; int yUseHei = _yHeight; // Cases in which there is nothing to draw if((!_pvImgBits && !_pvMaskBits && !_fSolid) || _yHeightValid==0) { return; } if(xDstWid<=0 || xSrcWid<=0 || _xWidth<=0 || yDstHei<=0 || ySrcHei<=0 || _yHeight<=0) { return; } if(dwRop!=SRCCOPY && (_pvMaskBits || _iTrans>=0)) { return; } // Step 1: Limit the source and dest rectangles to the visible area only. if(_yHeightValid>0 && _yHeightValid<_yHeight) { yUseHei = _yHeightValid; } if(xSrc < 0) { xDst += MulDivQuick(-xSrc, xDstWid, xSrcWid); xDstWid = prcDst->right - xDst; xSrcWid += xSrc; xSrc = 0; if(xDstWid<=0 || xSrcWid<=0) { return; } } if(ySrc < 0) { yDst += MulDivQuick(-ySrc, yDstHei, ySrcHei); yDstHei = prcDst->bottom - yDst; ySrcHei += ySrc; ySrc = 0; if(yDstHei<=0 || ySrcHei<=0) { return; } } if(xSrc+xSrcWid > _xWidth) { xDstWid = MulDivQuick(xDstWid, _xWidth-xSrc, xSrcWid); xSrcWid = _xWidth - xSrc; if(xDstWid<=0 || xSrcWid<=0) { return; } } if(ySrc+ySrcHei > yUseHei) { yDstHei = MulDivQuick(yDstHei, yUseHei-ySrc, ySrcHei); ySrcHei = yUseHei - ySrc; if(yDstHei<=0 || ySrcHei<=0) { return; } } // For the mirrored case, we need flip then offset. if(_fNeedMirroring) { // We need to handle clipping correctly and give a right-to-left tiling effect. // Let's take the "opposite" slice of the source. // The maximum will be the whole image. xSrc = - xSrc +_xWidth - xSrcWid; xDst += xDstWid - 1; xDstWid = - xDstWid; } // Optimization: if solid, just patblt the color if(_fSolid) { // Turn on the palette relative bit for palettized devices in order to ensure that dithering // doesn't happen here. The main reason is that is looks ugly, but more importantly we aren't // prepared to seam multiple copies of the image so that the dithering looks smooth. PatBltBrush(hdc, xDst, yDst, xDstWid, yDstHei, PATCOPY, _crSolid|g_crPaletteRelative); return; } SetStretchBltMode(hdc, COLORONCOLOR); // Step 2: For tranparent images, use mask to whiten drawing area if(_pvMaskBits || _iTrans>=0) { if(dwFlags & DRAWIMAGE_NOTRANS) { goto NoTransparency; } if(GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASPRINTER) { // No transparency for printers that we know lie about their support for transparency. int iEscapeFunction = POSTSCRIPT_PASSTHROUGH; THREADSTATE* pts = GetThreadState(); if(Escape(hdc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&iEscapeFunction, NULL)) { // Skip transparency unless we are a mask-only image if(_pvImgBits || !_pvMaskBits) { goto NoTransparency; } } } if(_pvMaskBits) { // 1-bit mask case if(_hbmMask) { // We have an HBITMAP, not just bits Assert(!hdcDib && !hbmSav); hdcDib = GetMemoryDC(); if(!hdcDib) { goto Cleanup; } // Special case: use MaskBlt for the whole thing on NT if(xSrcWid==xDstWid && ySrcHei==yDstHei && _hbmImg) { hbmSav = (HBITMAP)SelectObject(hdcDib, _hbmImg); MaskBlt(hdc, xDst, yDst, xDstWid, yDstHei, hdcDib, xSrc, ySrc, _hbmMask, xSrc, ySrc, 0xAACC0020); goto Cleanup; } hbmSav = (HBITMAP)SelectObject(hdcDib, _hbmMask); if(!_pvImgBits) { // a mask-only one-bit image: just draw the "1" bits as black ::StretchBlt(hdc, xDst, yDst, xDstWid, yDstHei, hdcDib, xSrc, ySrc, xSrcWid, ySrcHei, MERGEPAINT); } else { // transparent mask: draw the "1" bits as white ::StretchBlt(hdc, xDst, yDst, xDstWid, yDstHei, hdcDib, xSrc, ySrc, xSrcWid, ySrcHei, SRCPAINT); } } else { // We have just bits, not an HBITMAP struct { BITMAPINFOHEADER bmih; union { RGBQUAD rgb[2]; WORD windex[2]; }; } bmiMask; // construct mask header memset(&bmiMask, 0, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*2); bmiMask.bmih.biSize = sizeof(BITMAPINFOHEADER); bmiMask.bmih.biWidth = _xWidth; bmiMask.bmih.biHeight = _yHeight; bmiMask.bmih.biPlanes = 1; bmiMask.bmih.biBitCount = 1; if(!_pvImgBits) { // a mask-only one-bit image: just draw the "1" bits as black bmiMask.rgb[0] = g_rgbWhite; StretchDIBits(hdc, xDst, yDst, xDstWid, yDstHei, xSrc, _yHeight-ySrc-ySrcHei, xSrcWid, ySrcHei, _pvMaskBits, (BITMAPINFO*)&bmiMask, DIB_RGB_COLORS, SRCAND); } else if(_iBitCount<=8 && _fPalColors && !(dwFlags&DRAWIMAGE_NHPALETTE)) { // this setup only occurs on an 8-bit palettized display; we can use DIB_PAL_COLORS bmiMask.windex[1] = 255; StretchDIBits(hdc, xDst, yDst, xDstWid, yDstHei, xSrc, _yHeight-ySrc-ySrcHei, xSrcWid, ySrcHei, _pvMaskBits, (BITMAPINFO*)&bmiMask, DIB_PAL_COLORS, SRCPAINT); } else { bmiMask.rgb[1] = g_rgbWhite; StretchDIBits(hdc, xDst, yDst, xDstWid, yDstHei, xSrc, _yHeight-ySrc-ySrcHei, xSrcWid, ySrcHei, _pvMaskBits, (BITMAPINFO *)&bmiMask, DIB_RGB_COLORS, SRCPAINT); } } } else { // 1- 4- or 8-bit mask case (with _iTrans) long cTable = 1 << _iBitCount; Assert(_iTrans >= 0); Assert(_iTrans < cTable); Assert(_iBitCount <= 8); if(_hbmImg) { // We have an HBITMAP, not just bits RGBQUAD argbOld[256]; RGBQUAD argbNew[256]; memset(argbNew, 0, sizeof(RGBQUAD)*cTable); argbNew[_iTrans] = g_rgbWhite; Assert(!hdcDib && !hbmSav); hdcDib = GetMemoryDC(); if(!hdcDib) { goto Cleanup; } hbmSav = (HBITMAP)SelectObject(hdcDib, _hbmImg); // HBM case: we need to change the color table, which can only be done one-at-a time g_csImgTransBlt.Enter(); Verify(GetDIBColorTable(hdcDib, 0, cTable, argbOld) > 0); Verify(SetDIBColorTable(hdcDib, 0, cTable, argbNew) == (unsigned)cTable); ::StretchBlt(hdc, xDst, yDst, xDstWid, yDstHei, hdcDib, xSrc, ySrc, xSrcWid, ySrcHei, MERGEPAINT); Verify(SetDIBColorTable(hdcDib, 0, cTable, argbOld) == (unsigned)cTable); g_csImgTransBlt.Leave(); } else { // We have just bits, not an HBITMAP struct { BITMAPINFOHEADER bmih; RGBQUAD rgb[256]; } bmiMask; // construct mask header memset(&bmiMask, 0, sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*cTable)); bmiMask.bmih.biSize = sizeof(BITMAPINFOHEADER); bmiMask.bmih.biWidth = _xWidth; bmiMask.bmih.biHeight = _yHeight; bmiMask.bmih.biPlanes = 1; bmiMask.bmih.biBitCount = _iBitCount; bmiMask.rgb[_iTrans] = g_rgbWhite; StretchDIBits(hdc, xDst, yDst, xDstWid, yDstHei, xSrc, _yHeight-ySrc-ySrcHei, xSrcWid, ySrcHei, _pvImgBits, (BITMAPINFO*)&bmiMask, DIB_RGB_COLORS, MERGEPAINT); } } // prepare for transparent blt: area to be painted is now whitened, so AND-blt on top of it dwRop = SRCAND; } NoTransparency: // Step 3: Draw the image bits if(_pvImgBits) { if(dwFlags & DRAWIMAGE_MASKONLY) { goto Cleanup; } if(_hbmImg) { // The normal case (not to a Win95 printer): call StretchBlt if(!hdcDib) { hdcDib = GetMemoryDC(); if(!hdcDib) { goto Cleanup; } } HBITMAP hbmOld; hbmOld = (HBITMAP)SelectObject(hdcDib, _hbmImg); if(!hbmSav) { hbmSav = hbmOld; } ::StretchBlt(hdc, xDst, yDst, xDstWid, yDstHei, hdcDib, xSrc, ySrc, xSrcWid, ySrcHei, dwRop); } else { // We have just bits, not an HBITMAP if(!_pbmih) { // No color table header: cobble up a standard header [perhaps these should just be globally cached?] struct { BITMAPINFOHEADER bmih; union { WORD windex[256]; RGBQUAD rgb[256]; DWORD bfmask[3]; }; } bmi; DWORD dwDibMode = DIB_RGB_COLORS; // construct mask header memset(&bmi, 0, sizeof(BITMAPINFOHEADER)+(_iBitCount>8?sizeof(DWORD)*3:sizeof(WORD)*(_iBitCount<<1))); bmi.bmih.biSize = sizeof(BITMAPINFOHEADER); bmi.bmih.biWidth = _xWidth; bmi.bmih.biHeight = _yHeight; bmi.bmih.biPlanes = 1; bmi.bmih.biBitCount = _iBitCount + (_iBitCount==15); if(_iBitCount == 4) { // Thanks to Steve Palmer: fix VGA color rendering bmi.bmih.biClrUsed = 16; bmi.bmih.biClrImportant = 16; CopyColorsFromPaletteEntries(bmi.rgb, g_peVga, 16); } else if(_iBitCount <= 8) { if(dwFlags & DRAWIMAGE_NHPALETTE) { // If being drawn on an <= 8-bit surface from a filter, we can make no assumptions about // the selected palette, so use RGB_COLORS LONG c; c = (1 << (_iBitCount-1)); memcpy(bmi.rgb, g_rgbHalftone, c*sizeof(RGBQUAD)); memcpy(bmi.rgb+c, g_rgbHalftone+256-c, c*sizeof(RGBQUAD)); } else { // internal draw, no color table with _iBitCount <= 8 means that the palette selected into hdc // is our standard 8-bit halftone palette and we can use DIB_PAL_COLORS LONG c; LONG d; WORD* pwi; dwDibMode = DIB_PAL_COLORS; for(c=(1<<(_iBitCount-1)),pwi=bmi.windex+c; c; *(--pwi)=(--c)); for(c=(1<<(_iBitCount-1)),pwi=bmi.windex+c*2,d=256; c; --c,*(--pwi)=(--d)); } } else if(_iBitCount == 16) { // sixteen-bit case: fill in the bitfields mask for 565 bmi.bmih.biCompression = BI_BITFIELDS; bmi.bfmask[0] = MASK565_0; bmi.bfmask[1] = MASK565_1; bmi.bfmask[2] = MASK565_2; } StretchDIBits(hdc, xDst, yDst, xDstWid, yDstHei, xSrc, _yHeight-ySrc-ySrcHei, xSrcWid, ySrcHei, _pvImgBits, (BITMAPINFO*)&bmi, dwDibMode, dwRop); } else { StretchDIBits(hdc, xDst, yDst, xDstWid, yDstHei, xSrc, _yHeight-ySrc-ySrcHei, xSrcWid, ySrcHei, _pvImgBits, (BITMAPINFO*)_pbmih, DIB_RGB_COLORS, dwRop); } } } Cleanup: if(hbmSav) { SelectObject(hdcDib, hbmSav); } if(hdcDib) { ReleaseMemoryDC(hdcDib); } }