Is there a way to get Alpha on DIB?

I am exploring the possibility to render a main windows dialog using OpenGL which could have 32-bit per pixel (8-bit alpha, 24-bit color).

So, far I get the render to work and display to work, but the alpha byte stay 0x00. The alpha is working in OpenGL and as well on my main window, as I could get some alpha effect when I process this byte in software. However, this slow down the render and I cannot retrieve what was the exact alpha-value from the OpenGL buffer.

The result currently look like that:

But as you can see, the triangles render in OpenGL is not in transparent but most likely mix in a more like a add-value… where on the black it look nice, on the white, you don’t see the triangle but all white.

Looking to the alpha byte they are all zeroes. If I replace the alpha when 0, to a value related with R,G,B… I get a result that show that the win32 stuff is working.

This code work in windows XP up to windows 8. For a windows size of 800x600 pixels, I get a FPS that is currently not as good as I would like… even for this simple example on a good PC.

I think it would be very interesting if I can first get the alpha byte set in the DIB… then to check how I can improve the FPS for slow end machine.

I have start to look at DirectX stuff, to see what could be done. The code below show nothing using DirectX… as I am looking how to get the render be into buffer which would be render on a windows. I am looking just to see what will be the performance. But, I would prefer OpenGL as it may work on Linux as well.

Here is my code below… type of project win32 c++ in MSVC 2010.

So, if someone has an idea how to modify it to get the alpha byte being copy… let me know!


#define _WIN32_WINNT 0x0500

#include <windows.h>
#include "stdafx.h"
//#include <windowsx.h>
#include <GL/gl.h>
#include <GL/glu.h>
//#include <GL/glaux.h>
#include <mmsystem.h>
#include <stdio.h>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")
#pragma comment (lib, "winmm.lib")
//#pragma comment (lib, "glaux.lib")
#include <d3d9.h>

// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")

// global declarations
LPDIRECT3D9 d3d = NULL;    // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev = NULL;    // the pointer to the device class

#include <assert.h>
#include <tchar.h>
#include <math.h>
#define PI 3.14159265359

#ifdef  assert
#define verify(expr) if(!expr) assert(0)
#else verify(expr) expr
#endif

const TCHAR szAppName[]=_T("TransparentGL");
const TCHAR wcWndName[]=_T("WS_EX_LAYERED OpenGL");

HDC hDC;            
HGLRC m_hrc; 
HWND g_hWnd;
int w(800);
int h(600); 
bool g_bSwitchAlpha = false;//false;
bool g_bTryFaster = false;//true;

HDC pdcDIB;                 
HBITMAP hbmpDIB;            
void *bmp_cnt(NULL);        
int cxDIB(0); 
int cyDIB(0);   
BITMAPINFOHEADER BIH;    
BITMAPV5HEADER BIHA;

//#define USE_DIRECT_X

BOOL initSC()
{
    glEnable(GL_ALPHA_TEST);        
    glEnable(GL_DEPTH_TEST);        
    glEnable(GL_COLOR_MATERIAL);

    glEnable(GL_LIGHTING);          
    glEnable(GL_LIGHT0);            

    glEnable(GL_BLEND);             
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glClearColor(0, 0, 0, 0);
	return 0;
}

void resizeSC(int width,int height)
{
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW );
    glLoadIdentity();
}

BOOL renderSC()
{   
	DWORD	dwTime, dwTime2;
	static float t = 0.0f;
	float a1, a2, a3, x,y;
	int i, j;

	t=timeGetTime()/1.4f + 350.0f * sin(2.0f * PI * timeGetTime()/1.4f* 1.0f /1000);
#ifndef USE_DIRECT_X
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glPushMatrix();
    glColor3f(0, 1, 1);
    glBegin(GL_TRIANGLES);                              // Drawing Using Triangles
#else
	// clear the window to a deep blue
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);

    d3ddev->BeginScene();    // begins the 3D scene

    // do 3D rendering on the back buffer here

#endif

	a3 = 0.0f;
	for(j=0;j<5;++j)
	{
		x = 0.3f * sin(2.0f * PI * t* 0.25f /1000);
		y = 0.3f * sin(2.0f * PI * t* 0.5f /1000);
		for(i=0;i<3;++i)
		{
			a1 = 0.75f * cos(2.0f * PI * t *0.3f / 1000 + 2.0f * PI * i /3);
			a2 = 0.75f * sin(2.0f * PI * t *0.3f  / 1000 + 2.0f * PI * i /3);
#ifndef USE_DIRECT_X
			if (i==0)
				glColor4f(0.8f,0.0f,0.0f,1.0f);                      // Set The Color To Red
			else if (i==1)
				glColor4f(1.0f,1.0f,0.0f,1.0f);                      // Set The Color To Green
			else
				glColor4f(0.0f,0.0f+j*0.1f,2.0f,0.0f);                      // Set The Color To Blue
			glVertex3f( a1+x, a2+y, a3);                  // Top
#else
#endif
		}
		t += (38.0f+30.0f*sin(2.0f*PI*t*0.70f/1000))*(j+1+j*0.1f);
		a3-=0.01f;
//		a3+=1.5f;
	}
#ifndef USE_DIRECT_X
    glEnd();

    glPopMatrix();
    glFlush();
#else
    d3ddev->EndScene();    // ends the 3D scene
    d3ddev->Present(NULL, NULL, NULL, NULL);    // displays the created frame
#endif
/*        glColor4f(0.0f,1.0f,0.0f,0.0f);                      // Set The Color To Green
        glVertex3f(-1.0f,-0.0f-a, 0.0f);                  // Bottom Left
        glColor4f(0.0f,0.0f,1.0f,1.0f);                      // Set The Color To Blue
        glVertex3f( 1.0f,0.0f-a, 0.0f);                  // Bottom Right*/

    return 0;
}

// DIB -> hDC
void draw(HDC pdcDest)
{
	POINT pptDst, pptSrc;
	SIZE pSize;
	int i,j;
	DWORD dwValue;
	DWORD dwTime = timeGetTime();
    assert(pdcDIB);
	BLENDFUNCTION blendfunc;

	blendfunc.AlphaFormat = AC_SRC_ALPHA;
	blendfunc.BlendFlags = 0;
	blendfunc.SourceConstantAlpha = 255;
	blendfunc.BlendOp = AC_SRC_OVER;

//	AlphaBlend(pdcDest,  0, 0, w, h, pdcDIB, 0, 0, w, h, blendfunc);
//	TransparentBlt(pdcDest, 0, 0, w, h, pdcDIB, 0, 0, w, h, 0);
//    verify(BitBlt(pdcDest, 0, 0, w, h, pdcDIB, 0, 0, SRCCOPY));
	pptDst.x = 40;
	pptDst.y = 30;
	pptSrc.x = 0;
	pptSrc.y = 0;
	pSize.cx = w;
	pSize.cy = h;

	BOOL bRet;

	unsigned char *pBuf;
/*	pBuf = new unsigned char[4*w*h];
	BITMAPINFO	bmi;
	memset(&bmi, 0, sizeof(BITMAPINFO));
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biHeight = h;
	bmi.bmiHeader.biWidth = w;
	bmi.bmiHeader.biCompression = BI_BITFIELDS;
	bmi.bmiHeader.biSize = sizeof(BITMAPINFO);*/
	HBITMAP hbm;
//	hbm = CreateCompatibleBitmap(pdcDIB, w, h);
	
	DWORD *pBmp = (DWORD *) bmp_cnt;
//	DWORD dwValue;
	int a, b;
	if (g_bSwitchAlpha)
	{
	for(i=0;i<w*h;++i)
	{
		if ((pBmp[i]&0xFF000000)==0)
		{
		a = (pBmp[i]&0x00FF00)>>8;
		a+= pBmp[i]&0x00FF;
		a+= (pBmp[i]&0xFF0000)>>16;
		a*=1.0f+0.5f * sin(2.0f * PI * timeGetTime()*0.2f/1000);
		if (a>0xFF) a = 0xFF;

		pBmp[i]|= (a<<24);
		}
	}
	}

//	int nres;
//	nres = GetDIBits(pdcDIB, hbm, 0, h, pBuf, &bmi, DIB_RGB_COLORS);

//	if ((timeGetTime()%1000)<500)
	if (g_bTryFaster)
		bRet = UpdateLayeredWindow(g_hWnd, pdcDest, &pptDst, &pSize, pdcDIB, &pptSrc, RGB(0,0,0), &blendfunc, ULW_COLORKEY);
	else
		bRet = UpdateLayeredWindow(g_hWnd, pdcDest, &pptDst, &pSize, pdcDIB, &pptSrc, RGB(0,0,0), &blendfunc, ULW_ALPHA);
	
	//	else
	//	bRet = UpdateLayeredWindow(g_hWnd, pdcDest, &pptDst, &pSize, pdcDIB, &pptSrc, RGB(0,0,0), &blendfunc, ULW_ALPHA);
/*	if (g_bTryFaster)
		bRet = UpdateLayeredWindow(g_hWnd, pdcDest, &pptDst, &pSize, pdcDIB, &pptSrc, RGB(0,0,0), &blendfunc, ULW_OPAQUE|ULW_COLORKEY);
	else
		bRet = UpdateLayeredWindow(g_hWnd, pdcDest, &pptDst, &pSize, pdcDIB, &pptSrc, RGB(0,0,0), &blendfunc, ULW_ALPHA);*/
//	else
	//	bRet = UpdateLayeredWindow(g_hWnd, pdcDest, &pptDst, &pSize, pdcDIB, &pptSrc, RGB(0,0,0), &blendfunc, ULW_ALPHA|ULW_OPAQUE);
//	AlphaBlend(pdcDest,  0, 0, w, h, pdcDIB, 0, 0, w, h, blendfunc);
//	dwTime = timeGetTime() - dwTime;
//	char szDbg[MAX_PATH];
//	sprintf(szDbg, "draw: %d ms
", dwTime);
//	OutputDebugString(szDbg);
}

void CreateDIB(int cx, int cy)
{
    assert(cx > 0); 
    assert(cy > 0);

    cxDIB = cx ;
    cyDIB = cy ;

/*    int iSize = sizeof(BITMAPINFOHEADER);   
    memset(&BIH, 0, iSize);

    BIH.biSize = iSize;
    BIH.biWidth = cx;   
    BIH.biHeight = cy;  
    BIH.biPlanes = 1;   
    BIH.biBitCount = 32;    
    BIH.biCompression = BI_RGB;*/
	int iSize = sizeof(BITMAPV5HEADER);
	memset(&BIHA, 0, iSize);
	
    //The following mask specification specifies a supported 32 BPP
    //alpha format for Windows XP.
	BIHA.bV5Size			= sizeof(BITMAPV5HEADER);
    BIHA.bV5Width           = cx;
    BIHA.bV5Height          = cy;
    BIHA.bV5Planes			= 1;
    BIHA.bV5BitCount		= 32;
	BIHA.bV5SizeImage		= w*h*4;
	BIHA.bV5CSType		= LCS_sRGB;
    BIHA.bV5Compression = BI_BITFIELDS;
    BIHA.bV5RedMask   =  0x00FF0000;
    BIHA.bV5GreenMask =  0x0000FF00;
    BIHA.bV5BlueMask  =  0x000000FF;
    BIHA.bV5AlphaMask =  0xFF000000;
    if(pdcDIB) 
        verify(DeleteDC(pdcDIB));

    pdcDIB = CreateCompatibleDC(NULL);
    assert(pdcDIB);

    if(hbmpDIB) 
        verify(DeleteObject(hbmpDIB));

    hbmpDIB = CreateDIBSection(
        pdcDIB,         
        (BITMAPINFO*)&BIHA,  
        DIB_RGB_COLORS,     
        &bmp_cnt,       
        NULL,
        0);
	memset(bmp_cnt, 0x44, 4*w*h);

    assert(hbmpDIB);
    assert(bmp_cnt);

    if(hbmpDIB)
        SelectObject(pdcDIB, hbmpDIB);
}

BOOL CreateHGLRC()
{
    DWORD dwFlags = PFD_DIRECT3D_ACCELERATED | PFD_DRAW_TO_BITMAP;
//	dwFlags = PFD_DRAW_TO_BITMAP|PFD_GENERIC_ACCELERATED;

    PIXELFORMATDESCRIPTOR pfd ;
    memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR)) ;
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
    pfd.nVersion = 1;                       
    pfd.dwFlags =  dwFlags ;                
    pfd.iPixelType = PFD_TYPE_RGBA ;        
    pfd.cColorBits = 32 ;                   
    pfd.cDepthBits = 24 ;
	pfd.cStencilBits = 8;
	pfd.cAlphaBits = 8;
	pfd.iLayerType = PFD_MAIN_PLANE;  


   int PixelFormat = ChoosePixelFormat(pdcDIB, &pfd);
   if (PixelFormat == 0){
      assert(0);
      return FALSE ;
   }

   BOOL bResult = SetPixelFormat(pdcDIB, PixelFormat, &pfd);
   if (bResult==FALSE){
      assert(0);
      return FALSE ;
   }

   m_hrc = wglCreateContext(pdcDIB);
   if (!m_hrc){
      assert(0);
      return FALSE;
   }

   return TRUE;
}

BOOL CreateHDXRC(HWND hWnd)
{
	D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information

	ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use
	d3dpp.Windowed = TRUE;    // program windowed, not fullscreen
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames
	d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D

	// create a device class using this information and information from the d3dpp stuct
	d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);



	return TRUE;
}

LRESULT CALLBACK WindowFunc(HWND hWnd,UINT msg, WPARAM wParam, LPARAM lParam)
{
	static int s_enter = 0;
    PAINTSTRUCT ps;
	int i;
	char szDbg[MAX_PATH];
	char szLastDbg[MAX_PATH];
	DWORD	dwTime;
	static DWORD s_dwTime = 0;
	static int s_nTime = 0;
	static DWORD s_cumTime = 0;

    switch(msg) 
    {
        case WM_ERASEBKGND:
            return 0;
        break;

        case WM_CREATE:
        break;

        case WM_DESTROY:
#ifndef USE_DIRECT_X
            if(m_hrc)
            {
                wglMakeCurrent(NULL, NULL);
                wglDeleteContext(m_hrc) ;
            }
#else
			if (d3ddev)
				d3ddev->Release();    // close and release the 3D device
			if (d3d)
			    d3d->Release();    // close and release Direct3D		
#endif
            PostQuitMessage(0) ;
        break;

        case WM_PAINT:
            hDC = BeginPaint(hWnd, &ps);
            renderSC(); // OpenGL -> DIB
            draw(hDC);  // DIB -> hDC
            EndPaint(hWnd, &ps);
        break;
		case WM_TIMER:
			if (s_enter!=0) return FALSE;
			if (s_dwTime==0) s_dwTime = timeGetTime();
			++s_enter;
			dwTime = timeGetTime();
//#ifndef USE_DIRECT_X
			hDC = GetDC(hWnd);
//            hDC = BeginPaint(hWnd, &ps);
            renderSC(); // OpenGL -> DIB
            draw(hDC);  // DIB -> hDC
			ReleaseDC(hWnd, hDC);
//#endif
			--s_enter;
			dwTime = timeGetTime() - dwTime;
			s_cumTime+=dwTime;
			++s_nTime;
//			OutputDebugString(szLastDbg);
			s_dwTime = timeGetTime();
 //           EndPaint(hWnd, &ps);
		break;

        case WM_SIZE:
            w = LOWORD(lParam); h = HIWORD(lParam);         
#ifndef USE_DIRECT_X
			// --- initialize Open GL ---
            wglMakeCurrent(NULL, NULL);
            wglDeleteContext(m_hrc);

            CreateDIB(w, h);
            CreateHGLRC();
            verify(wglMakeCurrent(pdcDIB, m_hrc));

            initSC();
            resizeSC(w, h);
            renderSC();
#else
			// --- initialize Direct X ---
			d3d = Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface
			CreateDIB(w, h);
			CreateHDXRC(hWnd);
            renderSC();
#endif
        break;
		case WM_KEYDOWN:
			if (toupper(LOBYTE(wParam))=='A')
			{
				sprintf(szLastDbg, "Average: %d ms (cumul. time: %d ms, count: %d)
", s_cumTime/(s_nTime), s_cumTime, s_nTime);
				MessageBox(NULL, szLastDbg, "Debug", MB_OK);
			}
			else if (toupper(LOBYTE(wParam))=='Q')
			{
				g_bTryFaster = !g_bTryFaster;
				s_cumTime = 0;
				s_nTime = 0;
			}
			else
			{
				g_bSwitchAlpha = !g_bSwitchAlpha;
				s_cumTime = 0;
				s_nTime = 0;
			}
			break;

        default: 
            return DefWindowProc(hWnd,msg,wParam,lParam);
    }

    return 0;
}

int WINAPI _tWinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str,int nWinMode)
{   
    WNDCLASSEX wc;
    memset(&wc, 0, sizeof(wc));
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WindowFunc;
    wc.cbClsExtra  = 0;
    wc.cbWndExtra  = 0;
    wc.hInstance = hThisInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    wc.lpszClassName = szAppName;

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, _T("RegisterClassEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
        return FALSE;
    }

    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szAppName, wcWndName,
                    WS_VISIBLE | WS_POPUP, 200, 150, w, h,
                    NULL, NULL, hThisInst, NULL);
    if(!hWnd){
        MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
        return FALSE;
    }

//    verify(SetLayeredWindowAttributes(hWnd, 0x0, 255, LWA_ALPHA));
	g_hWnd = hWnd;
    MSG msg;
	SetTimer(hWnd, 1, 25, NULL);
    while(1) 
    {
        while (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
            if (GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else return 0;
        }
    } 

    return (FALSE); 
}

I made some progress, on the DirectX support and got the alpha included with the RGB. The performance is 1 ms to update the window on win7 using a modern PC (however this drop to 300 ms using a Pentium III 800MHz, with Windows XP).

That give me some hopes that there is a way in OpenGL too with some good performance. I need to found out if the very low performance on old PC can be improve by removing some of the visual features.

here is a screen shot of my dialog box (yeah… yeah… those colored computed by the graphic cards triangles is a dialog box).

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.