0
\$\begingroup\$

I am working with a RawImage texture which is fully stretched, filling up the entire scene. I am using some code to download images from website and then show them on the RawImage, the code is simple, I use WWW to start a download, use WWW.texture as the Image I want to show in RawImage, I do RawImage.texture = WWW.texture; and then I get the image but the Image is getting scrteched, I don't want to stretch the image but just fill instead, Just like a windows Wallpaper setting. Not to stretch or tile the image but to just fill it. I tried an approach to rotate the image via code but that still leaves some stretching in the image, if I use a portrait image( height is greater than width) I rotate the image from showing in landscape mode(which you can imagine, stretches the image a lot) to portrait mode by using some pixel conversion code, nothing special. Some images are displayed ok, because they fit the native size of the scene but for some stretching occurs. Is it possible to completely remove this stretching? I am surprised Unity doesn't have an option for changing how a texture can be displayed in RawImage. Maybe I am missing something,

\$\endgroup\$
  • \$\begingroup\$ Presumably you tried changing the size of your RawImage to match the aspect ratio of your downloaded image? What went wrong when you tried to do that? \$\endgroup\$ – DMGregory Apr 19 at 12:20
1
\$\begingroup\$

Found a topic on the Unity forum that it looks like it might be what you need. Here's a copy of the post:

Here's a handy little script I came up with, so you can tell any RawImage to fill its parent's Rect, while maintaining the aspect ratio of the src texture. It also supports percentage based padding, and images that have been rotated by 90 degree increments.

static class CanvasExtensions {
public static Vector2 SizeToParent(this RawImage image, float padding = 0) {
    var parent = image.transform.parent.GetComponentInParent<RectTransform>();
    var imageTransform = image.GetComponent<RectTransform>();
    if (!parent) { return imageTransform.sizeDelta; } //if we don't have a parent, just return our current width;
    padding = 1 - padding;
    float w = 0, h = 0;
    float ratio = image.texture.width / (float)image.texture.height;
    var bounds = new Rect(0, 0, parent.rect.width, parent.rect.height);
    if (Mathf.RoundToInt(imageTransform.eulerAngles.z) % 180 == 90) {
          //Invert the bounds if the image is rotated
          bounds.size = new Vector2(bounds.height, bounds.width);
    }
    //Size by height first
    h = bounds.height * padding;
    w = h * ratio;
    if (w > bounds.width * padding) { //If it doesn't fit, fallback to width;
        w = bounds.width * padding;
        h = w / ratio;
    }
    imageTransform.sizeDelta = new Vector2(w, h);
    return imageTransform.sizeDelta;
}
}
\$\endgroup\$
  • \$\begingroup\$ and to use it RawImage.SizeToParent(); but there is one more answer, which adjusts the image to Fit the screen, which is just perfect for all cases. \$\endgroup\$ – AKC Apr 20 at 8:54
0
\$\begingroup\$

Answer by Esildor works nice, but it doesn't make it fit inside the Parent scene. It does fill it nicely, but chances are that you may find your RawImage.texture a bit cropped from all sided, so this adjusted method will let you keep the Image in a nice aspect ratio will fitting it inside the RawImage.

public static Vector2 SizeToParent(this RawImage image, float padding = 0) {
        float w = 0, h = 0;
        var parent = image.GetComponentInParent<RectTransform>();
        var imageTransform = image.GetComponent<RectTransform>();

        // check if there is something to do
        if (image.texture != null) {
            if (!parent) { return imageTransform.sizeDelta; } //if we don't have a parent, just return our current width;
            padding = 1 - padding;
            float ratio = image.texture.width / (float)image.texture.height;
            var bounds = new Rect(0, 0, parent.rect.width, parent.rect.height);
            if (Mathf.RoundToInt(imageTransform.eulerAngles.z) % 180 == 90) {
                //Invert the bounds if the image is rotated
                bounds.size = new Vector2(bounds.height, bounds.width);
            }
            //Size by height first
            h = bounds.height * padding;
            w = h * ratio;
            if (w > bounds.width * padding) { //If it doesn't fit, fallback to width;
                w = bounds.width * padding;
                h = w / ratio;
            }
        }
        imageTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, w);
        imageTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, h);
        return imageTransform.sizeDelta;
    }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.