Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] loading multiple images stored in a single .dat

This thread is locked; no one can reply to it. rss feed Print
[A5] loading multiple images stored in a single .dat
Jay Hayden
Member #13,266
August 2011
avatar

using

  file = al_fopen("test.dat", "wb");
  al_save_bitmap_f(file,".png",sprite);
  al_save_bitmap_f(file,".png",sprite2);
  al_fclose(file);

I think I have created a .dat file with 2 pngs, but when I go to access them with

  file = al_fopen("test.dat", "rb");
  sprite2 = al_load_bitmap_f(file, ".png");
  std::cout<<"loaded file from .dat"<<std::endl;
  std::cout<<"size of bitmap: "<<sizeof(sprite2)<<std::endl;    
  al_fseek(file,11,ALLEGRO_SEEK_CUR);
  sprite = al_load_bitmap_f(file, ".png");  
  std::cout<<"read head at "<<al_ftell(file)<<std::endl;
  al_fclose(file);

sprite and sprite2 both contain the same image.
{"name":"8W3gm.gif","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/d\/cd4cc7727cee7a5e1464105da72996ef.gif","w":392,"h":296,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/d\/cd4cc7727cee7a5e1464105da72996ef"}8W3gm.gif

as an aside, I'm fairly sure my use of sizeof is incorrect. The size of the png is 41347, so shouldn't that be the result of sizeof? 4 would be the size of the pointer, but I'm not passing *sprite. Is there some indirection operator I'm missing?

Sorry for the newbie questions; I'm an artist, not a programmer (yet)

Matthew Leverton
Supreme Loser
January 1999
avatar

sizeof is a compile time thing, so there's no way it could return anything except the size of the pointer.

Also, what you are doing is not guaranteed to work. You need to load the data into a memfile and then use al_load_bitmap_f. Or if you are using 5.1, you can use al_fopen_slice.

Jay Hayden
Member #13,266
August 2011
avatar

The documentation page only has like 3 lines on al_open_memfile(), and I can't seem to make any usage of it compile.

How (explicitly) do I go about loading data into a memfile, and what data exactly am I trying to load into it? Am I loading the entire test.dat file, or only one image at a time?

and what does the parameter 'void *mem' mean? A pointer to empty memory? Does that mean I have to use malloc() or al_malloc()? I'm not even sure I understand what those functions do.

Thomas Fjellstrom
Member #476
June 2000
avatar

Sorry if the memfile docs aren't entirely clear.

You pass in a block of memory, it returns an ALLEGRO_FILE which you can then use the allegro file/fshook api on as if it were a real file. So things like al_load_bitmap work on chunks of memory.

A void pointer is just a way of specifying its just a pointer with no specific type associated.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Jay Hayden
Member #13,266
August 2011
avatar

Okay that makes a lot more sense. But if I still have to use al_fopen to load the .dat, then its contents are already in memory as an ALLEGRO_FILE type.

What's the purpose of a memfile here? do I pass the pointer of the ALLEGRO_FILE and just specify a smaller size to extract the individual .png files?

Thomas Fjellstrom
Member #476
June 2000
avatar

Okay that makes a lot more sense. But if I still have to use al_fopen to load the .dat, then its contents are already in memory as an ALLEGRO_FILE type.

Nope. Allegro does not load anything into memory when you al_fopen a file. You have to manually load the data with one or more of the al_fread* functions.

Quote:

What's the purpose of a memfile here?

Some image loaders like to seek around and not set the file position to 1 byte past the end of the last byte of the individual image. So when you try to load the next image, it starts at the wrong place. If you read each image into a chunk of memory and use the al_load_bitmap_f function to load from the memfile, there won't be any problems.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Matthew Leverton
Supreme Loser
January 1999
avatar

The problem with your original code is that there is no guarantee that the image loader will load all bytes of the image sequentially. It could make use of SEEK_SET, SEEK_END or leave the file open somewhere other than at the end.

The purpose of the memfile is that you explicitly load N bytes, where N is the known size of the image. You then pass those N bytes of memory to the image loader which can then do whatever it wants.

Alternatively, on 5.1 you can use al_fopen_slice() which allows you to treat a section of a file as if it were a whole file, and thus guarantees it to be compatible with the image loaders.

Jay Hayden
Member #13,266
August 2011
avatar

Ah, I think I understand now. I'll give it a shot. Thanks a lot both of you :D

I'm using 5.3, which means no al_fopen_slice. Why does 5.3 not have an equivalent function? It seems pretty useful.

SiegeLord
Member #7,827
October 2006
avatar

I'm using 5.3, which means no al_fopen_slice. Why does 5.3 not have an equivalent function? It seems pretty useful.

You're using 5.0.3 not 5.3. 5.1 is the development branch of Allegro 5, while you are using the stable branch (5.0 branch).

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Jay Hayden
Member #13,266
August 2011
avatar

Do you think it would be worth switching to the development version?

also, I'm fairly certain I still don't have the syntax for al_open_memfile right.

datfile = al_fopen("test.dat", "rb");
membuffer = al_open_memfile(membuffer,al_fsize(datfile),"rwb");
al_fread(datfile, membuffer,al_fsize(datfile));

sprite = al_load_bitmap_f(membuffer,".png");

I'm still unsure what I should pass as the void *mem parameter.

Thomas Fjellstrom
Member #476
June 2000
avatar

I'm still unsure what I should pass as the void *mem parameter.

You pass it a pointer to a chunk of memory that you previously loaded the image data you want to use with al_load_bitmap.

al_open_memfile returns an ALLEGRO_FILE, which you then use with al_load_bitmap.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Jay Hayden
Member #13,266
August 2011
avatar

now I'm 100% lost

#SelectExpand
1 //Open test.dat which contains 2 png images. 2 datfile = al_fopen("test.dat", "rb"); 3 4 //Load one image into ALLEGRO_BITMAP *sprite 5 sprite = al_load_bitmap_f(datfile,".png"); 6 7 //Create a memory file out of the chunk of memory where sprite now resides 8 membuffer = al_open_memfile(sprite,al_fsize(datfile),"rwb"); 9 10 //read the data from test.dat into this memfile 11 al_fread(datfile, membuffer,al_fsize(datfile)); 12 13 //Load 2 sprites from the memfile now? 14 sprite = al_load_bitmap_f(membuffer,".png"); 15 sprite2 = al_load_bitmap_f(membuffer,".png"); 16 17 //What the hell am I doing?

The image data that I want to use is contained in an external file, and I'm having trouble creating 2 bitmaps from it using al_load_bitmap; how does it help me to create a memfile from the single bitmap?

this code compiles and the application doesn't crash, but al_draw_bitmap(sprite) does nothing.

EDIT
So al_fread returns 0 meaning, I assume, it didn't copy anything into the membuffer, which means its empty? or does it contain the bitmap data from when I loaded sprite using al_load_bitmap_f the first time.

Thomas Fjellstrom
Member #476
June 2000
avatar

Oi.

The image data that I want to use is contained in an external file, and I'm having trouble creating 2 bitmaps from it using al_load_bitmap; how does it help me to create a memfile from the single bitmap?

You load up each bitmap in the data file one at a time, into a chunk of memory, then call al_open_memfile to obtain an ALLEGRO_FILE, then use al_load_bitmap_f to get an ALLEGRO_BITMAP from the memfile.

So first, you need to open the data file, then read the data for each image in the data file one at a time into a chunk of memory you obtained from malloc or new. Second, you create an ALLEGRO_FILE from each chunk of memory. And third, you create the ALLEGRO_BITMAPs from said ALLEGRO_FILE's.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Jay Hayden
Member #13,266
August 2011
avatar

Okay, I thought I needed to use some memory allocation, but my C++ professor is an old IBM project bum, and he's far more concerned with teaching UML than practical C++.

I'll take a shot at it and let you know how badly I screw up

Thank you for being so patient btw. :)

EDIT: the only usage I know of new is when I'm instantiating an existing construct.

al_fread says to give it the pointer that refers to a buffer, but I wouldn't literally type bitmapBuffer = new buffer would I?

Edgar Reynaldo
Member #8,592
May 2007
avatar

Is it just me, or isn't this what PhysFS is for? So you can read and write to zip files. Then you don't have to mess around with knowing how big each of your files is so you can allocate data to open with al_open_memfile.

Jay Hayden
Member #13,266
August 2011
avatar

I've read PhysicsFS on the API, but I didn't know how difficult it would be to include it in my project, so I didn't really consider it.

I'll do some more looking.

Do you know off-hand if the compression-decompression has any performance overhead?

EDIT:
It appears that only the source files are available, and I don't have the slightest hint of how to create the windows binaries I think i would need

Edgar Reynaldo
Member #8,592
May 2007
avatar

It's not hard to build PhysFS - I did it myself to build A5.1 SVN. Follow the directions in physfs-2.0.2/Install.txt. Whether you're building with MinGW or MSVC you will need CMake.

It doesn't look like PhysFS comes with the binary distributions of A5, so you'll have to build it yourself.

Thomas Fjellstrom
Member #476
June 2000
avatar

al_fread says to give it the pointer that refers to a buffer, but I wouldn't literally type bitmapBuffer = new buffer would I?

I think most of your problems stem from not quite knowing the language well enough. You might want to do some more studying.

When you want to create a buffer of bytes with new, you do something like:

char *buffer = new char[buffer_length];

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Matthew Leverton
Supreme Loser
January 1999
avatar

It doesn't look like PhysFS comes with the binary distributions of A5, so you'll have to build it yourself.

It is included.

Edgar Reynaldo
Member #8,592
May 2007
avatar

William Labbett
Member #4,486
March 2004
avatar

Before it's asked, you can't set a password on a PhysFS file.

Jay Hayden
Member #13,266
August 2011
avatar

Oh wow, I just spent half an hour building physfs with cmake and visual studio and now I realize that the binaries are included with the allegro 5.0.3 distribution

DERRRRRRRP

I can initialize physfs and it can open files just fine, but when I call
al_set_physfs_file_interface(); it grayscreens and the program goes unresponsive

EDIT: Nevermind, the problem occurs after I set the file interface. I'll find it and fix it.

EDIT: So it wasn't working because it was actually working correctly, odd as it seems.

I assumed that the compile directory stayed on the filesystem but you have to explicitly add it to the search path with PHYSFS_mount(). So everything works fine and dandy now, I can read files from a virtual filesystem handled by PhysicsFS that is created from a .zip of my resources.

Everything is so complicated. >___________< it all works, but it feels like if I sneeze on the damn thing everything will explode and I'll have to spend an hour trying to tape it back together again. thank you all for you help, though I warn you this is probably not the last time I'll need it.
If anyone needs some 2D graphics, I'd be glad to give something back instead of just being an information leech.

Go to: