EncodeToPNG() causes loss of image detail: How to avoid this?

Hello

I am saving a Texture to a SQLite3 database but in order to save the image I have to convert it to a Byte array using .EncodeToPNG(). This causes the image to loose detail/quality (see the below image).


Knowtice how the right image is blurred. The right image is just a texture that has had .EncodeToPNG() called, then reloaded into a new Texture object.

Is there a way to avoid this from occuring and maintain the image quality? Maybe I can convert the texture to a byte[] using some other method (that doesn’t result in loss of detail)?

EDIT: After more debugging I did notice that the format of the 2nd texture is different. The first is RGB24 the second texture is ARGB32 maybe this causes the problem? How do I fix this?

Heres the code that you can test for yourself that will replicate the issue:

virtual protected void downloadTextureCallback(WWW www) {
	
	if (!www.isDone)
		return;
		
	Texture2D t = www.texture;
	byte[] b    = t.EncodeToPNG();
	Texture2D t2  = new Texture2D(800, 800); 
	t2.LoadImage(b);
	renderer.material.mainTexture = t2;
}

2 Answers

2

PNG should be a lossless encoding. Are you sure that the blurring isn’t due to the FilterMode of the second texture?

@tanoshimi I inspected the two textures t and t2 they both have the same FilterMode and the same dimensions. The loss in detail always occurs after I call EncodeToPNG() has anyone else experienced this?

@tanoshimi after more debugging I did notice that the format of the 2nd texture is different. The first is RGB24 the second texture is ARGB32 maybe this causes the problem? How do I fix this?

The problem was that the format of the Texture2d was different.

This is the solution:

virtual protected void downloadTextureCallback(WWW www) {
 
    if (!www.isDone)
        return;
 
    Texture2D t = www.texture;
    byte[] b = t.EncodeToPNG();
    Texture2D t2 = new Texture2D(800, 800, t.format, false); // MUST ensure that t2 has the same format as t
    t2.LoadImage(b);
    renderer.material.mainTexture = t2;
}