Scaling / Resizing an Image (Texture2D)

I am trying to scale an image to fit within GUILayer box. The script comes up with an error on the line with NewImageWidth_1 = image_1.width * ImageRatio;

“BCE0051: Operator ‘*’ cannot be used with a left hand side of type ‘int’ and a right hand side of type ‘Object’.”

private var BoxWidth = 350;
private var BoxHeight = 400;
var image_1 : Texture2D;  
private var maxImageWidth = BoxWidth-50;  
private var ImageRatio;  
private var NewImageWidth_1 = image_1.width;  
private var NewImageHeight_1 = image_1.height;  
if(image_1.width > maxImageWidth){  
 ImageRatio = maxImageWidth / image_1.width;  
 NewImageWidth_1 = image_1.width * ImageRatio;  
 NewImageHeight_1 = image_1.height * ImageRatio;  
}  
GUILayout.Box(image_1,[GUILayout.Width(NewImageWidth_1),GUILayout.Height(NewImageHeight_1)]);

This script does the scaling on the GPU, it’s lighting fast and done by me. Here is the code: Unity3d Texture Image Scaler - Pastebin.com - Because this one scales with RTT, it’s only available to Unity 5 users and will possibly work in Unity 4 Pro.

Instead of trying to implement this yourself, you might be interested in Eric’s (Eric5h5) solution for this, which is freely available on the Wiki:

http://wiki.unity3d.com/index.php/TextureScale (archive.org)

It allows you to select which filtering type you’d like when scaling, and it’s also multithreaded, so there’s a good change it’ll be faster, too.

If anyone is looking for a way to resize the ‘canvas’ of a Texture2D, here’s some I ended up with after some trial and error:

public static Color32[] ResizeCanvas(Texture2D texture, int width, int height)
{
    var newPixels = ResizeCanvas(texture.GetPixels32(), texture.width, texture.height, width, height);
    texture.Resize(width, height);
    texture.SetPixels32(newPixels);
    texture.Apply();
    return newPixels;
}

private static Color32[] ResizeCanvas(IList<Color32> pixels, int oldWidth, int oldHeight, int width, int height)
{
    var newPixels = new Color32[(width * height)];
    var wBorder = (width - oldWidth) / 2;
    var hBorder = (height - oldHeight) / 2;

    for (int r = 0; r < height; r++)
    {
        var oldR = r - hBorder;
        if (oldR < 0) { continue; }
        if (oldR >= oldHeight) { break; }

        for (int c = 0; c < width; c++)
        {
            var oldC = c - wBorder;
            if (oldC < 0) { continue; }
            if (oldC >= oldWidth) { break; }

            var oldI = oldR*oldWidth + oldC;
            var i = r*width + c;
            newPixels *= pixels[oldI];*

}
}

return newPixels;
}

Here’s a simple texture scaling solution I saw on another answer. I use it and it works well.

Here is a quick solution using Graphics api.

            texture.LoadImage("example.png");

            int targetWidth = 400;
            int targetHeight = 300;
            
            RenderTexture rt = RenderTexture.GetTemporary(targetWidth, targetHeight, 0, RenderTextureFormat.ARGB32);
            Graphics.Blit(texture, rt);
            texture.Resize(targetWidth, targetHeight);
            RenderTexture active = RenderTexture.active;
            RenderTexture.active = rt;
            texture.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0);
            texture.Apply(false, true);
            RenderTexture.active = active;
            RenderTexture.ReleaseTemporary(rt);

You can see that at the final texture.Apply i use false, true, it’s because I don’t need mipmaps and don’t need texture r/w

Scaling image will stretch the existing contents to the new dimensions. Smooth scale image generally provides better quality results than Scaling, by blending neighbouring colors. And my project goes well with imaging method: public static int ApplyResize(REImage img, float ratio);

Because there is no ‘best’ or ‘perfect’ way, there are a lot of options that you may like to consider. Google to find out an image library suit your project.