MonoGame Content Pipeline XNB Compression not compressing

hi,
Not sure if something may be wrong with my MGCB editor, I enabled Compress to True at the top level, but when running it all my XNB files still are uncompressed and wasting a lot of space, does anyone have the same problem? I am trying to compress PNG files but I still get the big files same in Debug and Release with the Compress option enabled.

PNG is already compressed, if try compressing again, they could get larger.

well the png image is just about 200 kb , but the xnb is about 4 megabytes, both compressed and uncompressed mode, so somehow it is not working.

Yeah, that sounds like there is an issue or it’s an obscene amount of overhead.

are you able to compress png files? when I open the MGCB inside visual studio and compile it I get an error:

An unhandled exception occured in [21616] dotnet.exe

if I ignore it, it will create the xnb files as usual, but compress doesn’t make any difference. Even if I try the debugger with that error in dotnet, it doesn’t open correctly saying there are more errors in the dotnet thing. But everything gets a green check in the MGCB editor after I close the debugger.

I do not get any compile errors. I have an PNG that is 425 bytes and the XNB for that file is 9.08K.

Almost 22X the size…

I also have a PNG that is 181 bytes (It’s a Single Pixel) and the XNB for it is 89 bytes (smaller!).

So I’m not sure what it’s doing with the PNG files. I would have to look at the compiler to see what it’s doing. It has to be more than overhead as the one file got smaller rather than larger.

hmm, a lot of my png files are converted to 8101 kb files or 8193 kb files so my game end up being 240 mega because of this. Most of my png files are about 300 kb so it has a lot of wasted space , about 150-180 Mega is related to this issue I think

Mipmapping?

I am not using mipmaps.

Ok, I found the solution, the default value of ColorKeyEnabled is true, I guess it is storing additional data but this shouldn’t store the texture as not compressed. Since png files already have alpha value, ColorKeyEnabled is not needed at all, so disabling it and switching to false turns my texture size to almost the same size as png files.

2 Likes

I just wanted to point out that there are a lot of factors to texture sizes:

Target platform:
Each platform has a preferred lossy texture compression format(BMP is supported on all platforms.)

/processorParam:TextureFormat=Compressed

The following are common texture compression formats:

  • DDS or S3TC: Sometimes called DXTC or DXTn. Three forms of this format are supported by OpenGL.
  • ETC1: Supported on most devices. This format has no transparency support, but games can use a second texture file for the alpha component.
  • ETC2: Supported by all devices that support GLES3.
  • PVRTC: Popular with iOS games, and also supported on some Android devices.
  • ASTC: Recent format designed to supersede prior formats. More flexible than previous formats due to support for various block sizes. Using this format is a good way to optimize the size of your game.

From:
https://developer.android.com/guide/playcore/asset-delivery/texture-compression


Processor options:

/processorParam:ColorKeyEnabled=True
/processorParam:GenerateMipmaps=True
/processorParam:PremultiplyAlpha=True
/processorParam:ResizeToPowerOfTwo=True
/processorParam:MakeSquare=True

Many of these operations require conversion to Color or Vector4 types resulting in a BMP output. See https://github.com/MonoGame/MonoGame/blob/b21463b419e55b4c898030fc22bee77dabb11210/MonoGame.Framework.Content.Pipeline/Processors/TextureProcessor.cs#L51

/processorParam:TextureFormat=Color will process and store the image in a raw(no headers) 32bpp format.


PNG images cannot be stored in XNB files directly. This is an implementation restriction in the TextureProcessor

Some platforms allow reading of PNG files directly Texture2D.FromFile() or Texture2D.FromStream().


If you find yourself with a lot of small textures, it is more efficient to group them into texture atlases, or spritesheets.

Thanks Stromkos,
Still this doesn’t explain why using ColorKeyEnabled as true makes the png files ballon in size, I guess it may be using the BMP uncompressed format when using ColorKeyEnabled, since png doesn’t have a ColorKey value that can be used the MGCB , so the only solution I think that can be happening is that it is converting the png into BMP to use a ColorKey.

1 Like

Everything is a BMP in GPU memory so I think this was an optimisation thing.

Perhaps it force it to be transparent.
If your texture type is color it wont make any difference. By if you have it Compressed/DxtCompressed then it will be bigger.

I tried with DxtCompression but since I am using pixel art it became messed up, so it didn’t help at all, turning off ColorKey solved the issue. I also tested some other combinations but no other helped.

Sorry if I was unclear.

   if (ColorKeyEnabled || ResizeToPowerOfTwo || MakeSquare || PremultiplyAlpha || GenerateMipmaps)
            {
                // Convert to floating point format for modifications. Keep the original format for conversion back later on if required.
                var originalType = input.Faces[0][0].GetType();
                try
                {
                    input.ConvertBitmapType(typeof(PixelBitmapContent<Vector4>));
// ...
// Line 108:
                face[m] = bmp;

// If no change to the surface format was desired, change it back now before it early outs
                if (TextureFormat == TextureProcessorOutputFormat.NoChange)
                    input.ConvertBitmapType(originalType);

This code converts to 128 bit Vector4 type, and leaves it in that format unless /processorParam:TextureFormat=NoChange is specified, OR Until:

// Line 117:
  var texProfile = TextureProfile.ForPlatform(context.TargetPlatform);
            texProfile.ConvertTexture(context, input, TextureFormat, false);

This is the platform conversion:
If the /processorParam:TextureFormat= option is Color or Color16 return that type:

if (format == TextureProcessorOutputFormat.Color)
            {
                content.ConvertBitmapType(typeof(PixelBitmapContent<Color>));
                return;
            }

I hope this clarifies the point.

1 Like

Thanks stromkos!
Now it makes sense, I was not using any other of the flags besides ColorKeyEnabled , so by disabling it allows a non bmp uncompressed format.

1 Like

If this is concluded, do mark a post as the solution :slight_smile: