Load raw pixel data into Allegro Bitmap
The Master

Hey guys,
I'm trying to load pixel data from a TileStudio map into a Bitmap. Basically my code locks a square on the tileset bitmap and then freads it into the locked area.

  bytesPerTile = 4 * m_iTileHeight * m_iTileWidth;
  // now load the tiles
  for ( byCount = 0; byCount < m_iTileCount; byCount++ ) {

    // calculate the location on the grid of the current tile
    x  = ( byCount % m_byTilesPerRow ) *  m_iTileWidth;
    y = ( byCount / m_byTilesPerRow ) * m_iTileHeight;

    // now load the tile into the bitmap
    tileRegion = al_lock_bitmap_region( m_pTileBitmap, x, y, m_iTileWidth, m_iTileHeight, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_WRITEONLY );
    al_fread( pFile, tileRegion->data, bytesPerTile );
    al_unlock_bitmap( m_pTileBitmap );

  }

However its showing up blue and distorted. Any reason why?

weapon_S

The pixel format has to be exactly the same between the file on disk and the ALLEGRO_BITMAP in (video)memory. Bitmaps usually have a header (data that is not pixels). ALLEGRO_BITMAPs can have 'padding' between lines IIRC[1]. I.e. you need skip some bytes when writing to it. There was an example, but I can't remember where...
If it's only for loading purposes al_put_pixel can also be used on locked bitmaps, and it takes care of the 'stride' issue.
BTW I think a nested loop would look cleaner.

Johan Halmén

Quick guess

Blue: You're only writing to the blue channel. Like loading single bytes from an 8 bit image and putting them into a 24 bit bitmap.

Distorted: A square (or any rectangular) area of a bitmap is not consecutive memory.

The Master

ok, sounds good. I did use al_put_pixel at first, but I found it took up to a minute to load a 45-tile set with tile size 32x32. So I wanted something that ran faster.
I'll have a shot at using stride. Hopefully it'll work better.

-- EDIT --
Must say, not really digging the pitch approach. Just how much padding do the bitmaps have, anyway? Here's my new approach:

    // now load the tile into the bitmap
    tileRegion = al_lock_bitmap_region( m_pTileBitmap, x, y, m_iTileWidth, m_iTileHeight, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_WRITEONLY );
    for( j=0; j < m_iTileHeight; j++ ) {
    
      p = (size_t*)tileRegion->data + j * tileRegion->pitch;
      al_fread( pFile, p, m_iTileWidth*4 );

    }
    al_unlock_bitmap( m_pTileBitmap );

weapon_S

Must say, not really digging the pitch approach.

Do you have a choice? :P

Quote:

Just how much padding do the bitmaps have, anyway?

In any case the ones in memory will have more than the ones on disk >_> Unless, maybe if you use a non-video memory bitmap.

Matthew Leverton

The pitch is in bytes, so I think you are advancing 4 or 8 times too far (depending if you are 32-bit or 64-bit). Try:

p = (char*)tileRegion->data + j * tileRegion->pitch;

The Master
weapon_S said:

Do you have a choice? :P

What I meant to say is, I've tried the pitch approach, and it segfaulted.
I'll have a shot using what Leverton suggested.

-EDIT-
Ok, that worked. However, the colour's all confused. The greens are greens, but the browns are blues, and the blues are yellow. I'm still iffie on how colour conversion works.

weapon_S

Try other pixel formats[1]? There are differences in which order each color component is stored. (Apparently it is 32-bit and there is no header, when your image isn't distorted.)
You don't have any colour conversions; You're loading raw data.

The Master

I got it working. Just the endian-ness issue. Anyway, now comes to the drawing part.
What I've got now is a proper, non-colour-confused rendering of the map. However, when it renders tiles that have a portion transparent (like part of a pillar or something), it draws semi-transparent mask colour (as in [255,0,255]) where it should be drawing nothing. This didn't happen before when I just used put_pixel, and al_convert_mask_to_alpha doesn't seem to do anything. The bitmap format is ARGB 32bit.

-EDIT-
Got it working. But it's a bit of an ugly hack with TileStudio. I had to fix the export so that instead of outputting the proper alpha channel from the tile, TileStudio just outputs 255. This will make it hard if/when i want to do transparency in tiles rather than just masks.

weapon_S

Loading the alpha should work perfectly. Maybe the blender was set wrong?

Thread #609176. Printed from Allegro.cc