SaveAsPng missing 1/4 of image

I am having issue with SaveAsPng for long time but considering my current strategy I can’t afford this bug anymore and I can’t figure out why. Sometimes SaveAsPng miss bottom 1/4 of image after saved on HDD, thing is that this persist until application is closed and restarted, until that each images saved that way is corrupted. It is quite rare error, thus hard to track, I would say 1 in 25-50 app startups. Those data are created from render target thus .SaveAsPng is run on RT. I can empirically confirm that those RTs are always whole as otherwise it would cause obvious graphical issue. Any help is greatly appreciated.

I encountered the same problem some months back. And after some digging I concluded the problem is in the compression library used to compress PNG data. Sometimes it just compresses the data block wrong.

My solution was to read the texture directly and covert to bitmap. But: 1) apparently this will work only for specific texture format 2) I use it in tools, not in the engine, so I have access to System.Drawing.

I need this for tool (https://store.steampowered.com/app/768970/ModLab/) as well, I will look into it, thanks

@Ravendarke Did you find a solution for SaveAsPng? I’m hitting a very similar problem. It’s not 1/4, just a smaller portion, but it still prevents photoshop from correctly loading the PNG.

1 Like

What MonoGame backend is used?
As different MonoGame backends use different libs to write PNG.
MonoGame.Windows(DirectX) uses PngWriter: https://github.com/MonoGame/MonoGame/tree/develop/MonoGame.Framework/Utilities/Png
While MonoGame.DesktopGL uses StbImageWriteSharp:
https://github.com/StbSharp/StbImageWriteSharp

Though maybe issue not in the PNG writing lib, but in the Texture2D.GetData.
Also what format does texture have? SurfaceFormat.Color?

1 Like

In my case I’m using the DirectX version, grabbed from github on 2019/07/02. It’s SurfaceFormat.Color. I’m not using MSAA. I don’t think the problem is in GetData. If it was in GetData, Photoshop would load it without problems but there’d be a missing part of the image (i.e. full black).
Photoshop is just complaining of a malformed PNG. (EDIT: mspaint loads the image, but there’s 6 rows of white pixels in the 1920x1080 image)

I’ll try to reproduce the problem in a minimal program when I have some time.

I’ve bypassed saveaspng and used my/.net combined solution instead.

1 Like

ok, I found a simple example that sometimes fails on my side (Windows 10, DX)

I first tested a simple rendertarget clear but it didn’t fail in like 100 PNGs. Then I started blitting a random image, and seems to fail consistently. In example, in the first run 3 out of 20 PNGs failed.

I’ve uploaded a valid PNG and a failing PNG here: https://gofile.io/?c=cPgt9z
003 is ok but 004 has a chunk missing at the bottom (a few lines are filled with white EDIT: Well, they’re not filled with white, my windows photo viewer fills them with white, no idea what’s really there).

Thanks for making that example.
It reproduced on my env(win 7, mg 3.7). I think 10th generated image had white bottom.
However the problem went away when I changed backend from MonoGame.WindowsDX to MonoGame.DesktopGL.
So maybe problem is in png writing library(as I said before, these backends use different libraries for that task).

So the solution would be to either switch to MonoGame.DesktopGL. Or to use external library to write pngs.
Such as https://github.com/StbSharp/StbImageWriteSharp that is used in the MonoGame.DesktopGL
The code to save a texture would look like following:

// Saving texture in SurfaceFormat.Color
var data = new byte[texture.Width * texture.Height * 4];
texture.GetData(data);
using (Stream stream = File.OpenWrite(path))
{
	ImageWriter writer = new ImageWriter();
	writer.WritePng(data, width, height, ColorComponents.RedGreenBlueAlpha, stream);
}
1 Like

thanks @rds1983 !

I can’t move to DesktopGL so I’ll go with the external library solution as Ravendarke said.

In procastination mode, I decided to have a look at the issue a little bit more. I found an image that always fail : https://gofile.io/?c=M2EDzG ( it’s a raw file, just load as bytes and upload to a Texture2D which is 127 x 1080 )

Debugged a little more, decided the problem was in ZLibStream, and afterwards found this :blush: https://github.com/MonoGame/MonoGame/pull/6704