[A5] trouble writing ALLEGRO_BITMAP to zip file

So I have an ALLEGRO_BITMAP in memory and I want to save the image in this case a tga file to a zip file.

Currently I am using libzip to write the zip file.
My problem comes from when I want to save the zip file again so I need to copy files from my existing archive into the new one.

I could just use physfs to grab the file instead of where it has been loaded into memory but I don't think it matters too much just as long as I have a file in memory I can do stuff with.

Basically the issue is that the files that are created in the archive are unreadable and often just garbage and don't have the expected end for a TGA file.

I also tried al_load_bitmap_f(memfile ".tga") just after saving it and the bmp was always null, not sure if I was using it wrong or not though.

It is true that if I save the file and then put it in the archive it works fine that way but I'd prefer to have to save it somewhere to disk if I can help it.

I'm sure there is something important I don't realise oh and al_init_image_addon(); and al_init() have been called so its not that.

1 2 PHYSFS_addToSearchPath(al_path_cstr(setPathGlb,'/'),1); 3 PHYSFS_File *currentGraphicFile = PHYSFS_openRead(it->first.c_str()); 4 int length = PHYSFS_fileLength(currentGraphicFile); 5 PHYSFS_close(currentGraphicFile); 6 7 void *fileBuffer; 8 void *graphicBuffer; 9 10 int dot = it->first.find_last_of("."); 11 std::string basename = it->first.substr(0, dot); 12 13 std::unordered_map<std::string, Graphic*>::const_iterator got; 14 if( (got = currentSetMap->find(basename)) != currentSetMap->end() ) 15 { 16 17 length+=8000; //just make it much bigger for now 18 19 ALLEGRO_BITMAP *bmp = got->second->getBitmapImage(); 20 21 fileBuffer = malloc(length); 22 ALLEGRO_FILE *memfile = al_open_memfile(fileBuffer, length, "w+b"); 23 24 bool result = al_save_bitmap_f(memfile, ".tga", bmp); //temp as .tga instead of generically 25 graphicBuffer = malloc(length); 26 27 size_t bytes = al_fread(memfile, graphicBuffer, length); 28 printf("bytes=%i\n", bytes); 29 printf("eof?=%i\n",al_feof(memfile)); 30 printf("error?=%i\n",al_ferror(memfile)); 31 32 33 zip_source *currentGraphicSource = zip_source_buffer(z, graphicBuffer, length, 0); 34 zip_add(z, it->first.c_str(), currentGraphicSource); 35 36 al_fclose(memfile); 37 length-=8000; 38 } 39 40 free(fileBuffer); 41 free(graphicBuffer);


After your al_save_bitmap_f call the file pointer will be at the end of the file just written. So the next al_fread cannot work. Either use al_fseek to reset the position or close and re-open the memfile.


thought it might be something obvious like that but I'm still not quite there yet. drawing the bmp from the memfile works fine but saving it either to file or to a buffer doesn't seem to be working for me.

Ignoring writing to the buffer for now and trying to write to file it looks like it almost creates a valid tga file but irfanview can't read it but at least it thinks its a tga file instead of unrecognised now.

EDIT: well that was kindof dumb of me forgetting to close the file....


Lets try again and do the real problem of writing to the buffer
So the problem is that it never seems to write the right stuff to the buffer i think. I'm not sure on the difference with using a void* buffer opposed to a char* buffer but if I use a char* buffer it definitely comes out empty

It seems odd to me that the bytes written to the buffer is significantly bigger then the bytes written to the memfile. Something like 11000 compared to 4116 I expected a little bit more but not nearly that much.

I definitely know that it is in the memfile because I can al_load_bitmap_f() from it and draw it on the screen. But I've had no luck actually writing it to file and instead get an invalid TGA file.

1fileBuffer = malloc(length); 2 ALLEGRO_FILE *memfile = al_open_memfile(fileBuffer, length, "rw"); 3 4 int pos = al_ftell(memfile); 5 printf("initpos=%i\n", pos); 6 7 bool result = al_save_bitmap_f(memfile, ".tga", bmp); //temp as .tga 8 printf("save result = %i\n", result); 9 10 int endpos = al_ftell(memfile); 11 printf("save endpos=%i\n", endpos); 12 length = endpos; 13 14 al_fseek(memfile,0,ALLEGRO_SEEK_SET); 15 16 length*=3; 17 graphicBuffer = malloc(length); 18 void *buf = malloc(length); 19 20 int bytes = al_fread(memfile, buf, length); 21 printf("bytes=%i\n", bytes); 22 printf("eof?=%i\n",al_feof(memfile)); 23 printf("error?=%i\n",al_ferror(memfile)); 24 al_fseek(memfile,0,0); 25 26 27 28 zip_source *currentGraphicSource = zip_source_buffer(z, graphicBuffer, bytes+1, 0); 29 30 zip_add(z, it->first.c_str(), currentGraphicSource); 31 free(buf); 32 al_fclose(memfile);

Looks like I worked out and isn't it obvious what the problem is.
So playing around I checked that the buffer was being saved properly and that it was. The issue is that while the file is added to the zip archive its apparently not saved until zip_close() is called and I had already cleared the buffers before than and so it only saved garbage to the file.

Thread #614010. Printed from Allegro.cc