Texture2D.FromStream in 3.7

Hello,

so, Texture2D.FromStream is now fixed and works like XNA works… yay… cant say that is an improvement. The old monogame way was much easier to use. How can I now load my textures without getting that ugly black look?

Greeting
Kai

2 Likes

I noticed that too. Super frustrating issue, because textures loaded through Content pipeline are working well (for me at least), but every png loaded with FromStream() has that horribly looking, pixelated effect.

You need to change BlendState to “NonPremultiplied” in SpriteBatch.

spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);

I tested one png image, with transparent background, random colors, and soft (blur) edges and no pixel effect or hard edges. Also “Additive” is working fine. I think the default value “AlphaBlend” generate this pixelated effect.

Those two BlendState types completely changed how all the other sprites look for me. Default state was working fine before 3.7. How can you call this a solution when it completely changes original graphics? For example “Additive” makes my tree sprites transparent.

Which platform(s) does this occur in (DesktopGL, Windows, UWP, mobile, etc.)?

1 Like

If you want to work well with both loads (FromStream and regular Content Pipeline), then with MG Pipeline Tool in the image properties, “PremultiplyAlpha” should be false. In this case, I work well with BlendState.NonPremultiplied. I tested it under OpenGL. If “rebuild” does not change the result, you can try multiple times or manually re-import the images and delete the old ones. I think there’s a tiny bug in the MG tool. If you change the one value to true or false (just check or uncheck a tiny box), and you do not clicking after on anything else inside Properties, and you just go to rebuild, it will not update the image.

For me the problem occurs in Windows.

What he meant to say was, DirectX or OpenGL projects? and also which platform target. i.e. Windows Desktop [DX or OGL], Windows UWP App, etc.

Actually Texture2D.FromStream behaved differently on different backends in MG 3.6. As far as I remember it premultiplied alpha with Monogame.Windows and didnt premultiply it with Monogame.DesktopGL. Unsure about other backends.
Now Texture2D.FromStream should have same behaviour on all backends starting from MG 3.7: the alpha is not premultiplied.
Those who are used to the old behavior have two solutions:

  1. Use BlendState.NonPremultiplied(as it was said above).
  2. Premultiply alpha manually after the loading. I.e. with the following code:

		private static byte ApplyAlpha(byte color, byte alpha)
		{
			var fc = color / 255.0f;
			var fa = alpha / 255.0f;
			var fr = (int)(255.0f * fc * fa);
			if (fr < 0)
			{
				fr = 0;
			}
			if (fr > 255)
			{
				fr = 255;
			}
			return (byte)fr;
		}

		public static void PremultiplyAlpha(Texture2D texture)
		{
			Color[] data = new Color[texture.Width * texture.Height];
			texture.GetData(data);

			for (int i = 0; i < data.Length; ++i)
			{
				byte a = data[i].A;

				data[i].R = ApplyAlpha(data[i].R, a);
				data[i].G = ApplyAlpha(data[i].G, a);
				data[i].B = ApplyAlpha(data[i].B, a);
			}

			texture.SetData(data);
		}

This way you can keep using default BlendState.AlphaBlend.

I’d suggest a new overload on FromStream where a parameter specifies premultiplied/nonPremultiplied when loading. GetData can be very costing sometimes, and it’s a common operation.

1 Like

Well, I made a PR #6206
If it’ll be accepted, it would be possible to load images directly into the memory, do various preprocessing and create textures from the result.

1 Like

DirectX and Windows Desktop

What should I do if BlendState.NonPremultiplied changes how my graphics looks?

Try 2nd solution. Copy/Paste above code snippet and call PremultiplyAlpha with the texture you got from Texture2D.FromStream.

1 Like

It worked. Now my sprites are rendered as expected. Thanks!

Here’s a method that’s loading a file into a premultiplied RenderTarget.

I wrote that some years ago so I don’t really know if it’s the best possible solution.

1 Like

thank you guys :smiley: the textures are fine now.