Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Allegro with wxWidgets Bitmap converion

This thread is locked; no one can reply to it. rss feed Print
Allegro with wxWidgets Bitmap converion
Stepes
Member #10,390
November 2008

Hi, wanted to ask if there is any way to convert an Allegro Bitmap into a wxWidgets wxBitmap.

Essentially I want to print my BITMAP* buffer onto a wxDC.
I found the bitmap struct in Allegro which has a void* dat. wxBitmap has a constructor which takes as a parameter a void* to bitmap data. But I don't think it worked as it crashes with an unhandled exception.

VS2008 error:

Unhandled exception at 0x00556ade in Test3.exe: 0xC0000005: Access violation reading location 0x00000000.

in this function

void DrawBitmap(const wxBitmap &bmp, const wxPoint& pt, bool useMask = false)
        { DoDrawBitmap(bmp, pt.x, pt.y, useMask); }

seems like the dat is null I guess?

Any help appreciated :)
Otherwise I'll have to change all my code to work with wxBitmaps instead of allegro Bitmaps which I don't exactly look forward to :P

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

You probably need to write a conversion function to grab the bitmap data from an allegro BITMAP and move it into a contiguous array. What is the data format of a wxBitmap (How are the color values arranged - RGBA / BGR / RGB / ARGB?) or rather, what format does the wxBitmap constructor expect?

Also, I don't think bmp->dat is what you are looking for, but bmp->line[y].

Edit
On second thought just use the getpixel and then the getr, getg, getb, and geta functions to find the appropriate color component values. After that it should be fairly easy to convert them into whatever format the wxBitmap constructor is using.

Stepes
Member #10,390
November 2008

Hm how can I know what the bitmap representation is of a wxBitmap?
Got rid of the previous error which was a mistake of mine. Now it says that bmp.Ok() failed because its an invalid bitmap which sounds logical.

The constructor I try to use is:

wxBitmap(void* data, int type, int width, int height, int depth = -1)

Creates a bitmap from the given data which is interpreted in platform-dependent manner.

What you were suggesting is copying every pixel from one bitmap to the other in a loop? That would propably not work for me since I want a realtime particle editor and such a big loop in every animation loop would propably bring down my fps to the ground.(Plus I don't know how to write pixels on a wxBitmap)

Is the bitmap data representation in memory same for both libraries?(cant find documentation about it :/) How am I supposed to use the bmp->line? Copy each line of one bmp to the other?

I'm starting to think I might just change the whole code to wxBitmaps after all :P

anonymous
Member #8025
November 2006

Why don't you simply use wxWidgets' routines to load bitmap files?

If you can't do that, the conversion function should probably use the wxBitmap public interface (to set pixels), rather than make assumptions about the underlying data layout.

Stepes
Member #10,390
November 2008

(because if I use wxBitmap to load bitmaps then I can't blit them in allegro anymore)

Hm now that I thought about it, is there perhaps a way for allegro to blit on a device context or a panel of wx?
Or can it only blit to/from its own Bitmap structures?

Edit: Hm I looked at the code of another guy on these forums and this function propably does a similar job to what I want. I'll give it a try

void blit_from_allegro_to_wx(BITMAP *src, wxDC *target, int sx, int sy, int dx, int dy, int w, int h)
{
  wxPen pn(wxColour(0,0,0), 1, wxDOT);
  for(int x = 0; x < w; ++x)
  {
    for(int y = 0; y < h; ++y)
    { 
      pn.SetColour(((int **)src->line)[y][x] >> 16, (((int **)src->line)[y][x] >> 8) & 0xF, ((int **)src->line)[y][x] & 0xF);
      // make it active
      target->SetPen(pn);
      target->DrawPoint(dx + x, dy + y);
    }
  }
}

Edit2: Damn this code prints the whole image red. :/
Any idea what the correct shifts are to get the r,g,b information out of a line[y][x] ?

Edit3: WHY!?!?! WHY are allegro bitmaps in BGR format?? grrr took me 2 hours to figure out how it is. Finally it works now.
And the code was wrong after all... Here's the fixed version

void blit_from_allegro_to_wx(BITMAP *src, wxDC *target, int sx, int sy, int dx, int dy, int w, int h)
{
  wxPen pn(wxColour(0,0,0), 1, wxDOT);
  for(int x = 0; x < w; ++x)
  {
    for(int y = 0; y < h; ++y)
    { 
      pn.SetColour((((unsigned long **)src->line)[y][x]) & 0xFF, (((unsigned long **)src->line)[y][x]>> 8) & 0xFF,(((unsigned long **)src->line)[y][x] >> 16));
      // make it active
      target->SetPen(pn);
      target->DrawPoint(dx + x, dy + y);
    }
  }
}

The question remains though on if I can blit on wxDC's.
Because this idea didn't help much. It's way too costly to draw the bitmap each loop pixel for pixel

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Quote:

Edit3: WHY!?!?! WHY are allegro bitmaps in BGR format?? grrr took me 2 hours to figure out how it is. Finally it works now.

Allegro BITMAP's are in different formats for each color depth, and possibly even vary between platforms. So what you have might work for one color depth on your platform. That's why I suggested the getpixel, getr, getg, and getb functions.

Quote:

The question remains though on if I can blit on wxDC's.
Because this idea didn't help much. It's way too costly to draw the bitmap each loop pixel for pixel

Well, there are several problems with that function that will slow it down or are incorrect :
1. The pen should only need to be set once, not for every pixel. At least as far as I can tell from looking at the online WxWidgets manual anyway.
2. It incorrectly draws from the top left corner of the source bitmap and not from the source x or y.
3. As I said, it's probably only valid for 32 bit bitmaps.
4. It's being processed from top to bottom and left to right when it should be processed from left to right and then top to bottom. So the outer loop needs to iterate over y, not x. This will match the layout of the BITMAP in memory more closely.

I rewrote it as well as I could. I was using function pointers for getpixel etc..., but since the get pixel/r/g/b functions are AL_INLINE functions I used a switch statement with a case for each color depth and used the faster functions _getpixel#, and get?# (_getpixel32 , getr32, so on...).

Let me know if this speeds things up for you at all. I don't have WxWidgets installed, so let me know if it doesn't work - it's untested.

1//
2 
3void blit_al_to_wxdc(BITMAP* src , wxDC* dest , int srcx , int srcy , int destx , int desty , int w , int h) {
4 wxPen pn(wxColour(0,0,0) , 1 , wxDOT);
5 if (!src || !dest) {return;}
6 if ((srcx + w) > src->w) {w = src->w - srcx;}
7 if (w < 1) {return;}
8 if ((srcy + h) > src->h) {h = src->h - srcy;}
9 if (h < 1) {return;}
10
11 dest->SetPen(pn);
12 int color = 0;
13 int dx = 0;
14 int dy = 0;
15 int stopy = srcy + h;
16 int stopx = srcx + w;
17
18 switch (bitmap_color_depth(src)) {
19 case 32 :
20 for (int y = srcy , dy = desty; y < stopy ; ++y , ++dy) {
21 for (int x = srcx , dx = destx ; x < stopx ; ++x , ++dx) {
22 color = _getpixel32(src , x , y);
23 pn.SetColour(getr32(color) , getg32(color) , getb32(color));
24 dest->DrawPoint(dx , dy);
25 }
26 }
27 break;
28 case 24 :
29 for (int y = srcy , dy = desty; y < stopy ; ++y , ++dy) {
30 for (int x = srcx , dx = destx ; x < stopx ; ++x , ++dx) {
31 color = _getpixel24(src , x , y);
32 pn.SetColour(getr24(color) , getg24(color) , getb24(color));
33 dest->DrawPoint(dx , dy);
34 }
35 }
36 break;
37 case 16 :
38 for (int y = srcy , dy = desty; y < stopy ; ++y , ++dy) {
39 for (int x = srcx , dx = destx ; x < stopx ; ++x , ++dx) {
40 color = _getpixel16(src , x , y);
41 pn.SetColour(getr16(color) , getg16(color) , getb16(color));
42 dest->DrawPoint(dx , dy);
43 }
44 }
45 break;
46 case 15 :
47 for (int y = srcy , dy = desty; y < stopy ; ++y , ++dy) {
48 for (int x = srcx , dx = destx ; x < stopx ; ++x , ++dx) {
49 color = _getpixel15(src , x , y);
50 pn.SetColour(getr15(color) , getg15(color) , getb15(color));
51 dest->DrawPoint(dx , dy);
52 }
53 }
54 break;
55 case 8 :
56 for (int y = srcy , dy = desty; y < stopy ; ++y , ++dy) {
57 for (int x = srcx , dx = destx ; x < stopx ; ++x , ++dx) {
58 color = _getpixel(src , x , y);
59 pn.SetColour(getr8(color) , getg8(color) , getb8(color));
60 dest->DrawPoint(dx , dy);
61 }
62 }
63 break;
64 }
65}
66 
67//

Go to: