Unity 编辑器工具:扩展Sprite的图片大小

1、功能说明

因为一些特殊的原因,现在需要把项目中所有的图片的宽和高扩展 几个像素,但实际做起来会出现一些别的问题,比如说贴图 是 512 * 512 的尺寸,扩展几个像素,会导致贴图占较大内存,不利于压缩, 所以目前只做了关于Sprite类型的图片的扩展。因为Sprite中有Single和Multiple模式,需要先把所有的Single类型转化成Multiple,不然就会出现图片会偏移的问题。

2、在Unity中获取图片原始尺寸

第一种方式就是通过反射

public static Vector2Int GetTextureOriginalSize(TextureImporter ti)
{
    if (ti == null)
    {
        return Vector2Int.zero;
    }
    object[] args = new object[2] { 0, 0 };
    MethodInfo mi = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
    mi.Invoke(ti, args);
    return new Vector2Int((int)args[0], (int)args[1]);
}

第二种方式,就需要用到 System.Drawing.dll 这个动态库,文章后面会提供该库,Unity自带的库基本都用不了,而且在Mac上,也没找到能用的库,所以这个功能是在Windows系统上制作的,System.Drawing中Image,可以获取到相应的图片的尺寸 (这个功能就是用这种方式实现)

3、把全部Sprite的 Single改为Multiple

TextureImporter textureImporter = AssetImporter.GetAtPath(imgPaths[i].path) as TextureImporter;
//如果不是Sprite类型,则直接跳过
if (textureImporter.textureType != TextureImporterType.Sprite) continue;
//通过System.Drawing.dll 的Image组件,获取图片数据
using (Image csImage = Image.FromFile(imgPaths[i].path))
{
    if (textureImporter.spriteImportMode == SpriteImportMode.Single)
    {
        SpriteMetaData metaData = new SpriteMetaData();
        metaData.name = "_0";
        metaData.rect = new Rect(0, 0, csImage.Width, csImage.Height);
        textureImporter.spriteImportMode = SpriteImportMode.Multiple;
        textureImporter.spritesheet = new SpriteMetaData[] { metaData };
        textureImporter.SaveAndReimport();
    }
}

4、在一个新的路径,创建扩展像素后的图片

使用Bitmap创建的图片,如果路径上已经有同名图片,则无法替换,报错,所以先把图片放到新的文件夹下,后面手动替换下即可

using (Image csImage = Image.FromFile(imgPaths[i].path))
{
    Vector2Int size = new Vector2Int(csImage.Width, csImage.Height);
    using (var bmp = new Bitmap(size.x + 8, size.y + 8))
    {
        bmp.SetResolution(csImage.HorizontalResolution, csImage.VerticalResolution);

        using (var g = System.Drawing.Graphics.FromImage(bmp))
        {
            g.Clear(System.Drawing.Color.Empty);
            g.DrawImageUnscaled(csImage, 0, 8);
        }
        //在新的AssetsTemp中创建扩展后的图片
        string path1 = Application.dataPath.Replace('/', '\\').Replace("Assets", imgPaths[i].path).Replace("Assets", "AssetsTemp");
        DirectoryInfo info = new DirectoryInfo(path1.Replace("\\" + imgPaths[i].name, ""));
        if (!info.Exists) info.Create();
        bmp.Save(path1, imgPaths[i].format);
    }
}

5、完整代码

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

public class ImageSizeEditor : Editor
{
    public struct ImagePath
    {
        public string path;
        public ImageFormat format;
        public string name;
    }

    [MenuItem("Window/ChangeImageSize")]
    public static void ChangeImageSize()
    {
        List<ImagePath> imgPaths = LoadAllImage();
        int offsetX = 8;
        int offsetY = 8;
        for (int i = 0; i < imgPaths.Count; i++)
        {
            TextureImporter textureImporter = AssetImporter.GetAtPath(imgPaths[i].path) as TextureImporter;
            if (textureImporter.textureType != TextureImporterType.Sprite) continue;
            using (Image csImage = Image.FromFile(imgPaths[i].path))
            {
                if (textureImporter.spriteImportMode == SpriteImportMode.Single)
                {
                    SpriteMetaData metaData = new SpriteMetaData();
                    metaData.name = "_0";
                    metaData.rect = new Rect(0, 0, csImage.Width, csImage.Height);
                    textureImporter.spriteImportMode = SpriteImportMode.Multiple;
                    textureImporter.spritesheet = new SpriteMetaData[] { metaData };
                    textureImporter.SaveAndReimport();
                }

                Vector2Int size = new Vector2Int(csImage.Width, csImage.Height);
                using (var bmp = new Bitmap(size.x + offsetX, size.y + offsetY))
                {
                    bmp.SetResolution(csImage.HorizontalResolution, csImage.VerticalResolution);

                    using (var g = System.Drawing.Graphics.FromImage(bmp))
                    {
                        g.Clear(System.Drawing.Color.Empty);
                        g.DrawImageUnscaled(csImage, 0, offsetY);
                    }
                    string path1 = Application.dataPath.Replace('/', '\\').Replace("Assets", imgPaths[i].path).Replace("Assets", "AssetsTemp");
                    DirectoryInfo info = new DirectoryInfo(path1.Replace("\\" + imgPaths[i].name, ""));
                    if (!info.Exists) info.Create();
                    bmp.Save(path1, imgPaths[i].format);
                }
            }
        }
        Debug.Log("Finish");
    }

    static List<ImagePath> LoadAllImage()
    {
        List<ImagePath> filePaths = new List<ImagePath>();
        string[] imgtypes = { "*.BMP", "*.JPG", "*.GIF", "*.PNG" };
        ImageFormat[] imgFormats = { ImageFormat.Bmp, ImageFormat.Jpeg, ImageFormat.Gif, ImageFormat.Png };
        for (int i = 0; i < imgtypes.Length; i++)
        {
            string[] dirs = Directory.GetFiles("Assets", imgtypes[i], SearchOption.AllDirectories);
            for (int j = 0; j < dirs.Length; j++)
            {
                string[] pArray = dirs[j].Split('\\');
                filePaths.Add(new ImagePath { path = dirs[j], format = imgFormats[i], name = pArray[pArray.Length - 1] });
            }
        }
        return filePaths;
    }
}

6、下载System.Drawing.dll

点击此处

我的Unity版本:2018.4.12
Window系统

你可能感兴趣的:(Unity,C#)