Follow

How can I get pixels from unreadable textures?

Symptoms

  • I want to get pixels from a Texture
  • I do not want to set the texture as "readable"

Causes

In order to use Texture2D.GetPixels you need to select "Read/Write Enabled" on Texture Import Settings to enable access to the texture data from scripts. Sometimes you need to get pixels from a texture without having to set the texture as readable, similar to how the Unity Editor does it to get preview images from Textures.

Resolutions

You can use a RenderTexture to do that, take a look at the following code:
 
"texture" is the texture you want to read which is not marked as readable in importsettings:
 
// Create a temporary RenderTexture of the same size as the texture
RenderTexture tmp = RenderTexture.GetTemporary(
texture.width, texture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
// Blit the pixels on texture to the RenderTexture
Graphics.Blit(texture, tmp);
// Backup the currently set RenderTexture
RenderTexture previous = RenderTexture.active;
// Set the current RenderTexture to the temporary one we created
RenderTexture.active = tmp;
// Create a new readable Texture2D to copy the pixels to it
Texture2D myTexture2D = new Texture2D(texture.width, texture.height);
// Copy the pixels from the RenderTexture to the new Texture
myTexture2D.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0); myTexture2D.Apply();
// Reset the active RenderTexture
RenderTexture.active = previous;
// Release the temporary RenderTexture
RenderTexture.ReleaseTemporary(tmp);

// "myTexture2D" now has the same pixels from "texture" and it's readable.
 
You can now get/set pixels from "myTexture2D".

More Information

 
Was this article helpful?
4 out of 4 found this helpful
Have more questions? Submit a request

4 Comments

  • 0
    Avatar
    Arnaud

    Typo in your script:

    // Create a new readable Texture2D to copy the pixels to it
    Texture2D myTexture2D = new Texture2D(texture.width, texture.width);

    Above has "width" twice. Supposed to be: 

    new Texture2D(texture.width, texture.height);

    Otherwise, it helped me a lot, thanks!

     

  • 0
    Avatar
    Sergio Gomez

    Fixed! thanks.

  • 0
    Avatar
    Crash Helmet

    Very helpful, thanks.

    Something I ran into afterwards; pixel coordinates for PC & iOS are different, as described here:

    https://docs.unity3d.com/Manual/SL-PlatformDifferences.html

    https://docs.unity3d.com/ScriptReference/SystemInfo-graphicsUVStartsAtTop.html

    Edited by Crash Helmet
  • 0
    Avatar
    sama.van

    Very helpful for Standalone and Android but hours of pain of debugging from iOS.

    RenderTexture seems to be refreshed/cleared (Call it as you want) each time you call it from StandAlone and Android which let you use it for many texture in the same frame.

    On iOS, you should call it once a frame or that will just render the first one called.

    No idea why but the the per update trick is 100% working on iOS now.

    Running with Unity 2019.3.0f1

Please sign in to leave a comment.