![]() |
|
How do you render a certain area of a bitmap using OpenGL and Allegro 5? |
Desmond Taylor
Member #11,943
May 2010
![]() |
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. 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() |
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: |
Desmond Taylor
Member #11,943
May 2010
![]() |
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 Append: Append 2: |
Arthur Kalliokoski
Second in Command
February 2005
![]() |
I use this thing to set pixels in a gui. 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
![]() |
glTexCoord2f((float)xInPixels/textureWidthInPixels, (float)yInPixels/textureHeightInPixels); -- |
|