Loading a Texture From a Zip File in DirectX 9
by Greg Stewart



This is a simple article on how to load textures from .ZIP files. I am using DirectX 9 (with the D3DX utility library) and unzip.h by Gilles Vollant (his work uses / is based on zlib). This code is for those programmers who might be interested in loading their images (or any file for that matter) from a .ZIP file for either compression or archival purposes (or both).

Why not just include the images as resources into your .EXE? Well, first of all, including many large images as resources can increase your .EXE size and compilation time. Plus, .ZIP files are cool and practically everyone already has a compression program that can create them. Just think of all the space you'll save.

The Code

Using D3DX and the included unzip code makes everything easy. The idea is to use the unzip functions to open the zip file, find which file we want, and load it into memory. After we have it in memory, we can use D3DXCreateTextureFromFileInMemory() to load the image (which can be in .bmp, .dds, .dib, .jpg, .png, or .tga format). I do not claim that this code is the right way, nor the fastest or best way to do this. That being said, here is a function that wraps up all the .ZIP handling and texture creation code into one little package:

// CreateTextureFromFileInZip()
//  pDevice   The D3D9 device
//  szZip     The .zip file
//  szFile    The image file within the .zip
//  ppTexture A pointer to the newly created texture
//  Return values:
//  S_OK      Everything went ok.
//  E_FAIL    Everything did not go ok. :-)
//  E_OUTOFMEMORY  I'll let you guess on this one.

HRESULT CreateTextureFromFileInZip( LPDIRECT3DDEVICE9 pDevice, LPCSTR szZip,
                                    LPCSTR szFile, LPDIRECT3DTEXTURE9 *ppTexture )
  // open ZIP
  unzFile zip = unzOpen( szZip );

  if( !zip )
    return E_FAIL;
  // locate the file and open it (1 means case sensitive comparison)
  unzLocateFile( zip, szFile, 1 );
  if( unzOpenCurrentFile( zip ) != UNZ_OK )
    return E_FAIL;
  // find current file info (we are looking for uncompressed file size)
  unz_file_info info;
  unzGetCurrentFileInfo( zip, &info, NULL, 0, NULL, 0, NULL, 0 );
  // create a buffer big enough to hold uncompressed file in memory
  void *buffer = malloc( info.uncompressed_size );

  if( !buffer )
    unzCloseCurrentFile( zip );
    unzClose( zip );

    return E_OUTOFMEMORY;
  // load into memory
  unzReadCurrentFile( zip, buffer, info.uncompressed_size );
  unzCloseCurrentFile( zip );
  unzClose( zip );

  // use D3DX utility library to load our texture now.
  if( FAILED( D3DXCreateTextureFromFileInMemory( pDevice, buffer,
        info.uncompressed_size, ppTexture ) ) )
    free( buffer );
    return E_FAIL;

  free( buffer );
  return S_OK;

Notes & Improvements

The CreateTextureFromFileInZip() function (whew! long name!) is rather easy to use. However, it is not the most efficient thing in the world. You may want to modify the code so if you are loading multiple files from the same .ZIP, you only need to load the .ZIP once. As it is, opening and closing the .ZIP file for each image is rather redundant. And of course, the wonderful call to malloc is regarded by some as evil. You could perhaps create a static buffer that is big enough to hold your largest image (uncompressed) and just reuse the same buffer for all your image loading. This would eliminate the need for malloc()/free(). However, D3DXCreateTextureFromFileInMemory() probably uses malloc() anyways, right?

The included MSVC++ workspace and code demonstrate how to use this function. Nothing too fancy.


Thanks for reading and I hope somebody found this article to be of use.

Discuss this article in the forums

Date this article was posted to GameDev.net: 9/11/2003
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
Sweet Snippets

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!