Esempio n. 1
0
/******************************************************************************
 * 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;
    }
}
Esempio n. 2
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
// 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;
}
Esempio n. 8
0
/////////////////////////////////////////////////////////////////////////////
//
// 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 );
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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);
      }
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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);
        }
    }
}
Esempio n. 15
0
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++;
							}

						}
					}
Esempio n. 16
0
/***********************************************************************
 *           WinGGetDIBColorTable   (WING32.@)
 */
UINT WINAPI WinGGetDIBColorTable( HDC hdc, UINT start, UINT end, RGBQUAD *colors )
{
    return GetDIBColorTable( hdc, start, end, colors );
}
Esempio n. 17
0
/*******************************************************************************
// 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;
}
Esempio n. 18
0
/*! 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;
}
Esempio n. 19
0
int BMPanvas::GetPallete(RGBQUAD **pColors, int first,int total)
{
    if(*pColors==NULL) *pColors=new RGBQUAD[total];
    return GetDIBColorTable(hdc,first,total,*pColors);
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
/******************************************************************************
 * 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;
}
Esempio n. 22
0
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:
    ;
}
Esempio n. 23
0
/**
 * 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;
}
Esempio n. 24
0
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;
}
Esempio n. 25
0
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;
}
Esempio n. 26
0
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
Esempio n. 27
0
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;
}
Esempio n. 28
0
// 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);
    }
}