1

The reason I wish to do so is that Unity has a nice DTX5 format that reduces the file size by a lot. But to get that, I need a sprite that's size is - both for height and width - a multiple of 4. So I thought I create a new texture with the desired size, load its pixels with the original's pixels and make a sprite out of it that I save as an asset. The issue is that while saving the texture works, I get the same texture with the proper sizes, saving the sprite doesn't work. It spits out something, but that isn't even close to what I need.

Here is the code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ResizeSprites
{
    public void Resize(Sprite sprite)
    {
        int _hei, _wid;
        //getting the closest higher values that are a multiple of 4. 
        for (_hei = sprite.texture.height; _hei % 4 != 0; _hei++) ;
        for (_wid = sprite.texture.width; _wid % 4 != 0; _wid++) ;
        //creating the new texture. 
        Texture2D tex = new Texture2D(_wid, _hei,TextureFormat.RGBA32,false);
        //tex.alphaIsTransparency = true;
        //tex.EncodeToPNG();

       //giving the new texture the "improper" ratio sprite texture's pixel info
        //pixel by pixel.
        for (int wid = 0; wid < sprite.texture.width; wid++)
        {
            for (int hei = 0; hei < sprite.texture.height; hei++)
            {
                tex.SetPixel(wid, hei, sprite.texture.GetPixel(wid, hei));
            }
        }
        //saving the asset. the save works, was used for both meshes as well as textures. 
        Sprite n_spr = Sprite.Create(tex,
            new Rect(0, 0, tex.width, tex.height),
            new Vector2(0.5f, 0.5f), 100.0f);
        AssetSaver.CreateAsset(n_spr, sprite.name + "_dtx5");
    }

}

And here are my results:

original sprite

the sad outcome

The first one is the original sprite, and the second is what I was given.

Edit: Even if I don't save my creation, just instantiate it as a GameObject, the result is still the same ugly one.

agiro
  • 2,018
  • 2
  • 30
  • 62
  • 1
    Have you tried calling `Texture2D.Apply()` after your for loop? [Texture2D.Apply](https://docs.unity3d.com/ScriptReference/Texture2D.Apply.html) – Foggzie Jul 12 '17 at 22:09
  • 1
    Also, look into `GetPixels()` and `SetPixels()`. They accept an `x`, `y`, `width`, and `height` and will transfer the color data without the need for a loop. – Foggzie Jul 12 '17 at 22:12
  • Thanks for the help. Tomorrow morning I start by checking this out, I haven't tried any of those. – agiro Jul 12 '17 at 22:39
  • 1
    Have you considered using an external editor? – Draco18s no longer trusts SE Jul 13 '17 at 15:50
  • @Draco18s If I get you, you mean I should edit those images outside Unity and reimport? – agiro Jul 13 '17 at 16:02
  • 1
    @agiro Yes. If you right click on the existing file, show in explorer, it'll pop up a file browser window to the asset directly. You can just edit the texture there as you would any other file. – Draco18s no longer trusts SE Jul 13 '17 at 16:05
  • That would be viable but I got to know this compression way too late, so I have tons of textures in place. Hand-editing all of them would be a loss on the long run, not to mention this "tool"-ish I build now (alongside my sprite-to-mesh replacer) can be reused in other projects. – agiro Jul 13 '17 at 16:07
  • 1
    @Draco18s well after swapping my "hole-less" sprites with unlit meshes, I have few sprites left. Those are easily edited by hand and I plan to do so. Couple of days into coding and I forgot about the easiest solution :D thanks for pointing it out. – agiro Jul 13 '17 at 18:39
  • Hundreds of files would indeed be a pain to hand-edit. I'd pull out tools like Workspace Macro or GIMP filter scripts before writing a Unity script to do it. Glad you got things solved though. – Draco18s no longer trusts SE Jul 13 '17 at 18:48

1 Answers1

2

You really don't need all these code.Texture2D has a resize function so just pull the Texture2D from the Sprite then call the re-szie function to re-size it. That's it.

Something like this:

public void Resize(Sprite sprite)
{
    Texture2D tex = sprite.texture;

    tex.Resize(100, 100, TextureFormat.RGBA32, false);

    Sprite n_spr = Sprite.Create(tex,
        new Rect(0, 0, tex.width, tex.height),
        new Vector2(0.5f, 0.5f), 100.0f);

    AssetSaver.CreateAsset(n_spr, sprite.name + "_dtx5");
}

As for you original problem, that's because you did not call the Apply function. Each time you modify the pixels, you are supposed to call the Apply function. Finally, always use GetPixels32 not GetPixel or GetPixels. The reason is because GetPixels32 is extremely faster than the rest of the function.

public void Resize(Sprite sprite)
{
    int _hei, _wid;
    //getting the closest higher values that are a multiple of 4. 
    for (_hei = sprite.texture.height; _hei % 4 != 0; _hei++) ;
    for (_wid = sprite.texture.width; _wid % 4 != 0; _wid++) ;
    //creating the new texture. 
    Texture2D tex = new Texture2D(_wid, _hei, TextureFormat.RGBA32, false);
    //tex.alphaIsTransparency = true;
    //tex.EncodeToPNG();

    //giving the new texture the "improper" ratio sprite texture's pixel info
    //pixel by pixel.

    Color32[] color = sprite.texture.GetPixels32();

    tex.SetPixels32(color);

    tex.Apply();

    //saving the asset. the save works, was used for both meshes as well as textures. 
    Sprite n_spr = Sprite.Create(tex,
        new Rect(0, 0, tex.width, tex.height),
        new Vector2(0.5f, 0.5f), 100.0f);
    AssetSaver.CreateAsset(n_spr, sprite.name + "_dtx5");
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • 1
    Thanks for the reply. The first solution does indeed create a sprite but it's all transparent :/ The second does that too :D Now, using my old solution with the `Apply` method it works fine. All the problem is that though I get a sprite as an asset, I can't modify texture type, the sprite mode, so no import settings where I could enforce the use of DTX5. How to save it so I can modify those? – agiro Jul 13 '17 at 08:07
  • All in all you answered my question perfectly. For runtime performance I can save at least 10% on file size without any noticable quality change according to the Profiler. Thanks for your help! – agiro Jul 13 '17 at 17:23
  • 1
    No problem. There is also `TextureFormat.DXT5`. You can use that instead of `TextureFormat.RGBA32`. Having really tried it though. – Programmer Jul 13 '17 at 17:30
  • I used that _after_ creating the new texture and applied again. Hopefully that way it works too – agiro Jul 13 '17 at 18:08
  • 1
    That looks fine. – Programmer Jul 13 '17 at 18:25