Thread: Drawing bitmaps efficiently

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Mar 2007
    Posts
    416
    Quote Originally Posted by Sebastiani View Post
    If you get a solid, unbroken rectangle, then the implementation is somehow broken. Otherwise, I would recommend posting more code so that we can get a better idea of what else could be the problem.
    That was a good idea, but I still get the broken image in the exact same format as shown above. The code for my GetPixel function is there. I'm almost certain it's not that since I use to have a global array of the same thing and got the pixel in the same fashion and it worked correctly. This use to work, even with my CANVAS class, then I changed a few things and didn't remember what I changed, and it didn't work

    I'm working on using novacain's idea on the BitBlt, hoping my problem goes away somewhere in the process. I'm still completely confused on why my exe file creates 50% cpu with just the WM_PAINT message being present. I tested this by creating a new project, changed nothing except adding case WM_PAINT: {} break; and boom, cpu shoots up. I have no idea why. So until that also gets figured out my paint message will be replaced by my own defined message that acts as WM_PAINT.

    Code:
    unsigned char CANVAS::GetPixel(int col /*x*/, int row /*y*/, UINT color, UINT &error)
    {
        if(m_empty){
            error = ERR_NO_CANVAS;
            return 0;
        }
        else if(col > m_width){
            error = ERR_WIDTH_TOO_LARGE;
            return 0;
        }
        else if(row > m_height){
            error = ERR_HEIGHT_TOO_LARGE;
            return 0;
        }
        
        //PIXEL_R = 9
        //PIXEL_G = 8
        //PIXEL_B = 7
        error = ERR_SUCCESS;
        return m_im_rgb[(col + row*m_width)*3 + PIXEL_R - color];
    }

  2. #2
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    The easiest way to draw a bitmap in a static control is to let someone else do it.

    Code:
    case WM_CREATE: // or wherever else the control is created
    {
        // you can set the control height and width to 0 as it'll resize automatically
        HWND hStatic = CreateWindowEx(0, WC_STATIC, TEXT(""), SS_BITMAP | WS_CHILD, ...); 
        if(hStatic)
        {
            HBITMAP hBm = // load your hbitmap
            SendMessage(hStatic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBm);
            ShowWindow(hStatic, SW_SHOW);
        }
    }
    break;
    You could also create a pattern brush with CreatePatternBrush using your HBITMAP and return the brush in reponse to WM_CTLCOLORSTATIC for largely the same effect.

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I don't know if it would help (and I'm a little rusty at Win32, so it may not be 100% correct), but here's a simple test harness that you can use to compare with:

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    void cleanup( void );
    LRESULT callback( HWND handle, UINT code, WPARAM wparam, LPARAM lparam );
    
    HWND
    	window = 0;
    HDC
    	foreground = 0;
    HBITMAP
    	bitmap = 0,
    	saved = 0;
    
    int main( int argc, char** argv )
    {
    	if( argc != 2 )
    	{
    		fprintf( stderr, "- Bitmap Test -\n" );
    		fprintf( stderr, "Usage: %s <FILE_NAME>\n", argv[ 0 ] );
    		cleanup( );
    		return 1;
    	}
    	bitmap = HBITMAP( LoadImage( 0, argv[ 1 ], IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT | LR_LOADFROMFILE ) );
    	if( bitmap == 0 )
    	{
    		fprintf( stderr, "Error: could not load file '%s'\n", argv[ 1 ] );
    		cleanup( );
    		return 2;
    	}
    	WNDCLASS 
    		settings;	
    	memset( &settings, 0, sizeof( settings ) );
    	settings.lpfnWndProc = WNDPROC( callback );
    	settings.hInstance = GetModuleHandle( 0 );
    	settings.hIcon = LoadIcon( 0, IDI_APPLICATION );
    	settings.hCursor = LoadCursor( 0, IDC_ARROW );
    	settings.lpszClassName = __FILE__;
    	if( !RegisterClass( &settings ) )
    	{
    		fprintf( stderr, "Error: could not register window class '%s'\n", settings.lpszClassName );
    		cleanup( );
    		return 3;
    	}
    	RECT 
    		size;	
    	SystemParametersInfo( SPI_GETWORKAREA, 0, &size, 0 );	
    	window = CreateWindow
    	( 
    		settings.lpszClassName,
    		"Bitmap Test",
    		WS_OVERLAPPEDWINDOW,
    		0,
    		0,
    		size.right - size.left,
    		size.bottom - size.top,
    		0,
    		0,
    		settings.hInstance,
    		0 
    	);
    	if( window == 0 )
    	{
    		fprintf( stderr, "Error: could not create window" );
    		cleanup( );
    		return 4;
    	}
    	HDC
    		canvas = GetDC( window );
    	foreground = CreateCompatibleDC( canvas );
    	ReleaseDC( window, canvas );
    	saved = HBITMAP( SelectObject( foreground, bitmap ) );	
    	ShowWindow( window, SW_SHOW );
    	UpdateWindow( window );
    	MSG 
    		message;	
    	while( GetMessage( &message, 0, 0, 0 ) > 0 ) 
    	{	
    		TranslateMessage( &message ); 
    		DispatchMessage( &message );
    	}
    	cleanup( );	
    	return message.wParam;		
    }	
    
    LRESULT callback( HWND handle, UINT code, WPARAM wparam, LPARAM lparam )
    { 
    	if( code == WM_CLOSE )
    	{		
    		PostQuitMessage( 0 );
    		return 0;
    	}
    	else if( code == WM_ERASEBKGND )
    	{
    	/*
    		We'll redraw the background in the WM_PAINT code, instead
    	*/	
    		return 1;
    	}
    	else if( code == WM_SIZE || code == WM_MOVE )
    	{
    		InvalidateRect( window, 0, 0 );
    	}
    	else if( code == WM_PAINT )
    	{		
    		PAINTSTRUCT 
    			info;
    		HDC 
    			canvas = BeginPaint( window, &info );
    	/*
    		We could actually use PAINTSTRUCT::rcPaint to calculate the 
    		dimensions, but I opted to go this route, for the sake of clarity. 
    	*/
    		RECT
    			bounds;
    		GetClientRect( window, &bounds );
    		int
    			width = bounds.right - bounds.left, 
    			height = bounds.bottom - bounds.top;
    		HBRUSH
    			saved = HBRUSH( SelectObject( canvas, GetStockObject( LTGRAY_BRUSH ) ) );	
    		PatBlt( canvas, 0, 0, width, height, PATCOPY );
    		BitBlt( canvas, 0, 0, width, height, foreground, 0, 0, SRCCOPY );
    		SelectObject( canvas, saved );
                    EndPaint( window, &info );
    	}
    	return DefWindowProc( handle, code, wparam, lparam );		
    }
    
    void cleanup( void )
    {
    	SelectObject( foreground, saved );
    	DeleteObject( bitmap );
    	DeleteDC( foreground );
    	DestroyWindow( window );
    }
    Last edited by Sebastiani; 06-14-2009 at 01:02 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Slow drawing code
    By tjpanda in forum Windows Programming
    Replies: 5
    Last Post: 05-09-2008, 05:09 PM
  2. drawing on bitmaps
    By eth0 in forum Windows Programming
    Replies: 2
    Last Post: 03-24-2006, 05:56 PM
  3. Interesting problem with bmp drawing
    By Victor in forum C++ Programming
    Replies: 3
    Last Post: 04-12-2005, 10:39 AM
  4. MFC: Multiple clicks shows multiple bitmaps - how?
    By BrianK in forum Windows Programming
    Replies: 0
    Last Post: 06-20-2004, 07:25 PM
  5. Drawing Bitmaps
    By filler_bunny in forum Windows Programming
    Replies: 6
    Last Post: 05-05-2004, 04:32 PM