Unwanted pixels showing up using masked_blit()
Matthew Dalrymple

I am using masked_blit() to draw tiles to the screen. When I draw a transparent tile to the screen it leaves some unwanted pixels as you can see in the image below. There is only 9 tiles being draw from the coord (0,0). Each tile is 64x64 pixels.
The tileset I am using is this:
I am drawing the bottom right one to the screen. (TILE: 3 AKA the 4th one coord: 1,1 or 2,2 however you look at it) (FYI: The file is actually a bitmap... imageshack just converted it to a png)
I was wondering how I can get rid of those pixels. I am also wondering what I should be drawing to the back of the screen. Right now I have it drawing the background to the transparent color.
clear_to_color(BackBuffer, bitmap_mask_color(BackBuffer));
(I then swap the BackBuffer to the screen when I am ready)
I can set the BackBuffer to any color, but when I do a masked_blit() with a transparent color, the transparent color shows up as black. Why is this and how can I fix it?
Last question: How come I cannot use other things to draw to the screen other than the first tool I use. i.e. If I use masked_blit() to draw something to the screen... If I then try and draw something with blit() or draw_sprite it will not be drawn to the screen.

Ron Ofir

Can you show some minimal code? Something like the function that draws a tile and the loop that draws them (or whatever you used in this particular example). It seems like either draw too much, or clear your buffer twice or something.

Matthew Dalrymple

Yeah here are some bits of my code

2cTile Tile;
4BITMAP* tile;
5tile = create_bitmap(64, 64);
6tile = Tile.GetTile(3);
10 for(int y = 0; y < 3; y++)
11 {
12 for(int x = 0; x < 3; x++)
13 {
14 thescreen.DrawToBuffer(tile, 0, 0, tile->w * x, tile->h * y);
15 }
16 }
17 thescreen.Swap();
18 vsync();

Here is the DrawToBuffer and Swap methods...

     BITMAP* BackBuffer
BOOL cScreen::DrawToBuffer(BITMAP* backbuf, int xpos, int ypos, int xdes = 0, int ydes = 0)
     masked_blit(backbuf, BackBuffer, xpos, ypos, xdes, ydes, backbuf->w, backbuf->h);
     return TRUE;

BOOL cScreen::Swap()
     masked_blit(BackBuffer, screen, 0, 0, 0, 0, BackBuffer->w, BackBuffer->h);
     return TRUE;

BOOL cScreen::ClearBuffer()
     clear_to_color(BackBuffer, bitmap_mask_color(BackBuffer));
     return TRUE;

If this may be helpful to you... here is some information from my tile class:

1BITMAP* cTile::GetTile(int TileNum)
3 // Is the Tile Number in range?
4 if(TileNum > ((m_Cols * m_Rows) - 1))
5 {
6 allegro_message("TileSet: %s\nTile: %d\nDoes not exhist!", m_Filename, TileNum);
7 TileNum = ((m_Cols * m_Rows) - 1);
8 allegro_message("Using Tile: %d", TileNum);
9 }
10 BITMAP* tile;
11 tile = create_bitmap(m_TileWidth, m_TileHeight);
12 int tilexpos = 0;
13 int tileypos = 0;
15 tileypos = ((TileNum / m_Cols) * m_TileHeight);
16 tilexpos = ((TileNum % m_Cols) * m_TileWidth);
17 masked_blit(m_TileSet, tile, tilexpos, tileypos, 0, 0, m_TileWidth, m_TileHeight);
18 return tile;


You must not use masked_blit() when you copy the back buffer to the screen. What do you want to achieve by this anyway? Also it doesn't make sense to call vsync() after drawing the back buffer to the screen.

Matthew Dalrymple

Well what should I use instead of masked blit? And I'm new to Allegro so I was playing with the vsync(), I didn't notice I copied that too.


Well what should I use instead of masked blit?


Matthew Dalrymple

Alright, well that was changed but had no effect on what is being seen on the screen. I heard there might be problems with making my graphics in MS Paint (Which that tile set was made in) What is another program I could use? Link? :-D


I heard there might be problems with making my graphics in MS Paint

Depends on which version you have, what format you save to and how you setup the gfx mode in Allegro and load the bitmap.


What is another program I could use?





Matthew Dalrymple

Recreating the graphic in another editor didn't help. I'm still seeing red dots.


Then post a simple but complete and compilable 20 line program that shows the error and we'll tell you what you're doing wrong.

James Stanley

Is it saved in a true bitmap format? If it is a JPEG then even though you draw magic pink from one pixel to the next, you end up with nearly magic pink. Trust me. I've done this myself. :)

Kris Asick

Matthew, I want you to take a very close look at the screenshot you've provided by using any graphics editor and filling the black area with white. You're going to notice that not only are the leftover colours not the same as your tile, you're also going to notice FOUR different colours being left over. Each bright pixel has another one beside them. The ones beside the green pixels are a dark blue and the ones beside the red ones are very slightly green.

Those colours are NOT coming from your bitmaps. So where are they coming from?

First, you really need to change your naming conventions. Naming a global object "tile", another global object "Tile" and a local object in CTile "tile" is extremely confusing.

Secondly, you've got a memory leak. You're calling:
tile = create_bitmap(64, 64);
...and then immediately afterwards in the CTile::GetTile() routine you're changing that freshly created bitmap to point to:
tile = create_bitmap(m_TileWidth, m_TileHeight);

So that's definitely something you need to fix, but it's NOT the cause of the pixels you're seeing.

Your problem has to do with how you're grabbing your tiles. Miran said you should be using blit() instead of masked_blit(). I agree, but not just for the back buffer, EVERYWHERE, except cScreen :: DrawToBuffer(), you want to leave that one as masked_blit(), or even draw_sprite() to simplify things.

Think about this: When you allocate some memory nothing's in it, except possibly remnants from other things previously in memory. That's where those coloured pixels are coming from. So why aren't they disappearing when you grab your tile with CTile::GetTile()? Because you're grabbing your tile with masked_blit()! Because the tile you're trying to grab is completely transparent, masked_blit() doesn't paste anything onto your bitmap, thus it STILL has memory remnants in it!

blit() ignores transparent pixels, blitting them exactly as they are.
masked_blit() pays attention to transparent pixels by NOT blitting them.

So, you have three changes you need to make:
1. Change all masked_blit() commands to blit() except for the one in cScreen :: DrawToBuffer().
2. REMOVE: tile = create_bitmap(64, 64);
3. Call vsync() BEFORE drawing to the screen, not after.

And you really should have a unique name for absolutely everything global to minimize confusion.

That should solve your problems.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Richard Phipps

Excellent analysis Kris.

Matthew Dalrymple

Yeah I fixed this problem yesterday by changing all my masked_blit()'s to regular blit()'s except for the one in my DrawToBuffer() method. This solved the problem. I will work on my naming method, I normally just call them whatever I want when I'm trying to test them out, sorry about the confusion. I need to rename my whole screen class because I've already created and fixed an error where I did this:

cScreen screen;
blit(randombitmap, screen, ...);

That tried to blit to my cScreen object instead of the screen >.< dope

Oh and to this:

Richard Phipps said:

Excellent analysis Kris.

It was an "Excellent analysis" very indepth and more people should think like that.

Thread #588362. Printed from Allegro.cc