Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Taking screenshot of partial area

Discussion in 'Scripting' started by baylor, Jul 13, 2010.

  1. baylor

    baylor

    Joined:
    Oct 29, 2009
    Posts:
    25
    My game lets you dress up your character. i'd like to save off that image (but not the rest of the 800x600 screen) to a file. According to the help, i can use Application.CaptureScreen() to capture the full screen but how does one capture just one part of it?

    (Sorry if this is a common question. i searched first for "screenshot" but that produced tons of hits that weren't relevant (it's a popular key word))
     
    T0RED and ina like this.
  2. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    324
    Code (csharp):
    1.  var width = 400;
    2.  var height = 300;
    3.  var startX = 200;
    4.  var startY = 100;
    5.  var tex = new Texture2D (width, height, TextureFormat.RGB24, false);
    6.  
    7.  tex.ReadPixels (Rect(startX, startY, width, height), 0, 0);
    8.  tex.Apply ();
    9.  
    10.  // Encode texture into PNG
    11.  var bytes = tex.EncodeToPNG();
    12.  Destroy(tex);
    13.  
    14.  File.WriteAllBytes(Application.dataPath + "/../SavedScreen.png", bytes);
    15.  
     
    spider853, T0RED, ina and 3 others like this.
  3. JtheSpaceC

    JtheSpaceC

    Joined:
    Oct 5, 2014
    Posts:
    14
    Wow. 7 years later and no accepted answer.

    Well CaptainKiyaku's answer (with a little modification, below) still works.

    Code (CSharp):
    1. var width = 400;
    2.         var height = 300;
    3.         var startX = 200;
    4.         var startY = 100;
    5.         var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
    6.  
    7.         Rect rex = new Rect(startX, startY, width, height);
    8.  
    9.         tex.ReadPixels(rex, 0, 0);
    10.         tex.Apply();
    11.  
    12.         // Encode texture into PNG
    13.         var bytes = tex.EncodeToPNG();
    14.         Destroy(tex);
    15.  
    16.         System.IO.File.WriteAllBytes(Application.dataPath + "SavedScreen.png", bytes);
     
  4. FenixShadow

    FenixShadow

    Joined:
    Dec 10, 2014
    Posts:
    3
    To make sure the screen is captured correctly, you should wait to perform ReadPixels until after the frame is fully rendered. You can accomplish this by calling your script (or at least ReadPixels and everything after) in the OnPostRender message or by using WaitForEndOfFrame.
     
    kk88 likes this.
  5. Metsker

    Metsker

    Joined:
    Oct 21, 2020
    Posts:
    1
    Here is my solution how you can take a shot of an 2D UI object. It works with any resolution and aspect ratio (Screen Space - Camera). But I belive there is a better way.

    Code (CSharp):
    1. [SerializeField] private RectTransform targetRect;
    2. private Camera _camera;
    3.  
    4. private void Start()
    5. {
    6.     _camera = Camera.main;
    7. }
    8.  
    9. public void TakeScreenshot(string fileName)
    10. {
    11.     StartCoroutine(CutSpriteFromScreen(fileName));
    12. }
    13.  
    14. private IEnumerator CutSpriteFromScreen(string fileName)
    15. {
    16.     yield return new WaitForEndOfFrame();
    17.  
    18.     var corners = new Vector3[4];
    19.     targetRect.GetWorldCorners(corners);
    20.     var bl = RectTransformUtility.WorldToScreenPoint(_camera, corners[0]);
    21.     var tl = RectTransformUtility.WorldToScreenPoint(_camera, corners[1]);
    22.     var tr = RectTransformUtility.WorldToScreenPoint(_camera, corners[2]);
    23.  
    24.     var height = tl.y - bl.y;
    25.     var width = tr.x - bl.x;
    26.  
    27.     Texture2D tex = new Texture2D((int)width, (int)height, TextureFormat.RGB24, false);
    28.     Rect rex = new Rect(bl.x,bl.y,width,height);
    29.     tex.ReadPixels(rex, 0, 0);
    30.     tex.Apply();
    31.     var bytes = tex.EncodeToPNG();
    32.     Destroy(tex);
    33.  
    34.     File.WriteAllBytes(Application.dataPath + fileName, bytes);
    35. }
     
  6. fraeri

    fraeri

    Joined:
    Nov 8, 2018
    Posts:
    64
    Hi,
    this is giving me the following error from line 27:

    Code (CSharp):
    1. Texture has out of range width / height
    2. UnityEngine.Texture2D:.ctor (int,int,UnityEngine.TextureFormat,bool)
    I checked the values and I got 59932.74 for the height and 89332.05 for the width. Which sounds ridiculously high ....

    Any idea why that happened?
     
  7. elfasito

    elfasito

    Joined:
    Jul 4, 2017
    Posts:
    51
    thanks for the script.
    I created my own modification:

    Code (CSharp):
    1.  
    2.     public RectTransform AreaToCapture;
    3.     public string FileName; //filename needs the direction, name & extension, ex: \varios\myphoto.png
    4.  
    5.     public enum RectMode { RectStretched, RectCentered }
    6.     public RectMode RectTransformMode;
    7.  
    8.  
    9.     public void TakeScreenShoot()
    10.     {
    11.         StartCoroutine(coroutineTakeScreenShoot());
    12.     }
    13.  
    14.     private IEnumerator coroutineTakeScreenShoot()
    15.     {
    16.         yield return new WaitForEndOfFrame();
    17.  
    18.         var width = 0;
    19.         var height = 0;
    20.         var startX = 0f;
    21.         var startY = 0f;
    22.  
    23.         if (RectTransformMode == RectMode.RectStretched)
    24.         {
    25.             //these var are correct only for a panel setted to stretch
    26.             width = (int)AreaToCapture.rect.width;
    27.             height = (int)AreaToCapture.rect.height;
    28.             startX = AreaToCapture.offsetMin.x;
    29.             startY = AreaToCapture.offsetMin.y;
    30.  
    31.             var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
    32.             Rect rex = new Rect(startX, startY, width, height);
    33.  
    34.             tex.ReadPixels(rex, 0, 0);
    35.             tex.Apply();
    36.             // Encode texture into PNG
    37.             var bytes = tex.EncodeToPNG();
    38.             Destroy(tex);
    39.             File.WriteAllBytes(Application.dataPath + FileName, bytes);
    40.         }
    41.  
    42.         if (RectTransformMode == RectMode.RectCentered)
    43.         {
    44.             /*Debug.Log("tamaño y: " + AreaToCapture.rect.height);
    45.             Debug.Log("tamaño x: " + AreaToCapture.rect.width);
    46.             Debug.Log("localposition x: " + AreaToCapture.transform.localPosition.x);
    47.             Debug.Log("localposition y: " + AreaToCapture.transform.localPosition.y);
    48.             Debug.Log("offsetMin y: " + AreaToCapture.offsetMin.y);
    49.             Debug.Log("offsetMin y: " + -AreaToCapture.offsetMin.y);*/
    50.  
    51.             Vector2 min = AreaToCapture.anchorMin;
    52.             min.x *= Screen.width;
    53.             min.y *= Screen.height;
    54.  
    55.             min += AreaToCapture.offsetMin;
    56.  
    57.             Vector2 max = AreaToCapture.anchorMax;
    58.             max.x *= Screen.width;
    59.             max.y *= Screen.height;
    60.  
    61.             max += AreaToCapture.offsetMax;
    62.  
    63.             //Debug.Log(min + " " + max);
    64.  
    65.             //these var are correct only for a panel setted to stretch
    66.             width = (int)AreaToCapture.rect.width;
    67.             height = (int)AreaToCapture.rect.height;
    68.             startX = min.x;
    69.             startY = min.y;
    70.  
    71.             var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
    72.             Rect rex = new Rect(startX, startY, width, height);
    73.  
    74.             tex.ReadPixels(rex, 0, 0);
    75.             tex.Apply();
    76.             // Encode texture into PNG
    77.             var bytes = tex.EncodeToPNG();
    78.             Destroy(tex);
    79.             File.WriteAllBytes(Application.dataPath + FileName, bytes);
    80.         }
    81.  
    82.         Debug.Log("Capture saved in: " + FileName);
    83.     }
    84.  
    its necessary to select the rectTransform mode (stretched/center)
     
    Last edited: Aug 21, 2022
  8. SaumyaSaurav

    SaumyaSaurav

    Joined:
    Oct 7, 2017
    Posts:
    13
    How to use - Make a empty game object, drag and drop this script and assign the required items in inspector panel.
    and you are ready to take a screenshot.

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. public class TakeScreenshotAndSave : MonoBehaviour
    5. {
    6.     //Object To Screenshot
    7.     [SerializeField] private RectTransform _objToScreenshot;
    8.     //Assign the button to take screenshot on clicking
    9.     [SerializeField] private Button _takeScreenshotButton;
    10.     void Start()
    11.     {
    12.         _takeScreenshotButton.onClick.AddListener(OnClickTakeScreenshotAndSaveButton);
    13.     }
    14.     private void OnClickTakeScreenshotAndSaveButton()
    15.     {
    16.         StartCoroutine(TakeSnapShotAndSave());
    17.     }
    18.     //Using a Coroutine instead of normal method
    19.     public IEnumerator TakeSnapShotAndSave()
    20.     {
    21.         //Code will throw error at runtime if this is removed
    22.         yield return new WaitForEndOfFrame();
    23.         //Get the corners of RectTransform rect and store it in a array vector
    24.         Vector3[] corners = new Vector3[4];
    25.         _objToScreenshot.GetWorldCorners(corners);
    26.         //Remove 100 and you will get error
    27.         int width = ((int)corners[3].x - (int)corners[0].x) - 100;
    28.         int height = (int)corners[1].y - (int)corners[0].y;
    29.         var startX = corners[0].x;
    30.         var startY = corners[0].y;
    31.         //Make a temporary texture and read pixels from it
    32.         Texture2D ss = new Texture2D(width, height, TextureFormat.RGB24, false);
    33.         ss.ReadPixels(new Rect(startX, startY, width, height), 0, 0);
    34.         ss.Apply();
    35.         Debug.Log("Start X : " + startX + " Start Y : " + startY);
    36.         Debug.Log("Screen Width : " + Screen.width + " Screen Height : " + Screen.height);
    37.         Debug.Log("Texture Width : " + width + " Texture Height : " + height);
    38.         //Save the screenshot to disk
    39.         byte[] byteArray = ss.EncodeToPNG();
    40.         string savePath = Application.persistentDataPath + "/ScreenshotSave.png";
    41.         System.IO.File.WriteAllBytes(savePath, byteArray);
    42.         Debug.Log("Screenshot Path : " + savePath);
    43.         // Destroy texture to avoid memory leaks
    44.         Destroy(ss);
    45.     }
    46. }
     
    DarkDeivel, Zir2904, svenvanh and 2 others like this.
  9. Zir2904

    Zir2904

    Joined:
    Sep 13, 2021
    Posts:
    7

    Thank you very much for this, helped me a lot. Just to mention, i removed the "-100" part because it was cutting a part of my picture. Other than that thank you <3.