Last active
April 25, 2024 12:45
-
-
Save Shubhra22/bab1052cd90b9f4b89b3 to your computer and use it in GitHub Desktop.
Screen Capture of particular UI elements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.IO; | |
using UnityEngine.UI; | |
public class ScreenshotNow : MonoBehaviour | |
{ | |
public RectTransform rectT; // Assign the UI element which you wanna capture | |
public Image img; | |
int width; // width of the object to capture | |
int height; // height of the object to capture | |
// Use this for initialization | |
void Start () | |
{ | |
width = System.Convert.ToInt32(rectT.rect.width); | |
height = System.Convert.ToInt32(rectT.rect.height); | |
} | |
// Update is called once per frame | |
void Update () | |
{ | |
if (Input.GetMouseButtonDown (0)) | |
{ | |
//StartCoroutine(takeScreenShot ()); // screenshot of a particular UI Element. | |
} | |
if (Input.GetKeyDown (KeyCode.A)) | |
{ | |
Application.CaptureScreenshot ("FullPageScreenShot.png"); | |
} | |
} | |
public IEnumerator takeScreenShot() | |
{ | |
yield return new WaitForEndOfFrame (); // it must be a coroutine | |
Vector2 temp = rectT.transform.position; | |
var startX = temp.x - width/2; | |
var startY = temp.y - height/2; | |
var tex = new Texture2D (width, height, TextureFormat.RGB24, false); | |
tex.ReadPixels (new Rect(startX, startY, width, height), 0, 0); | |
tex.Apply (); | |
// Encode texture into PNG | |
var bytes = tex.EncodeToPNG(); | |
Destroy(tex); | |
//File.WriteAllBytes(Application.dataPath + "ScreenShot.png", bytes); | |
string imgsrc = System.Convert.ToBase64String(bytes); | |
Texture2D scrnShot = new Texture2D(1, 1, TextureFormat.ARGB32, false); | |
scrnShot.LoadImage(System.Convert.FromBase64String(imgsrc)); | |
Sprite sprite = Sprite.Create(scrnShot, new Rect(0, 0, scrnShot.width, scrnShot.height), new Vector2(.5f, .5f)); | |
img.sprite = sprite; | |
} | |
public void Capture() | |
{ | |
StartCoroutine(takeScreenShot()); // screenshot of a particular UI Element. | |
} | |
} |
Hey, no problem, I'm glad it helped people, and nice improvement and note about rotation. We could even edit it further so it finds the appropriate corners to use automatically by comparing their world positions to see which is closest to the true bottom left (although I imagine in almost all cases it would be either the corners you used or I used).
This script takes screenshot of just the required UI object and saves to disk.
`using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class TakeScreenshotAndSave : MonoBehaviour
{
//Object To Screenshot
[SerializeField] private RectTransform _objToScreenshot;
//Assign the button to take screenshot on clicking
[SerializeField] private Button _takeScreenshotButton;
void Start()
{
_takeScreenshotButton.onClick.AddListener(OnClickTakeScreenshotAndSaveButton);
}
private void OnClickTakeScreenshotAndSaveButton()
{
StartCoroutine(TakeSnapShotAndSave());
}
//Using a Coroutine instead of normal method
public IEnumerator TakeSnapShotAndSave()
{
//Code will throw error at runtime if this is removed
yield return [new](http://www.google.com/search?q=new+msdn.microsoft.com) WaitForEndOfFrame();
//Get the corners of RectTransform rect and store it in a array vector
Vector3[] corners = [new](http://www.google.com/search?q=new+msdn.microsoft.com) Vector3[4];
_objToScreenshot.GetWorldCorners(corners);
//Remove 100 and you will get error
int width = ((int)corners[3].x - (int)corners[0].x) - 100;
int height = (int)corners[1].y - (int)corners[0].y;
var startX = corners[0].x;
var startY = corners[0].y;
//Make a temporary texture and read pixels from it
Texture2D ss = [new](http://www.google.com/search?q=new+msdn.microsoft.com) Texture2D(width, height, TextureFormat.RGB24, false);
ss.ReadPixels([new](http://www.google.com/search?q=new+msdn.microsoft.com) Rect(startX, startY, width, height), 0, 0);
ss.Apply();
Debug.Log("Start X : " + startX + " Start Y : " + startY);
Debug.Log("Screen Width : " + Screen.width + " Screen Height : " + Screen.height);
Debug.Log("Texture Width : " + width + " Texture Height : " + height);
//Save the screenshot to disk
byte[] byteArray = ss.EncodeToPNG();
string savePath = Application.persistentDataPath + "/ScreenshotSave.png";
System.IO.File.WriteAllBytes(savePath, byteArray);
Debug.Log("Screenshot Path : " + savePath);
// Destroy texture to avoid memory leaks
Destroy(ss);
}
}`
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'd like to highlight one requirement for Straafe's solution to work exactly as they have posted it. The rectTransform you are using must not be rotated. i.e. it must have a rotation of (0.0.0).
If it is rotated, you must use a different corner for your startX and startY values. Also, depending on the rotation, you may need to swap your width and height parameters. For example, my rectTransform was rotated -90 on the Z, so it would fit better on a phone in portrait mode.
This is the logic that worked for me:
startX and startY must be taken from the corner that is closest to the bottom left corner of your screen. So, in my case, it was corners[3], not corners[0].
I was skeptical if this solution would work with screen space overlay but it does, so that's great. Thanks for the solution, Straafe!