当前位置:   article > 正文

Unity图片处理 批量改画布大小_unity 设置统一画布大小

unity 设置统一画布大小

不知道有没有人遇到过这种情况。
资源大小并非2的整数幂,导致Unity无法压缩。
而且资源量很大,无法放在PS里去一张一张的去修改画布。

问题分析

在这里插入图片描述
最开始,我是放在PS里修改画布来让图片修改为2的整数幂的尺寸。
但是看着文件夹里几百帧的贴图。
我顿时陷入了沉思。
显然不能手动来做…

Unity的Texture2D似乎可以用来处理这个问题。
需要注意的一个地方

Color[] texturePixels = Texture2D.GetPixels();
  • 1

在这里插入图片描述
我原本以为会是一个二维数组,因为图片像素的排布可以看作一个二维数组么。
不过问题也不大在这里插入图片描述
像素图片的像素在数组中的索引是以这种方式排布的。
在这里插入图片描述
所以如何把一张图的像素转到另一张上,便成了这样的一个数学问题。
(需要创建一张目标规格的图片,然后将原图的像素转移到正确位置)
(左:目标图,右:原图)

所以实际在索引并且确定目标图每一个像素颜色的时候,需要将目标图的索引号(左)转换为原图的索引号(右)并正确赋值,才能够将原图的信息正确的保存在我们目标规格的图片上。
实际上也只是一个
0 = func(7)
1 = func(8)

4 = func(13)

的问题。

在Texture的定义里,是有图片的宽高的,通过宽高,我们便可以将这个一维数组转换为一个二维数组的模型,来获得这个像素所在的行和列(个人row,culomn容易搞混,所以行列用x,y表示)

Texture2D.width
Texture2D.height
  • 1
  • 2

首先还是分析个例,
在左图上7号像素所在的位置是(1,1),对应的像素是右图中0号像素(0,0)。
从(1,1)到(0,0),x,y都减掉了1。
1是两张图片的长宽差的一半。
所以就有了(伪代码)
(current代表原图,target代表目标图,类型Texture2D)

public int GetCurrentIndex(int targetIndex)
{
	int widthDifference = target.width - current.width;
	int heightDifference = target.height - current.height;
	
	widthDifference /= 2;
	heightDifference /= 2;
	
	int x = targetIndex % target.width;
	int y = targetIndex / target.width;
	
	x -= widthDifference;
	y -= heightDifference;
	
	int currentIndex = y * current.width + x;
	return currentIndex;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

可以通过先将目标图片得一维索引转换为二维索引,减去两张图片相差得结果之后,获得在原图得二维索引,再转换为原图得一维索引,这样就可以获得原图在目标图上每个像素得正确位置。
也就是完成了 0 = func(7)的 func 函数算法。

但是这样做的话,不仅目标图蓝圈内的像素会获取像素,外部的像素依旧能够找到,而且也可能因为太大而超出原图的索引。所以我们需要做一个判断,来让外部的像素完全透明。
(同样是伪代码)

if(x >= 0 && y >= 0 && x < current.width && y < current.height && currentIndex< currentPixels.Length)
{
	targetPixels[targetIndex] = currentPixels[currentIndex];
}
else
{
	targetPixels[targetIndex] = new Color(0, 0, 0, 0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

只有符合全部条件(在篮圈内部)的像素才会被赋值。

上面大多是讲原理并非实际代码,可能很多地方看起来会脑壳疼。
下面是编辑器的完整代码,放在Editor目录下即可使用。

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

public class TrimCanvasEditor : EditorWindow
{
    [MenuItem("ImageHandle/TrimCanvas")]
    private static void GetWindow()
    {
        TrimCanvasEditor window = GetWindow<TrimCanvasEditor>(true, "修改画布大小", true);
        window.Show();
    }

    private SerializedObject serializedObject;
    private SerializedProperty texture2DListProperty;
    private Vector2Int trimSize;
    private Vector2Int offset;
    private string savePath;
    private string namePrefix;
    private string namePostfix;

    [SerializeField]
    private List<Texture2D> texture2DList;
    private Vector2 selectScrollPosition = Vector2.zero;

    private void OnEnable()
    {
        texture2DList = new List<Texture2D>();
        savePath = Application.dataPath;
        namePostfix = "copy";
        trimSize = new Vector2Int(256, 256);

        serializedObject = new SerializedObject(this);
        texture2DListProperty = serializedObject.FindProperty("texture2DList");
    }

    private void OnDisable()
    {
        serializedObject.Dispose();
    }

    private void OnGUI()
    {
        selectScrollPosition = EditorGUILayout.BeginScrollView(selectScrollPosition, EditorStyles.helpBox);

        EditorGUILayout.PropertyField(texture2DListProperty, new GUIContent("选择图集"), true);

        EditorGUILayout.Space();

        trimSize = EditorGUILayout.Vector2IntField("目标尺寸", trimSize);
        offset = EditorGUILayout.Vector2IntField("偏移", offset);

        EditorGUILayout.Space();

        for (int i = 0; i < texture2DListProperty.arraySize; i++)
        {
            SerializedProperty texProperty = texture2DListProperty.GetArrayElementAtIndex(i);
        }

        EditorGUILayout.BeginHorizontal();

        savePath = GUILayout.TextField(savePath);

        if (GUILayout.Button("选择保存路径"))
        {
            savePath = EditorUtility.OpenFolderPanel("路径选择", savePath, "");
        }

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.LabelField("图片前缀");
        namePrefix = EditorGUILayout.TextField(namePrefix);
        EditorGUILayout.LabelField("图片后缀");
        namePostfix = EditorGUILayout.TextField(namePostfix);

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        if (GUILayout.Button("保存", GUILayout.MinHeight(24), GUILayout.MinWidth(120)))
        {
            for (int i = 0; i < texture2DListProperty.arraySize; i++)
            {
                SerializedProperty texProperty = texture2DListProperty.GetArrayElementAtIndex(i);

                Texture2D item = texProperty.objectReferenceValue as Texture2D;

                Texture2D texture = new Texture2D(trimSize.x, trimSize.y, TextureFormat.RGBA32, item.streamingMipmaps);

                if (!item.isReadable)
                {
                    Debug.LogWarning("请打开图片的 Read/Write Enable");
                    return;
                }

                int widthDifference = texture.width - item.width;
                int heightDifference = texture.height - item.height;

                widthDifference /= 2;
                heightDifference /= 2;

                widthDifference += offset.x;
                heightDifference += offset.y;

                Color[] itemPixels = item.GetPixels();
                Color[] texturePixels = texture.GetPixels();

                for (int j = 0; j < texturePixels.Length; j++)
                {
                    int x = j % texture.width;
                    int y = j / texture.width;

                    x -= widthDifference;
                    y -= heightDifference;

                    int itemIndex = y * item.width + x;

                    if (x >= 0 && y >= 0 && x < item.width && y < item.height && itemIndex < itemPixels.Length)
                    {
                        texturePixels[j] = itemPixels[itemIndex];
                    }
                    else
                    {
                        texturePixels[j] = new Color(0, 0, 0, 0);
                    }
                }

                texture.SetPixels(0, 0, texture.width, texture.height, texturePixels);
                texture.Apply();

                string contents = Application.dataPath;

                byte[] bytes = texture.EncodeToPNG();
                if (!Directory.Exists(contents))
                    Directory.CreateDirectory(contents);
                FileStream file = File.Open(string.Format("{0}/{1}{2}{3}.png", savePath, namePrefix, texProperty.objectReferenceValue.name, namePostfix), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                BinaryWriter writer = new BinaryWriter(file);
                writer.Write(bytes);
                file.Close();

                EditorUtility.DisplayProgressBar("正在处理 : ", name, (float)i / texture2DListProperty.arraySize);
            }

            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
        }

        EditorGUILayout.EndScrollView();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157

在这里插入图片描述
讲想要的图片拖到数组中,设置目标尺寸,保存路径,偏移(不设置默认居中),还有图片名称,点击保存就可以批量修改图片的尺寸了。
这个修改方式不会压缩图片,如果目标尺寸小于原图尺寸,可能图片会被切掉一部分。
关于名称的设置是采用前缀+图片原名+后缀的形式,这样产生的新图片会和原图片编号相同,如果原图带有数字以外的字母,可以自己修改代码正则匹配想要的数字。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样可以快速的将所有图片修改为标准尺寸,并正确的压缩节省空间。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/636945
推荐阅读
相关标签
  

闽ICP备14008679号