getpixel() crashes program?
Crystylla

I'm trying to put together a Tetris clone called Bubbles using the Allegro library. It was all going swimmingly until I tried to display the bubbles (the blocks that make up the shapes).

See, I'm storing both the grid area and the current shape as small bitmaps a few pixels wide and tall, where one pixel corresponds to one block on screen. As such, I have to check what colour a given pixel is so that I can print the appropriate colour of block onto the screen. And that's where the problem lies.

I try to grab the pixel in question and compare it to my pre-defined colours in some way, to decide what to print to the screen. But every way I try to use to compare the two colours ends up crashing my program. I've tried defining RGB colours and comparing them to the colour grabbed with getpixel(), directly comparing the pixel grabbed to a pixel from a bitmap that exists for the sole purpose of being an example of all of the colours... everything crashes it.

Here's the relevant bit of code (actually, the real thing has more ifs, but they're mostly the same as the first anyway). The loops cycle through all the pixels in the shape bitmap, and the if statement SHOULD print a red bubble in the correct place if the pixel is red. The draw_sprite() by itself works like a charm, but trying any kind of colour comparison makes it crash.

         for(int y = 0; y < c_height; y++) {
              for(int x = 0; x < c_width; x++) {
                   if(_getpixel(cluster, x, y) == makecol(255, 0, 0)) {
                         draw_sprite(buffer, red, (left + ((c_x + x) * b_width)), (top + ((c_y + y) * b_height)));
                   }
              }
         }

I've been experimenting with trial and error for the past few hours, and searching these forums for likely topics, but nothing so far has worked. So a little wisdom from all you Allegro experts would be greatly appreciated.

P.S., try to keep explanations insultingly simple - I'm an Allegro newbie. ;)

Evert

Are your bitmaps 8 bit?
_getpixel() only works for 8 bit bitmaps. For higher colour depths, you need to use the proper version (be sure to check the manual for other caveats).

There are better waysto accomplish what you want than what you're doing now, but I'll leave it at the above for now.

Onewing
Quote:

P.S., try to keep explanations insultingly simple - I'm an Allegro newbie.

First off and foremost, have you stepped through it using a debugger of any kind? I think _getpixel() crashes if it tries to get a pixel outside the bitmap, but getpixel() will return a -1.

Crystylla

The bitmaps are all 24-bit (or they should be; that's what I saved them saved as). I tried the regular getpixel() as well (in fact, I only tried changing it to _getpixel() recently, in desperation), but that crashes just the same.

The point I'm checking is definitely inside the bitmap. I tried commenting out the loop and just giving it some test co-ordinates to make sure that the loop's x and y values weren't messing it up. And I'll know if it's returning the right thing, because the red bubbles should appear on screen (the Dev-C++ debugger doesn't seem to want to co-operate with me right now).

EDIT: Actually, the bubble and background bitmaps, which are loaded from bitmap files, are 24-bit... but the bitmaps I don't load from files, I don't know.

LennyLen
Quote:

but the bitmaps I don't load from files, I don't know.

Their bit depth will be whatever you set with set_color_depth. If you didn't set a color depth, they will be 8bit.

Evert
Quote:

The bitmaps are all 24-bit (or they should be; that's what I saved them saved as).

Doesn't work with _getpixel then.

Quote:

I tried the regular getpixel() as well (in fact, I only tried changing it to _getpixel() recently, in desperation), but that crashes just the same.

Odd. Check that cluster, buffer and red are valid bitmaps. Try making a small example program that reproduces the error.

Crystylla

Okay, I just tried setting it to 24-bit, and I still get a crash.

(In other news: On closer inspection, I noticed that yeah, setting to x and y to zero at the start of the loops wasn't going to get me far in terms of bitmap co-ordinates, so I've changed that. Also, make x < c_width into x <= c_width to accomodate for that. Same with y.)

for(int y = 1; y <= c_height; y++) {
              for(int x = 1; x <= c_width; x++) {
                   if(getpixel(cluster, x, y) == makecol(255, 0, 0)) {
                         draw_sprite(buffer, blue, (left + ((c_x + x) * b_width)), (top + ((c_y + y) * b_height)));
                   }

You know, I've tried this project before, and then I used char arrays instead of bitmaps to do this (and switch statements instead of if statements). That worked, but I thought this seemed neater somehow. What do you reckon?

EDIT: Trying your advice now, Evert...

LennyLen
Quote:

On closer inspection, I noticed that yeah, setting to x and y to zero at the start of the loops wasn't going to get me far in terms of bitmap co-ordinates, so I've changed that.

You had it right the first time. The top-left pixel in a bitmap is co-ordinate 0,0.

Crystylla

I did? Hmm, thanks. I'll change it back...

As far as I can see, cluster, buffer and red are valid. I tried throwing together a small test program, but this crashes, too...

1#include <allegro.h>
2 
3void init();
4void deinit();
5 
6int main() {
7 init();
8
9 while (!key[KEY_ESC]) {
10 BITMAP *red;
11 BITMAP *background;
12 BITMAP *grid;
13 BITMAP *buffer;
14
15 background = load_bitmap("images/background.bmp", NULL);
16 red = load_bitmap("images/bubble_red.bmp", NULL);
17 clear_to_color(grid, 0);
18 clear_to_color(buffer, 0);
19
20 draw_sprite(buffer, background, 0, 0);
21
22 if(getpixel(grid, 0, 0)) {
23 draw_sprite(buffer, red, 5, 5);
24 }
25
26 blit(buffer, screen, 0, 0, 0, 0, 320, 400);
27 clear_bitmap(buffer);
28 }
29
30 deinit();
31 return 0;
32}
33END_OF_MAIN()
34 
35void init() {
36 int depth, res;
37 allegro_init();
38 //depth = desktop_color_depth();
39 //if (depth == 0) depth = 32;
40 set_color_depth(24);
41 res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
42 if (res != 0) {
43 allegro_message(allegro_error);
44 exit(-1);
45 }
46
47 install_timer();
48 install_keyboard();
49 install_mouse();
50 /* add other initializations here */
51}
52 
53void deinit() {
54 clear_keybuf();
55 /* add other deinitializations here */
56}

miran

The only way you can make getpixel crash is if you give it an invalid bitmap pointer. Are you sure cluster is an actual valid pointer to a BITMAP? If cluster is a bitmap that you load from disk, then maybe this is the right moment to start checking if load_bitmap() was actually successful or not.

EDIT: In the example above grid is uninitialized.

LennyLen

Also remove:

  if (res != 0) {
    allegro_message(allegro_error);
    exit(-1);
  }

Since you haven't defined res.

edit: Never mind that. I just missed where you did.

miran

Also you made a huge enourmous gigantic memory leak.

Crystylla
Quote:

The only way you can make getpixel crash is if you give it an invalid bitmap pointer. Are you sure cluster is an actual valid pointer to a BITMAP? If cluster is a bitmap that you load from disk, then maybe this is the right moment to start checking if load_bitmap() was actually successful or not.

Ah... now that I look at it, I think it is the cluster that's causing it to crash. I'll see if I can't fiddle with the cluster to make it work. Huge thanks!

Quote:

Also you made a huge enourmous gigantic memory leak.

By putting everything into the loop? Oops. Sorry about that, I was being rushed to get off the PC for a while.

LennyLen
Quote:

I was being rushed to get off the PC for a while.

So you decided to put everything in a while {} then? ;)

Dustin Dettmer
1#include <allegro.h>
2 
3void init();
4void deinit();
5 
6int main() {
7 init();
8 
9 BITMAP *red;
10 BITMAP *background;
11 BITMAP *grid;
12 BITMAP *buffer;
13
14 background = load_bitmap("images/background.bmp", NULL);
15 red = load_bitmap("images/bubble_red.bmp", NULL);
16 grid = create_bitmap(320, 400);
17 buffer = create_bitmap(640, 480);
18 clear_to_color(grid, 0);
19 clear_to_color(buffer, 0);
20 
21 if(!background) {
22 allegro_message("Unable to load \"images/background.bmp\".\n");
23 exit(1);
24 }
25 
26 if(!red) {
27 allegro_message("Unable to load \"images/bubble_red.bmp\".\n");
28 exit(1);
29 }
30
31 while (!key[KEY_ESC]) {
32
33 draw_sprite(buffer, background, 0, 0);
34
35 if(getpixel(grid, 0, 0)) {
36 draw_sprite(buffer, red, 5, 5);
37 }
38
39 blit(buffer, screen, 0, 0, 0, 0, 320, 400);
40 clear_bitmap(buffer);
41 }
42
43 deinit();
44 return 0;
45}
46END_OF_MAIN()
47 
48void init() {
49 int depth, res;
50 allegro_init();
51 //depth = desktop_color_depth();
52 //if (depth == 0) depth = 32;
53 set_color_depth(24);
54 res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
55 if (res != 0) {
56 allegro_message(allegro_error);
57 exit(-1);
58 }
59
60 install_timer();
61 install_keyboard();
62 install_mouse();
63 /* add other initializations here */
64}
65 
66void deinit() {
67 clear_keybuf();
68 /* add other deinitializations here */
69}

Crystylla

Thanks guys, it works beautifully now! ;D

(Yeah, it was the cluster that was breaking it... heh.)

Thread #588282. Printed from Allegro.cc