摘要:Unity图片空白像素批量处理工具
该工具提供两种方式批量剔除图片空白像素:
静态处理类:提供TrimTexture方法,可读取纹理像素数据,计算非透明区域边界,生成裁剪后的新纹理;SaveTexture方法保存处理结果。
编辑器窗口:通过"Tools/UI"菜单打开窗口,支持多选PNG图片后批量处理。主要流程包括:加载选中项→分析像素边界→裁剪保存→恢复原始设置。处理时临时修改纹理为可读状态,完成后自动刷新资源库并统计成功数量。适用于UI图片资源优化,需在Unity编辑器环境下使用。
using UnityEditor;
using UnityEngine;
using System.IO;
public static class ImageTrimmerHandle
{
public static Texture2D TrimTexture(Texture2D sourceTexture)
{
if (sourceTexture == null) return null;
string assetPath = AssetDatabase.GetAssetPath(sourceTexture);
TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (importer == null) return null;
bool originalReadable = importer.isReadable;
TextureImporterCompression originalCompression = importer.textureCompression;
// 设置为可读
importer.isReadable = true;
importer.textureCompression = TextureImporterCompression.Uncompressed;
AssetDatabase.ImportAsset(assetPath);
AssetDatabase.Refresh();
// 重新加载纹理
Texture2D readableTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
Color[] pixels = readableTexture.GetPixels();
// 找到边界
int width = readableTexture.width;
int height = readableTexture.height;
int left = width;
int right = 0;
int top = 0;
int bottom = height;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Color pixel = pixels[y * width + x];
if (pixel.a > 0.01f) // 非完全透明
{
left = Mathf.Min(left, x);
right = Mathf.Max(right, x);
top = Mathf.Max(top, y);
bottom = Mathf.Min(bottom, y);
}
}
}
// 创建新纹理
int newWidth = right - left + 1;
int newHeight = top - bottom + 1;
Texture2D trimmedTexture = null;
if (newWidth > 0 && newHeight > 0)
{
trimmedTexture = new Texture2D(newWidth, newHeight, TextureFormat.RGBA32, false);
Color[] newPixels = new Color[newWidth * newHeight];
for (int y = bottom; y <= top; y++)
{
for (int x = left; x <= right; x++)
{
int sourceIndex = y * width + x;
int destIndex = (y - bottom) * newWidth + (x - left);
newPixels[destIndex] = pixels[sourceIndex];
}
}
trimmedTexture.SetPixels(newPixels);
trimmedTexture.Apply();
}
// 恢复原始导入设置
importer.isReadable = originalReadable;
importer.textureCompression = originalCompression;
AssetDatabase.ImportAsset(assetPath);
return trimmedTexture;
}
public static void SaveTexture(Texture2D texture, string savePath)
{
if (texture == null || string.IsNullOrEmpty(savePath)) return;
byte[] bytes = texture.EncodeToPNG();
string directory = Path.GetDirectoryName(savePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
File.WriteAllBytes(savePath, bytes);
AssetDatabase.Refresh();
Debug.Log("图片已保存至: " + savePath);
// 自动选择保存的资源
Texture2D savedTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(savePath);
if (savedTexture != null)
{
Selection.activeObject = savedTexture;
}
}
}
using UnityEditor;
using UnityEngine;
using System.IO;
public class ImageTrimmerWindow : EditorWindow
{
private Object[] selectedTextures;
[MenuItem("Tools/UI/批量剔除图片的空白像素")]
public static void ShowWindow()
{
GetWindow<ImageTrimmerWindow>("批量剔除图片的空白像素");
}
private void OnGUI()
{
GUILayout.Label("批量图片空白像素剔除", EditorStyles.boldLabel);
EditorGUILayout.Space();
EditorGUILayout.HelpBox("请选择一个或多个 PNG 图片文件(可在Project窗口多选后点击“从选中项加载”)。", MessageType.Info);
if (GUILayout.Button("从选中项加载"))
{
selectedTextures = Selection.GetFiltered(typeof(Texture2D), SelectionMode.Assets);
}
if (selectedTextures != null && selectedTextures.Length > 0)
{
EditorGUILayout.LabelField($"已选择图片数量: {selectedTextures.Length}");
if (GUILayout.Button("批量剔除并覆盖保存"))
{
int successCount = 0;
foreach (Object obj in selectedTextures)
{
Texture2D tex = obj as Texture2D;
if (tex == null) continue;
Texture2D trimmed = ImageTrimmerHandle.TrimTexture(tex);
if (trimmed != null)
{
string path = AssetDatabase.GetAssetPath(tex);
ImageTrimmerHandle.SaveTexture(trimmed, path);
successCount++;
}
}
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("处理完成", $"已处理并覆盖保存 {successCount} 张图片。", "确定");
}
}
else
{
EditorGUILayout.LabelField("未选择图片。");
}
}
}