Direcly loading pngs to save game size?

My current project is roughly 500mb in size and that is because of png files and how they are converted into xnb. Xnb’s take a lot of space but pngs are 100 times smaller.
What I want to do is:

  1. Convert all pngs in to 2048x2048 sprite sheets. Because there are won’t be a lot of images it would minimize the amount of file streams.
  2. Write a personal mini Content class for loading pngs instead of xnbs using Texture2D.fromStream()

I am most likely going to publish the game only on Windows (possibly Linux). So I am okay if it will harm cross platforming.
Compressed xnb doesn’t work for me because they still take a lot of space.

What I am asking is how will it effect the performance? How will it effect the RAM usage? What should I expect?

Loading the textures might take a little longer because the images will need to be decompressed, but there’s less data that needs to be read from file which mitigates the performance impact. I doubt it will be an issue. RAM usage won’t be affected except maybe a little during the loading of the textures. MG doesn’t store texture data in RAM, it goes directly to VRAM when loaded.

There are two orthogonal alternatives to reduce file size with the Pipeline Tool. Firstly you can enable lossless compression for xnb’s in the root node of the Pipeline Tool (it uses generic compression, so it won’t reduce file size as much as converting to png’s). Secondly you can compress your textures individually with the Pipeline Tool. The formats that MG compresses to are directly supported for rendering on the GPU, so the textures don’t need to be decompressed and take up less VRAM. Note that this is lossy compression and texture quality will be affected.

1 Like

If its just going to be for windows linux and you are going to use fromStream

Make a folder in your project like Assets or something.

right click on that folder
select Add
select Existing Item (browse for the png on your drive to add it to the project)
then Right click on the file
select Properties
in the drop downs select Copy to Output Directory
select copy if Newer.

When loading the files using from stream the above would put the files in… Path.Combine(Enviroment.CurrentDirectory, Assets, … filename) folder when you build the project.
It will update it if you alter the image when you rebuild.
You need to include the using directorys for System and System.Io;

You probably should use the other one to load for the path, instead of enviroment.currentdirectory i forget the name of it appdomain basedomain or something its supposedly more reliable.

Since you are not using the content pipeline in UnloadContent (you need to call dispose) on each texture you have loaded.

When loaded pngs will expand to the equivalent color array uncompressed size. For windows linux this may or may not be a problem
If the the size is a problem and you need to manually unload textures during run time you should make a separate topic on how to do that properly in this specific case basically you will need to properly call dispose on a texture to unload it during runtime and check if it IsDisposed() if you wish to reuse that texture reference.

As for the speed of loading this will probably take a bit longer however you can start the game and make a loading function that asycronously loads each file then draws a texture, with a loading screen from a initial game loading mode (load the images to display to the user first) this will make it take even slightly longer to load but seem like the game is more professional.

1 Like

Thanks. That is a good quality of life idea!

Thank you for the detailed response!
I tried to turn on compression and it reduced the content size from 500mb to 475mb. So I am going to stick to the original plan

1 Like