Get binary stream of bitmap - al_save_bitmap_f() or something like this
JurekGP

My problem is about get a binary stream of bitmap. I'd like to saving the bitmap into my file through std::ofstream stream.
Before, I saved my bitmap to file and then read it so I got (char*)buffer which I could include to my file. But this idea is not very optimal so I want to bypass it.

I tried two ways, but anyone didn't work.

1. I try with ALLEGRO_FILE. I wanted to get char* buffer of bitmap file and then saved it into my file (it is experimental, it's not about saving just to PNG file but let's suppose).

int size;
char* buffer = gameCore->bitmapLoader->saveBitmap_f(".png", bmpo, size);
    
std::ofstream file("eksperyment.png", std::ios::out | std::ios::binary | std::ios::trunc);
file.write(buffer, size);
file.close();

char* BitmapLoader::saveBitmap_f(std::string fileType, ALLEGRO_BITMAP *bitmap, int &size)
{
  size = al_get_bitmap_width(bitmap) * al_get_bitmap_height(bitmap) * 4;
  void* fBuffer = malloc(size);
  ALLEGRO_FILE *fp = al_open_memfile(fBuffer, size, "rwb");
  if(!al_save_bitmap_f(fp, fileType.c_str(), bitmap))
    return NULL;

  unsigned fileLength = al_ftell(fp); // I don't know exactly if better is size variable or this fileLength. But I thing is this, because is calculate from fp file, have more correctly value than size variable. I think if bitmap is saving to AL_FILE is compressing to its own format? Doesn't have just 800x800 pixels but is saved with PNG headers etc... isn't? But 2,5k KB is just 800x800x4 so it's this value like size.
  al_fread(fp, fBuffer, fileLength);

  return (char*)fBuffer;
}

With this code up, I get from original bitmap 800x800 px (here called "bmpo"), PNG file of weight 2500 KB and it's unreadable.
On the beginning I had a trouble with function al_save_bitmap_f(fp, fileType.c_str(), bitmap), but it's probably because malloc of void pointer, I thing allocated not enough memory. Now it's work.

2. Because first thing doesn't work I found code like this. This code wasn't tested. On beginning it didn't work too, but finally I understand better this algorithm and get exactly this same unreadable file like before.

std::string buffer = gameCore->bitmapLoader->BitmapBytes(bmpo);
std::ofstream file("eksperyment.png", std::ios::out | std::ios::binary | std::ios::trunc);
file.write(buffer.c_str(), buffer.size());
file.close();

#SelectExpand
1std::string BitmapLoader::BitmapBytes(ALLEGRO_BITMAP* bmp) 2{ 3int size = al_get_bitmap_width(bmp)*al_get_bitmap_height(bmp)*4; 4void* buffer = malloc(size); 5if (!buffer) 6 return NULL; 7 8unsigned long width = al_get_bitmap_width(bmp); 9unsigned long height = al_get_bitmap_height(bmp); 10ALLEGRO_LOCKED_REGION* lock = al_lock_bitmap(bmp , ALLEGRO_PIXEL_FORMAT_RGBA_8888 , ALLEGRO_LOCK_READONLY); 11//ALLEGRO_LOCKED_REGION* lock = al_lock_bitmap(bmp , al_get_bitmap_format(bmp), ALLEGRO_LOCK_READONLY); I tried also like that but it doesn't work. 12 13for (unsigned long y = 0 ; y < height; y++) { 14 void* dat = (char*)lock->data + 4*y*width; 15 memcpy((void*)((char*)buffer + 4*y*width), dat, 4*width); 16} 17 18al_unlock_bitmap(bmp); 19std::string s(static_cast<const char*>(buffer), size); 20// You could use 'sp' directly, or this, which does a copy. 21//std::string s = *sp; I found also something like this but it throw exception. 22return s; 23}

I left comments in code, it give how I thought.

SiegeLord

I'm surprised that the first method didn't work. For your use case, you might also implement your own file vtable (see al_create_file_handle and the implementation of the memfile addon).

Have you tried saving the via al_save_bitmap and seeing how big that file was?

JurekGP
SiegeLord said:

For your use case, you might also implement your own file vtable (see al_create_file_handle and the implementation of the memfile addon).

I've never had to deal with it. I must implement those functions: https://www.allegro.cc/manual/5/allegro_file_interface ? I don't know how it will be help me. In those function I write excatly the same code, how wrote before. You mean maybe it change mode of action?

Quote:

Have you tried saving the via al_save_bitmap and seeing how big that file was?

Yes, on begin I save this bitmap as physical, temporary file with this function, but this way is not too optimal so I want to change it. In this case original bitmap PNG have 1049 KB, but bitmap PNG saved through this function have 1540 KB.

SiegeLord
JurekGP said:

I don't know how it will be help me. In those function I write excatly the same code, how wrote before. You mean maybe it change mode of action?

The main difference is that you'd be able to make it be backed by std::vector so you wouldn't need to know the in-memory size of your file ahead of time and you'd also know exactly how big the file is ( al_ftell only tells if you where the last file position is, so if the writer used al_fseek for some reason, it'd tell you something weird).

Thread #616035. Printed from Allegro.cc