How Can I Generate a Thumbnail from the Screen?

Hi folks,

I’m working on generating a thumbnail from a screen capture (to give users a visual image for file browsing). So far, my code works to generate a full-size screenshot:

    IEnumerator TakeEpicScreenshot()
    {
        yield return new WaitForEndOfFrame();
		
        // create a texture to pass to encoding
        Texture2D texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
 
        // put buffer into texture
        texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);

	yield return 0;

	texture.Apply();

        yield return 0;
 
        byte[] bytes = texture.EncodeToPNG();
 
        // save the image
	string imagePath = "amazingPath.png";
	File.WriteAllBytes(imagePath, bytes);
  }

This part works perfectly. The problem is that this image is far larger than I want to store. Is there a way for me to shrink the image down so that it fits in a smaller image (think: StretchBlt from Windows)?

I’m also somewhat concerned with the performance hit: it would be ideal to generate the screenshot at the proper size in the first place, but at this point I’ll take what I can get.

Any pointers are welcome.

Thanks,

Kevin

Edit: I should also mention that I’m developing for iOS, in case that is pertinent.

So I chatted with Mike from Prime31 – nice guy. He informed me that Unity has a built-in way to do this, using the RenderTexture class. What I ended up doing, essentially, is the following:

  1. Create a new camera, and set if up in the scene with the thumbnail view I want
  2. Create a new Render Texture, and add it as the camera’s Target Texture.
  3. Render my screenshot using the ReadPixels approach above, but using my render texture as the source instead of the screen (by setting RenderTexture.active to my render texture before calling ReadPixels()).

That’s basically it. See here for more info on RenderTexture (including detailed steps for some of the above): Unity - Manual: Render Texture

Thanks again to Fattie for pointing me in the right direction…+1.

Thank you for this code. It really helped me. Here is my updated version. First create a Render Texture and attach it to your camera under Target Texture then drag your camera onto the script. Press ‘e’ to generate a screenshot.

public Camera cam;

void Update()
{
    if (Input.GetKeyDown("e"))
    {
        Debug.Log("Saving Screen Shot");
        StartCoroutine(CreateLayerThumbnail());  
    }
        
}

IEnumerator CreateLayerThumbnail()
{
    yield return new WaitForEndOfFrame();

    // create a texture to pass to encoding
    Texture2D texture = new Texture2D(cam.targetTexture.width, cam.targetTexture.height, TextureFormat.RGB24, false);

    // Initialize and render
    cam.Render();
    RenderTexture.active = cam.targetTexture;

    // put buffer into texture
    texture.ReadPixels(new Rect(0, 0, cam.targetTexture.width, cam.targetTexture.height), 0, 0);

    yield return 0;

    texture.Apply();

    yield return 0;

    byte[] bytes = texture.EncodeToPNG();

    // save the image
    string imagePath = "amazingPath.png";
    File.WriteAllBytes(FileManager.DATA_DIRECTORY + Path.DirectorySeparatorChar + imagePath, bytes);

    //Tell unity to delete the texture, by default it seems to keep hold of it and memory crashes will occur after too many screenshots.
    DestroyObject(texture);
}