3
votes

Texture loaded from disk comparison

In the image above, the first image is loaded via C# script. The second is assigned via the inspector in Unity editor. Note the dark gray border around the first image. How can I load the image via C# and have it not have the border?

The source image is a white-on-transparent PNG 512x512 pixels. It's being displayed in an UnityEngine.UI.Image sized at 30x30 with a red color assigned. The source image is identical (same location on disk) for both examples above.

The code I am using for the first image is as follows;

var texture = new Texture2D(512, 512);
texture.LoadImage(File.ReadAllBytes(Path.Combine(TexturePath, name)));
image.sprite = Sprite.Create(texture, new Rect(0,0, texture.width, texture.height), new Vector2(.5f,.5f), 100);

where image is the appropriate UnityEngine.UI.Image.

Note

The advantage of using the code above is that the images do not need to be embedded in the game that unity ends up building. It means these images can be distributed separately from the game. Using Resources.Load does not cater for this, and I suspect, is the same as assigning the image via the inspector, meaning that unity has already done something to the texture prior to assignment (likely something by the UnityEditor.TextureImporter)

Update

jagged edges

I investigated the Texture2D constructor some more and determined that the following code results in the image above, where the edges of the sprite no longer have the grey border, but now appear jagged. (Setting the last parameter to true retains the grey border).

var texture = new Texture2D(512, 512, TextureFormat.Alpha8, false);

Some googling has me thinking that the issue is mipmap related, and that the Unity Editor may be resolving this on import due to whatever occurs with UnityEditor.TextureImporter.borderMipMap as seen here. However, the UnityEditor namespace is not available when building the project.

2
I think this is probably more about the png encoding options than c#Ewan
@Ewan considering the examples are based off the same source file, are you suggesting that the Unity Editor changes the png encoding?Stafford Williams
possibly it converts the file to a resource, possibly it uses differnt options when reading the file.Ewan
I agree, that's pretty much what this question is askingStafford Williams
yes im not being that helpful i guess. I jad a similar prob ages ago which i solved by saving the file with different options ticked rather than working out the correct way to load it. I was unaware at the time that there were 'options' and types of pngEwan

2 Answers

1
votes

The issue is that the PNG format uses a non-premultiplied Alpha and Unity uses straight alpha blending designed to work best with pre-multiplied alpha colors.

Better in-depth descriptions of Pre vs non-Pre can be found from:

A Unity-specific discussion can be found Here (however, note this problem has nothing to do with mip-mapping, but can be exacerbated by filtering and resizing techniques)

You can also look to Unity's documentation on alpha importing to see a visual example of a common solution to this problem if you have access to pipeline-side creation of these PNGs (I have typically solved this by applying a post-process to modify PNGs after/during their creation).

Using a cutout shader is also a solution though it can result in jaggy/visual artifacts.

You would think rendering a sprite using the features of Unity's primary supported runtime load image file format would be a simple affair but, alas, it is quite a bit more complicated than that. I don't know the inner workings of UnityEditor.TextureImporter.borderMipMap but I suspect its inception is built around a similar problem (weight between the edge pixel alpha and any neighbors used in the filtering)

0
votes

Use Resources.Load, thus you can configure the texture settings in the editor.