Talk:SDL:Tutorials:Displaying a Bitmap from a zip file using SDL RWops and zlib
From GDWiki
[edit] zlib & SDL_RWops
This entry using SDL_RWops and zlib a bit limited in that you can only get SDL_RWops from a file. I'm trying to figure out how to get a SDL_RWops from a SDL_RWops of a zipfile, but I'm having problems with zlib's function calls.
I can copy a zip file into memory, call SDL_RWFromMem() on it to create a SDL_RWops, and then parse though the data to find the chunk of data that represents the compressed info. I get an error 'Z_DATA_ERROR' when I call zlib's uncompress() function.
compresseddata = new Uint8[compressedsize]; uncompresseddata = new Uint8[uncompressedsize]; blocks = SDL_RWread(rw, compresseddata, compressedsize, 1); if (blocks != 1) { printf("Error reading data.\n"); exit(1); } unsigned long size = uncompressedsize; ret = uncompress( uncompresseddata, &size, compresseddata, compressedsize ); printf("zlib::uncompress returns %d\n", ret);
Once I figure out how to get zlib to decompress the data, all that needs to be done is call SDL_RWFromMem() on it. Any help with using zlib would be appreciated.
-rppowell
Since zlib has functions that read from a zip file, you can write out the SDL_RWops into a temp file, re-open it with zlib functions and get the data from in that.
// This function returns a SDL_RWops of a file within a SDL_RWops of a zipfile SDL_RWops * SDL_RWops_From_SDL_RWops_zipfile( SDL_RWops *rw_zip, char *filename ) { char *tmpfilename; FILE *tmpfile; int size, i; Uint8 uint8; unzFile zip; unz_file_info info; Uint8 *buffer; SDL_RWops *rw_out; int result; // create and open unique tmpfile, keeping track of the name tmpfilename = tmpnam( NULL ); tmpfile = fopen(tmpfilename, "wb+"); // write the SDL_RWops into the tmpfile SDL_RWseek(rw_zip, 0, SEEK_SET); size = SDL_RWtell(rw_zip); if (size != 0) { printf("SDL_RWseek( SEEK_SET ) not at start of file\n"); return NULL; } SDL_RWseek(rw_zip, 0, SEEK_END); size = SDL_RWtell(rw_zip); SDL_RWseek(rw_zip, 0, SEEK_SET); for(i=0; i<size; i++) { result = SDL_RWread(rw_zip, &uint8, 1, 1); result = fputc(uint8, tmpfile); } fclose(tmpfile); // now we can use zlib/unzip functions to access 'tmpfilename' like a file zip = unzOpen( tmpfilename ); if ( zip == NULL ) { printf("Error opening tmpzipfile with unzOpen('%s')\n", tmpfilename); remove(tmpfilename); return NULL; } // search for the file within the zipfile result = unzLocateFile( zip, filename, 0 ); if ( result != UNZ_OK ) { printf("unzLocateFile('%s') != UNZ_OK(%d)\n", filename, result); unzClose(zip); remove(tmpfilename); return NULL; } result = unzGetCurrentFileInfo( zip, &info, NULL, 0, NULL, 0, NULL, 0 ); if ( result != UNZ_OK ) { printf("unzGetCurrentFileInfo() != UNZ_OK (%d)\n", result); unzClose(zip); remove(tmpfilename); return NULL; } result = unzOpenCurrentFile( zip ); if ( result != UNZ_OK ) { printf("unzOpenCurrentFile() != UNZ_OK (%d)\n", result); unzClose(zip); remove(tmpfilename); return NULL; } buffer = new Uint8[info.uncompressed_size]; result = unzReadCurrentFile( zip, buffer, info.uncompressed_size ); if ( result != info.uncompressed_size ) { printf("unzReadCurrentFile() Error (%d != %d)\n", result, info.uncompressed_size); delete buffer; remove(tmpfilename); return NULL; } unzClose(zip); remove(tmpfilename); rw_out = SDL_RWFromMem(buffer, info.uncompressed_size); if(!rw_out) { printf("Error with SDL_RWFromMem: %s\n", SDL_GetError() ); delete buffer; return NULL; } // Note: we do not handle deleting the allocate memory for the new SDL_RWops, // SDL_freeRW() should do that for us. return rw_out; } SDL_RWops *zip; SDL_RWops *bmp; // open our zipfile into a SDL_RWops zip = SDL_RWFromFile("data.zip", "rb"); if(!zip) { printf("Error opening archive.zip with SDL_RWFromFile: %s\n", SDL_GetError() ); exit(1); } bmp = SDL_RWops_From_SDL_RWops_zipfile(zip, "bitmap.bmp");
In theory, we can also access zipfiles from within zipfiles.

