Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » How do you render a certain area of a bitmap using OpenGL and Allegro 5?

This thread is locked; no one can reply to it. rss feed Print
How do you render a certain area of a bitmap using OpenGL and Allegro 5?
Desmond Taylor
Member #11,943
May 2010
avatar

Hey guys, I'm using OpenGL with the depth buffer so I can render different layers ect easier but I am stuck on on drawing part of a bitmap.

The code I use for drawing the entire image is below.

I have tried using al_create_sub_bitmap but it seemed not to work.

Here is the full code of the graphics class.

#SelectExpand
1#include "graphics.h" 2 3Graphics::Graphics( Client* client ) 4{ 5 if ( !al_init_image_addon() ) 6 this->client->Error( "Failed to initialize the image addon" ); 7} 8 9Graphics::~Graphics() 10{ 11 for ( unsigned int i = 0; i < this->bitmap.size(); i++ ) 12 { 13 if ( this->bitmap[i] ) 14 al_destroy_bitmap( this->bitmap[i] ); 15 } 16 17 al_shutdown_image_addon(); 18} 19 20int Graphics::Load( const char* filename, int resID ) 21{ 22 ALLEGRO_BITMAP* newBitmap = NULL; 23 ALLEGRO_LOCKED_REGION* locked; 24 BITMAP bm; 25 26 HMODULE module = LoadLibrary( filename ); 27 if ( !module ) 28 { 29 this->client->Error( "Failed to LoadLibrary: %s", filename ); 30 return -1; 31 } 32 33 HBITMAP bitmap = LoadBitmap( module, MAKEINTRESOURCE( resID ) ); 34 if ( !bitmap ) 35 { 36 this->client->Error( "Failed to LoadBitmap: %i", resID ); 37 return -1; 38 } 39 40 if ( !GetObject( bitmap, sizeof( bm ), reinterpret_cast<LPSTR>( &bm ) ) ) 41 { 42 this->client->Error( "Failed to GetObject" ); 43 return -1; 44 } 45 46 al_set_new_bitmap_flags( ALLEGRO_MEMORY_BITMAP ); 47 48 newBitmap = al_create_bitmap( bm.bmWidth, bm.bmHeight ); 49 50 locked = al_lock_bitmap( newBitmap, ALLEGRO_PIXEL_FORMAT_RGB_888, ALLEGRO_LOCK_READWRITE ); 51 BYTE *data = reinterpret_cast<BYTE *>(locked->data); 52 53 int pitch = bm.bmWidth * locked->pixel_size; 54 pitch = ( pitch + 3 ) & ~3; 55 56 BYTE *pixels = new BYTE[bm.bmHeight * pitch]; 57 58 BITMAPINFOHEADER bi; 59 ZeroMemory( &bi, sizeof( BITMAPINFOHEADER ) ); 60 bi.biSize = sizeof( BITMAPINFOHEADER ); 61 bi.biBitCount = al_get_pixel_format_bits( locked->format ); 62 bi.biPlanes = 1; 63 bi.biWidth = bm.bmWidth; 64 bi.biHeight = -abs( bm.bmHeight ); 65 bi.biClrUsed = 256; 66 bi.biCompression = BI_RGB; 67 68 BITMAPINFO *binfo = static_cast<BITMAPINFO *>( std::malloc( sizeof( BITMAPINFO ) + sizeof( RGBQUAD ) * 256 ) ); 69 binfo->bmiHeader = bi; 70 71 HDC hdc = GetDC( NULL ); 72 73 GetDIBits( hdc, bitmap, 0, bm.bmHeight, pixels, binfo, DIB_RGB_COLORS ); 74 75 delete( binfo ); 76 77 ReleaseDC(NULL, hdc); 78 79 int height = std::abs( std::min ( int( bm.bmHeight ), int( al_get_bitmap_height( newBitmap ) ) ) ); 80 int width = std::abs( std::min( pitch, int( locked->pitch ) ) ); 81 82 for ( int y = 0; y < height; ++y ) 83 std::memcpy( data + locked->pitch * y, pixels + pitch * y, width ); 84 85 DeleteObject( bitmap ); 86 FreeLibrary( module ); 87 88 delete[] pixels; 89 90 al_unlock_bitmap( newBitmap ); 91 92 al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP ); 93 94 ALLEGRO_BITMAP* clonedBitmap = al_clone_bitmap( newBitmap ); 95 if ( !clonedBitmap ) 96 { 97 this->client->Error( "Failed to clone the bitmap" ); 98 return -1; 99 } 100 101 al_destroy_bitmap( newBitmap ); 102 103 for ( unsigned int i = 0; i < this->bitmap.size(); i++ ) 104 { 105 if ( !this->bitmap[i] ) 106 { 107 this->bitmap[i] = clonedBitmap; 108#ifdef DEBUG 109 printf( "Loaded Image: %s %i #%i\n", filename, resID, i ); 110#endif // DEBUG 111 112 return i; 113 } 114 } 115 116 this->bitmap.push_back( clonedBitmap ); 117 118#ifdef DEBUG 119 printf( "Loaded Image: %s %i #%i\n", filename, resID, this->bitmap.size() - 1 ); 120#endif // DEBUG 121 122 return this->bitmap.size() - 1; 123} 124 125void Graphics::Delete( int id ) 126{ 127 al_destroy_bitmap( this->bitmap[id] ); 128 this->bitmap[id] = NULL; 129 130#ifdef DEBUG 131 printf( "Deleted Image: %i\n", id ); 132#endif // DEBUG 133} 134 135void Graphics::Blit( int id, float x, float y, float z ) 136{ 137 this->GLBlit( this->bitmap[id], x, y, z ); 138} 139 140void Graphics::BlitRegion( int id, int sx, int sy, int width, int height, float dx, float dy, float z ) 141{ 142 ALLEGRO_BITMAP* bmpSub = al_create_sub_bitmap( this->bitmap[id], sx, sy, width, height ); 143 144 if ( bmpSub ) 145 { 146 this->GLBlit( bmpSub, dx, dy, z ); 147 } 148 else 149 this->client->Error( "Failed to create sub bitmap" ); 150} 151 152void Graphics::GLBlit( ALLEGRO_BITMAP* bmp, float x, float y, float z ) 153{ 154 int width = al_get_bitmap_width( bmp ) ; 155 int height = al_get_bitmap_height( bmp ); 156 GLuint texture; 157 158 glEnable( GL_TEXTURE_2D); 159 160 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 161 glEnable( GL_BLEND ); 162 163 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 164 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 165 166 glGenTextures( 1, &texture ); 167 168 texture = al_get_opengl_texture( bmp ); 169 170 glBindTexture( GL_TEXTURE_2D, texture ); 171 172 glLoadIdentity(); 173 174 glBegin( GL_QUADS ); 175 glColor4ub( 255, 255, 255, 255 ); 176 177 glTexCoord2f( 0, 0 ); glVertex3f( x, y + height, z ); 178 glTexCoord2f( 1, 0 ); glVertex3f( x + width, y + height, z ); 179 glTexCoord2f( 1, 1 ); glVertex3f( x + width, y, z ); 180 glTexCoord2f( 0, 1 ); glVertex3f( x, y, z ); 181 glEnd(); 182} 183 184void Graphics::MakeTransparent( int id, int r, int g, int b ) 185{ 186 al_convert_mask_to_alpha( this->bitmap[id], al_map_rgb( r, g, b ) ); 187}

This is what happens when I use BlitRegion()
{"name":"605195","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/a\/eaccdca7b4b17d6e7a1e3c9fccead329.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/a\/eaccdca7b4b17d6e7a1e3c9fccead329"}605195

Itachihro
Member #12,001
May 2010

A sub bitmap will probably share the same texture with it's parent bitmap. So if you write something like glTexCoord2f( 1, 0 ); you are referring to the tex coordinates of the whole texture. You have 2 choices:
1) Rather than a sub bitmap, create a whole new bitmap - then you could probably use that code pretty much unchanged. But you'd be wasting a lot of video memory.
2) Figure the tex coordinates of the sub bitmap out. I don't know how to access these, look in the manual maybe there's something useful. If not, maybe you should write an own bitmap class that keeps track of that information (though I imagine this would be unnecessary - allegro needs that info itself for drawing, it should be accessible somehow).

Desmond Taylor
Member #11,943
May 2010
avatar

Ah, I was wondering why it was rendering the full image but as a smaller version. I shall look into the open gl texturing coords so that I can work this out. I hope there is a gl function that takes pixels instead of just one and 0 :P

Append:
This should work glTexCoord2i(). I will code that in now and try it.

Append 2:
Looks like I have no clue on how that works either :(

Arthur Kalliokoski
Second in Command
February 2005
avatar

I use this thing to set pixels in a gui.

#SelectExpand
1//set up for 2D drawing with origin at upper left corner of screen ala VGA of old 2void set_image_ortho(void) 3{ 4 float w,h; 5 glMatrixMode(GL_TEXTURE); //don't bother with glflags here, since it changes 6 glPushMatrix(); //so much so quickly 7 glLoadIdentity(); 8 glMatrixMode(GL_PROJECTION); 9 glPushMatrix(); 10 glLoadIdentity(); 11 glMatrixMode(GL_MODELVIEW); 12 glPushMatrix(); 13 glLoadIdentity(); 14 w = gwin.width; h = gwin.height; 15 glOrtho(0.0,w,h,0.0,-1.0,1000.0); 16 glScalef(1.0,1.0,1.0); 17 //enable transparency for glDrawPixels() 18 glDisable(GL_ALPHA_TEST); 19 glDisable(GL_BLEND); 20 glEnable(GL_TEXTURE_2D); 21 glColor4fv((float *)vWHITE); 22 setglflags(TEX2D | MODELMODE); 23 clearglflags(BLEND | ALPHATST | TEXMODE | PROJMODE); 24}

They all watch too much MSNBC... they get ideas.

gnolam
Member #2,030
March 2002
avatar

glTexCoord2f((float)xInPixels/textureWidthInPixels, (float)yInPixels/textureHeightInPixels);

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Go to: