|
a5 hbitmap to allegro_bitmap |
komons
Member #11,083
June 2009
|
Hi How to convert from HBITMAP to video ALLEGRO_BITMAP? I did it by this way, but it's very slow, about few minutes: 1HDC _dc = GetWindowDC(GetDesktopWindow());
2RECT rect;
3GetWindowRect(GetDesktopWindow(),&rect);
4int w = rect.right, h = rect.bottom; //1440x900
5
6bg = al_create_bitmap( w, h );
7al_lock_bitmap( bg, al_get_bitmap_format(bg), ALLEGRO_LOCK_WRITEONLY );
8
9for ( unsigned j=0; j<h; j++ )
10for ( unsigned i=0; i<w; i++ )
11{
12 COLORREF clr = GetPixel( _dc, i, j );
13 al_put_pixel( i,j,al_map_rgb( int(GetRValue(clr)), int(GetGValue(clr)), int(GetBValue(clr)) ) );
14}
15
16al_unlock_bitmap( bg );
|
Desmond Taylor
Member #11,943
May 2010
|
Use al_set_new_bitmap_flags( ALLEGRO_MEMORY_BITMAP ) and then clone it to a VIDEO bitmap. |
Thomas Fjellstrom
Member #476
June 2000
|
Desmond Taylor said: Use al_set_new_bitmap_flags( ALLEGRO_MEMORY_BITMAP ) and then clone it to a VIDEO bitmap. He's locking the bitmap, which basically temporarily turns it into a memory bitmap. It really should not take minutes to copy from the HDC to the ALLEGRO_BITMAP. -- |
Edgar Reynaldo
Major Reynaldo
May 2007
|
You didn't set the target bitmap to your 'bg' bitmap. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
komons
Member #11,083
June 2009
|
It's still very slow for 1440x900 :< 1HDC _dc = GetWindowDC(GetDesktopWindow());
2RECT rect;
3GetWindowRect(GetDesktopWindow(),&rect);
4int w = rect.right, h = rect.bottom;
5
6ALLEGRO_BITMAP* target = al_get_target_bitmap();
7
8al_set_new_bitmap_flags( ALLEGRO_MEMORY_BITMAP );
9bg = al_create_bitmap( w, h );
10
11al_set_target_bitmap( bg );
12
13al_lock_bitmap( bg, al_get_bitmap_format(bg), ALLEGRO_LOCK_WRITEONLY );
14for ( unsigned j=0; j<h; j++ )
15for ( unsigned i=0; i<w; i++ )
16{
17 COLORREF clr = GetPixel( _dc, i, j );
18 al_put_pixel( i,j,al_map_rgb( int(GetRValue(clr)), int(GetGValue(clr)), int(GetBValue(clr)) ) );
19}
20al_unlock_bitmap( bg );
21al_set_new_bitmap_flags( 0 );
22al_set_target_bitmap( target );
|
Trent Gamblin
Member #261
April 2000
|
You can skip some of the overhead of al_put_pixel and al_map_rgb by locking in a simple format like RGBA_8888. You can skip the overhead of conversion to RGBA_8888 too, which will be even faster, if you create the bitmap in an easy format like that to begin with. Edit: To be clearer, I mean you'd write the bytes from GetR etc directly to the memory buffer in the ALLEGRO_LOCKED_REGION.
|
Matthew Leverton
Supreme Loser
January 1999
|
Isn't the problem likely to be that GetPixel is slow? |
Trent Gamblin
Member #261
April 2000
|
That's probably slow too, but I don't know winapi so I can only make Allegro suggestions.
|
Matthew Leverton
Supreme Loser
January 1999
|
Here's something I hacked together from Allegro 4 sources. It assumes going from 32-bit to 32-bit and has a bunch of unused variables (etc), but you can see if it's any better. Obviously for production quality it would need to be cleaned up a bit. I only ran it on a VM, so I don't know how fast it is. 1#include <Windows.h>
2
3#include <allegro5/allegro.h>
4
5#define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8)
6
7/* get_bitmap_from_dib:
8 * Creates an Allegro BITMAP from a Windows device-independent bitmap (DIB).
9 */
10static ALLEGRO_BITMAP *get_bitmap_from_dib(int bpp, int w, int h, BYTE *pixels)
11{
12 int x, y;
13 int pitch;
14 int col;
15 int b, g, r;
16 BYTE *src;
17 ALLEGRO_BITMAP *bitmap;
18 ALLEGRO_LOCKED_REGION *lock;
19 uint8_t *dst;
20
21 pitch = w * BYTES_PER_PIXEL(bpp);
22 pitch = (pitch + 3) & ~3; /* align on dword */
23
24 bitmap = al_create_bitmap(w, h);
25 lock = al_lock_bitmap(bitmap, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_WRITEONLY);
26
27 dst = (uint8_t *) lock->data;
28
29 for (y = 0; y < h; ++y)
30 {
31 memcpy(dst, pixels + y * pitch, w * BYTES_PER_PIXEL(bpp));
32 dst += lock->pitch;
33 }
34
35 al_unlock_bitmap(bitmap);
36
37 return bitmap;
38}
39
40/* get_dib_from_hbitmap:
41 * Creates a Windows device-independent bitmap (DIB) from a Windows BITMAP.
42 * You have to free the memory allocated by this function.
43 */
44static BYTE *get_dib_from_hbitmap(int bpp, HBITMAP hbitmap)
45{
46 BITMAPINFOHEADER bi;
47 BITMAPINFO *binfo;
48 HDC hdc;
49 HPALETTE hpal, holdpal;
50 int col;
51 BITMAP bm;
52 int pitch;
53 BYTE *pixels;
54 BYTE *ptr;
55 int x, y;
56
57 if (!hbitmap)
58 return NULL;
59
60 if (bpp == 15)
61 bpp = 16;
62
63 if (!GetObject(hbitmap, sizeof(bm), (LPSTR) & bm))
64 return NULL;
65
66 pitch = bm.bmWidth * BYTES_PER_PIXEL(bpp);
67 pitch = (pitch + 3) & ~3; /* align on dword */
68
69 pixels = (BYTE *) al_malloc(bm.bmHeight * pitch);
70 if (!pixels)
71 return NULL;
72
73 ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
74
75 bi.biSize = sizeof(BITMAPINFOHEADER);
76 bi.biBitCount = bpp;
77 bi.biPlanes = 1;
78 bi.biWidth = bm.bmWidth;
79 bi.biHeight = -abs(bm.bmHeight);
80 bi.biClrUsed = 256;
81 bi.biCompression = BI_RGB;
82
83 binfo = (BITMAPINFO *) al_malloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256);
84 binfo->bmiHeader = bi;
85
86 hdc = GetDC(NULL);
87
88 GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pixels, binfo, DIB_RGB_COLORS);
89
90 ptr = pixels;
91
92 al_free(binfo);
93
94
95 ReleaseDC(NULL, hdc);
96
97 return pixels;
98}
99
100/* convert_hbitmap_to_bitmap:
101 * Converts a Windows BITMAP to an Allegro BITMAP.
102 */
103ALLEGRO_BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap)
104{
105 BYTE *pixels;
106 ALLEGRO_BITMAP *bmp;
107 BITMAP bm;
108 int bpp;
109
110 if (!GetObject(bitmap, sizeof(bm), (LPSTR) & bm))
111 return NULL;
112
113 if (bm.bmBitsPixel == 8) {
114 /* ask windows to save truecolor image, then convert to our format */
115 bpp = 24;
116 }
117 else
118 bpp = bm.bmBitsPixel;
119
120 /* get the DIB first */
121 pixels = get_dib_from_hbitmap(bpp, bitmap);
122
123 /* now that we have the DIB, convert it to a BITMAP */
124 bmp = get_bitmap_from_dib(bpp, bm.bmWidth, bm.bmHeight, pixels);
125
126 al_free(pixels);
127
128 return bmp;
129}
130
131ALLEGRO_BITMAP *convert_hdc_to_bitmap(HDC dc)
132{
133 ALLEGRO_BITMAP *bg;
134 const int w = GetDeviceCaps(dc, HORZRES);
135 const int h = GetDeviceCaps(dc, VERTRES);
136
137 HDC hmemdc = CreateCompatibleDC(dc);
138 HBITMAP hbmp = CreateCompatibleBitmap(dc, w, h);
139 HBITMAP holdbmp = (HBITMAP) SelectObject(hmemdc, hbmp);
140
141 StretchBlt(hmemdc, 0, 0, w, h, dc, 0, 0, w, h, SRCCOPY);
142 SelectObject(hmemdc, holdbmp);
143
144 bg = convert_hbitmap_to_bitmap(hbmp);
145
146 DeleteObject(hbmp);
147 DeleteDC(hmemdc);
148
149 return bg;
150}
151
152int main()
153{
154 al_init();
155
156 ALLEGRO_DISPLAY *display = al_create_display(800, 600);
157 if (!display) return -1;
158
159 ALLEGRO_BITMAP *bmp = convert_hdc_to_bitmap(GetWindowDC(GetDesktopWindow()));
160
161 al_draw_bitmap(bmp, 0, 0, 0);
162 al_flip_display();
163
164 al_rest(1);
165
166 return 0;
167}
|
komons
Member #11,083
June 2009
|
It works but result is someidontknow bitmap. Black with some elements of screen. I did it by another way. Save screen to bmp file, and load it by al_load_bitmap. Loading is little fast, but I wouldn't like do it by this way. 1void C_Tools::screen(HWND okno, char* plik)
2{
3HDC _dc = GetWindowDC(okno);
4RECT re;
5GetWindowRect(okno,&re);
6int w = re.right, h = re.bottom;
7HDC dc = CreateCompatibleDC(0);
8HBITMAP bm = CreateCompatibleBitmap(_dc,w,h);
9SelectObject(dc,bm);
10StretchBlt(dc,0,0,w,h,_dc,0,0,w,h,SRCCOPY);
11void* f = CreateFileA(plik,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,0);
12void* buf = new char[w*h*3];
13GetObject(bm,84,buf);
14HDC ddd = GetDC(0);
15HDC dc2 = CreateCompatibleDC(ddd);
16tagBITMAPINFO bi;
17bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
18bi.bmiHeader.biWidth = w;
19bi.bmiHeader.biHeight = h;
20bi.bmiHeader.biPlanes = 1;
21bi.bmiHeader.biBitCount = 24;
22bi.bmiHeader.biCompression = 0;
23bi.bmiHeader.biSizeImage = 0;
24CreateDIBSection(dc,&bi,DIB_RGB_COLORS,&buf,0,0);
25GetDIBits(dc,bm,0,h,buf,&bi,DIB_RGB_COLORS);
26
27BITMAPFILEHEADER bif;
28bif.bfType = MAKEWORD('B','M');
29bif.bfSize = w*h*3+54;
30bif.bfOffBits = 54;
31
32BITMAPINFOHEADER bii;
33bii.biSize = 40;
34bii.biWidth = w;
35bii.biHeight = h;
36bii.biPlanes = 1;
37bii.biBitCount = 24;
38bii.biCompression = 0;
39bii.biSizeImage = w*h*3;
40
41DWORD r;
42WriteFile(f,&bif,sizeof(bif),&r,NULL);
43WriteFile(f,&bii,sizeof(bii),&r,NULL);
44WriteFile(f,buf,w*h*3,&r,NULL);
45CloseHandle(f);
46}
|
|