Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Image Rect with Preserve Aspect Ratio set

Discussion in 'UGUI & TextMesh Pro' started by mog-mog-mog, Sep 18, 2014.

  1. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    How to get Image Rect(rectangle) when Preserve Aspect Ratio is true?

    Image.rect always returns the default Rect irrespective of "Preserve Aspect". I want to get the actual Rect rendered for an Image object.
     
  2. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,877
    There is no way to get the rectangle of just the displayed image. The preserve aspect ratio setting on Image component is purely a display setting, it doesn't affect layout.

    However, beta 19 will have a new component called AspectRatioFitter which you can probably use for your use case.
     
    Melang likes this.
  3. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    Thank you once again, I'll wait for 19. What about without "Preserve Aspect"? What's the equivalent for getting screen rectangle on
    UI.Graphic element similar to GUIElement.GetScreenRect - http://docs.unity3d.com/ScriptReference/GUIElement.GetScreenRect.html

    I've an empty UI parent object with several UI.images, text as children. I want to take screenshot of that parent object with all children as rendered by camera. I am using Texture2D.ReadPixels to read screenpixels and need the Screen Rectangle corresponding to that UI object. How can I get the screen Rect of UI element?
     
  4. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    Ping, thanks
     
  5. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,877
    UI elements can be arbitrarily rotated, which means screen space rects don't make sense in the general case. You can get the local space rect using the rect property on the RectTransform.

    Why do you need a screen space rect? In most cases you can achieve what you want without that, and have it be more general as well so it for example also works correctly for rotated elements.
     
  6. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    Thank you again. I need to take a screenshot of specific game object with Rect Transform. What's the best way to do it?

    User upload a photo in game - can be of any size.
    1) Uploaded PhotoTexture is set to UI.Image.Sprite with Preserve Aspect set.
    2) Above image has child image -> frame whose dimensions are relative to photo size. Ideally it should be relative to photo render size after preserve ratio. As you mentioned, I can wait for 19.
    3) My game do some blah blah on player photo.
    4) Now I need to take screenshot of user photo + my frame to upload on web. This is where I need the exact gameobject screen rectangle to capture screen pixels into texture2D. Is there a better way to take the screenshot of specific gameobject and all it's children.
     
  7. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    Also, please let us know when do you guys plan to release v19? I am thinking whether to update to 18 or directly switch to 19. Any guestimate would be appreciated.
     
  8. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,183
    it's out :)
     
  9. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    using 19:

    1) Grid does not auto-refresh. Have a grid with 100 items. Disable some items out by firing events in the backend. Gird does not auto realign the items again. It'll give you missing items dirty folder view. If I refresh the grid by disabling/enabling, it'll auto-realign all items. How should I reset the grid?

    2) Original pending question - How do I get screenshot of a gameobject? Use-case:
    User upload a photo in game - can be of any size.
    • Uploaded PhotoTexture is set to UI.Image.Sprite with Preserve Aspect set.
    • Above image has child image -> frame whose dimensions are relative to photo size. Ideally it should be relative to photo render size after preserve ratio. As you mentioned, I can wait for 19.
    • My game do some blah blah on player photo.
    • Now I need to take screenshot of user photo + my frame to upload on web. This is where I need the exact gameobject screen rectangle to capture screen pixels into texture2D. Is there a better way to take the screenshot of specific gameobject and all it's children.

    Thanks
     
  10. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,877
    Please file a bug report with repro project and repro steps.

    It's basically the same for UI as for other objects, at least in Screen Space Camera mode and World Space mode. For Screen Space Overlay, world space = screen space, with (0,0) being the lower left corner.

    As for how to create screenshots of objects in general, it's not directly related to UI, and I don't have time to go into details at the moment.
     
  11. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    Thank you. Sorry for asking this simple question. But how do I get ScreenRect for the UI gameobject? Are you saying it's same and native to Unity. I believe we have this method- http://docs.unity3d.com/ScriptReference/GUIElement.GetScreenRect.html in old GUI, what's the corresponding equivalent method for UI element say Image or any element with RectTransform?
    Any small reference would be appreciated?


    Yes, if I get the screen rect from the UI.Image(rect transform), then I can take the screenshot.
     
  12. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    Thank you for all your help, I finally able to get ScreenRect correctly.
    For someone else coming at same issue, here is the solution to get ScreenRect:
    • Get four world corners as: GetWorldCorners(fourArray);
    • Convert four corners to Screen point: Camera.WorldToScreenPoint
    • Y-axis may be reverted based on Camera settings as mentioned above by runevision. If so, subtract y position from Screen.height.
     
  13. Notter

    Notter

    Joined:
    Mar 8, 2015
    Posts:
    65
    Can anyone translate the above code to an example code?
    I don't understand what do after converting the array to screen points.

    I'm using screen-space overlay, and i want to make a PNG image from a specific UI image.
    but I don't know how to find it's pixel position that i will make an image from
     
  14. Elin42

    Elin42

    Joined:
    Oct 21, 2014
    Posts:
    22
    This thread is so old now but there is still no artist friendly example how to create a screenshot from a rect transform instead of the full screen.
     
  15. pnthoai165

    pnthoai165

    Joined:
    Mar 23, 2020
    Posts:
    4
    This kinda old one, but I will post the example here for someone got stuck like me:
    upload_2021-5-27_21-58-48.png

    Thankfully to the idea of #lilboylost,
     
  16. SaumyaSaurav

    SaumyaSaurav

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