添加图片优化工具
parent
146197b320
commit
65252cb36d
|
@ -0,0 +1,363 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace LJ_OptTools
|
||||
{
|
||||
public class TextureSizeOptUtilities
|
||||
{
|
||||
public struct TextureSizeData
|
||||
{
|
||||
public int width;
|
||||
public int height;
|
||||
public SpriteMetaData[] spDatas;
|
||||
}
|
||||
|
||||
public static bool NeedExtend(Texture2D tex, TextureImporter ti)
|
||||
{
|
||||
if (tex == null ||//用packingTag打图集 和 本身就是2的整数幂的 不需要处理
|
||||
(ti.textureType == TextureImporterType.Sprite && !string.IsNullOrEmpty(ti.spritePackingTag))
|
||||
) return false;
|
||||
var oWidth = tex.width;
|
||||
var oHeight = tex.height;
|
||||
if (oWidth <= 0 || oHeight <= 0) return false;
|
||||
|
||||
var tarW = (oWidth / 4 + ((oWidth % 4 > 0) ? 1 : 0)) * 4;
|
||||
var tarH = (oHeight / 4 + ((oHeight % 4 > 0) ? 1 : 0)) * 4;
|
||||
|
||||
return oWidth != tarW || oHeight != tarH;
|
||||
}
|
||||
|
||||
public static TextureSizeData CalcTextureSize(Texture tex, TextureImporter ti)
|
||||
{
|
||||
var ret = new TextureSizeData();
|
||||
|
||||
var oWidth = tex.width;
|
||||
var oHeight = tex.height;
|
||||
#region Get Sprites Data
|
||||
if (ti.spriteImportMode == SpriteImportMode.Multiple && ti.spritesheet.Length > 0) //精灵表单
|
||||
{
|
||||
var spData = ti.spritesheet;
|
||||
var length = spData.Length;
|
||||
ret.spDatas = new SpriteMetaData[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
ret.spDatas[i] = spData[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//图片大小调整为4的整数倍
|
||||
var tarW = (oWidth / 4 + ((oWidth % 4 > 0) ? 1 : 0)) * 4;
|
||||
var tarH = (oHeight / 4 + ((oHeight % 4 > 0) ? 1 : 0)) * 4;
|
||||
|
||||
ret.width = tarW;
|
||||
ret.height = tarH;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool ExtendTexture( string path)
|
||||
{
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
||||
var ti = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
if (!NeedExtend(tex, ti)) return false; //不是4的整数倍的才进行处理
|
||||
|
||||
var sizeData = CalcTextureSize(tex, ti);
|
||||
|
||||
var oWidth = tex.width;
|
||||
var oHeight = tex.height;
|
||||
|
||||
var texName = tex.name;
|
||||
var texFormat = ti.DoesSourceTextureHaveAlpha() ? TextureFormat.RGBA32 : TextureFormat.RGB24;
|
||||
|
||||
Color[] texPixels = null;
|
||||
|
||||
if (tex.isReadable)
|
||||
{
|
||||
texPixels = tex.GetPixels(0, 0, oWidth, oHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
Texture2D tmpTex = null;
|
||||
var tmpRT = RenderTexture.GetTemporary(oWidth, oHeight, 0, RenderTextureFormat.ARGB32);
|
||||
Graphics.Blit(tex, tmpRT);
|
||||
Resources.UnloadAsset(tex);
|
||||
RenderTexture.active = tmpRT;
|
||||
tmpTex = new Texture2D(oWidth, oHeight, TextureFormat.ARGB32, false);
|
||||
tmpTex.ReadPixels(new Rect(0, 0, oWidth, oHeight), 0, 0);
|
||||
tmpTex.Apply(false, false);
|
||||
RenderTexture.active = null;
|
||||
RenderTexture.ReleaseTemporary(tmpRT);
|
||||
texPixels = tmpTex.GetPixels(0, 0, oWidth, oHeight);
|
||||
Object.DestroyImmediate(tmpTex);
|
||||
}
|
||||
|
||||
var tarW = sizeData.width;
|
||||
var tarH = sizeData.height;
|
||||
|
||||
var newTex = new Texture2D(tarW, tarH, texFormat, false, true);
|
||||
var defaultPixels = new Color32[tarW * tarH];
|
||||
for (int j = 0, jmax = tarH * tarW; j < jmax; ++j)
|
||||
{
|
||||
defaultPixels[j] = Color.clear;
|
||||
}
|
||||
newTex.SetPixels32(defaultPixels);
|
||||
newTex.Apply(true, false);
|
||||
|
||||
|
||||
newTex.SetPixels(0, 0, oWidth, oHeight, texPixels);
|
||||
newTex.Apply(true, false);
|
||||
|
||||
var ext = Path.GetExtension(path).ToLower();
|
||||
|
||||
switch (ext)
|
||||
{
|
||||
case ".png":
|
||||
File.WriteAllBytes(path, newTex.EncodeToPNG());
|
||||
break;
|
||||
case ".jpg":
|
||||
File.WriteAllBytes(path, newTex.EncodeToJPG());
|
||||
break;
|
||||
case ".tga":
|
||||
File.WriteAllBytes(path, newTex.EncodeToTGA());
|
||||
break;
|
||||
}
|
||||
Object.DestroyImmediate(newTex);
|
||||
AssetDatabase.ImportAsset(path);
|
||||
|
||||
ti = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
|
||||
ti.spriteImportMode = SpriteImportMode.Multiple;
|
||||
if (sizeData.spDatas == null || sizeData.spDatas.Length < 1)
|
||||
{
|
||||
var spData = new SpriteMetaData[1];
|
||||
spData[0].name = texName;
|
||||
spData[0].rect = new Rect(0f, 0f, oWidth, oHeight);
|
||||
spData[0].border = Vector4.zero;
|
||||
spData[0].alignment = 0;
|
||||
ti.spritesheet = spData;
|
||||
}
|
||||
else
|
||||
{
|
||||
var newSPSheet = new SpriteMetaData[sizeData.spDatas.Length];
|
||||
for (int i = 0; i < sizeData.spDatas.Length; i++)
|
||||
{
|
||||
newSPSheet[i] = sizeData.spDatas[i];
|
||||
}
|
||||
ti.spritesheet = newSPSheet;
|
||||
}
|
||||
AssetDatabase.WriteImportSettingsIfDirty(path);
|
||||
AssetDatabase.ImportAsset(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void SettingPlantformTex(TextureImporter ti, TextureImporterPlatformSettings setting, bool useCrunched, bool pot)
|
||||
{
|
||||
|
||||
if (!setting.overridden)
|
||||
{
|
||||
setting.overridden = true;
|
||||
}
|
||||
//带透明通道 压缩格式测试完更改
|
||||
if (ti.DoesSourceTextureHaveAlpha())
|
||||
{
|
||||
if (useCrunched)
|
||||
{
|
||||
if (setting.format != TextureImporterFormat.ETC2_RGBA8Crunched)
|
||||
setting.format = TextureImporterFormat.ETC2_RGBA8Crunched;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setting.format != TextureImporterFormat.ASTC_RGBA_5x5)
|
||||
setting.format = TextureImporterFormat.ASTC_RGBA_5x5;
|
||||
}
|
||||
|
||||
}
|
||||
else //不带透明通道
|
||||
{
|
||||
if (useCrunched)
|
||||
{
|
||||
if (pot && setting.format != TextureImporterFormat.ETC_RGB4Crunched)
|
||||
setting.format = TextureImporterFormat.ETC_RGB4Crunched;
|
||||
else
|
||||
setting.format = TextureImporterFormat.ETC2_RGBA8Crunched;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setting.format != TextureImporterFormat.ASTC_RGB_5x5)
|
||||
setting.format = TextureImporterFormat.ASTC_RGB_5x5;
|
||||
}
|
||||
}
|
||||
|
||||
if (setting.compressionQuality < 100)
|
||||
{
|
||||
setting.compressionQuality = 100;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void SetTextureFormat( string path, bool useCrunched)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
var ti = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
if (ti == null)
|
||||
{
|
||||
Debug.LogWarning("Can load TextureImporter:" + path);
|
||||
return;
|
||||
}
|
||||
if (ti.textureShape != TextureImporterShape.Texture2D)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var pAndSetting = ti.GetPlatformTextureSettings("Android");
|
||||
var piPSetting = ti.GetPlatformTextureSettings("iPhone");
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
||||
bool pot = Mathf.IsPowerOfTwo(tex.width) && Mathf.IsPowerOfTwo(tex.height);
|
||||
SettingPlantformTex(ti, pAndSetting, useCrunched,pot);
|
||||
ti.SetPlatformTextureSettings(pAndSetting);
|
||||
SettingPlantformTex(ti, piPSetting, useCrunched, pot);
|
||||
ti.SetPlatformTextureSettings(piPSetting);
|
||||
|
||||
AssetDatabase.WriteImportSettingsIfDirty(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class TextureSizeOptTool
|
||||
{
|
||||
[MenuItem("Tools/图片优化/优化选中文件夹中的图片-ASTC", priority = 1)]
|
||||
public static void OnMenuItem_ASTC()
|
||||
{
|
||||
OptUITexSelectTex(false);
|
||||
}
|
||||
|
||||
[MenuItem("Tools/图片优化/优化选中文件夹中的图片-Crunched", priority = 2)]
|
||||
public static void OnMenuItem_Crunched()
|
||||
{
|
||||
OptUITexSelectTex(true);
|
||||
}
|
||||
|
||||
public static void OptUITexSelectTex(bool useCrunched)
|
||||
{
|
||||
|
||||
var guids = Selection.assetGUIDs;
|
||||
var filePaths = new List<string>();
|
||||
foreach (var id in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(id);
|
||||
//可判断文件是否存在
|
||||
if (File.Exists(path))
|
||||
{
|
||||
if (!filePaths.Contains(path))
|
||||
filePaths.Add(path);
|
||||
|
||||
} //可判断文件路径是否存在
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
var subFileGuids = AssetDatabase.FindAssets("t:Texture", new string[] { path });
|
||||
if (subFileGuids != null && subFileGuids.Length > 0)
|
||||
{
|
||||
foreach (var subId in subFileGuids)
|
||||
{
|
||||
var subPath = AssetDatabase.GUIDToAssetPath(subId);
|
||||
if (!filePaths.Contains(subPath))
|
||||
filePaths.Add(subPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filePaths.Count < 1) return;
|
||||
|
||||
for (int i = 0; i < filePaths.Count; i++)
|
||||
{
|
||||
string path = filePaths[i];
|
||||
EditorUtility.DisplayProgressBar(
|
||||
string.Format("Opt UI Texture({0}/{1})", i, filePaths.Count)
|
||||
, path
|
||||
, i * 1f / filePaths.Count
|
||||
);
|
||||
TextureSizeOptUtilities.ExtendTexture( path);
|
||||
TextureSizeOptUtilities.SetTextureFormat(path, useCrunched);
|
||||
}
|
||||
AssetDatabase.Refresh();
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
[MenuItem("Tools/图片优化/检查ManagedResources中所有图片格式", priority = 0)]
|
||||
public static void OnMenuItem_Check()
|
||||
{
|
||||
var guid = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/ManagedResources" });
|
||||
List<string> floders = new List<string>();
|
||||
int errorTexCount = 0;
|
||||
for (int i = 0; i < guid.Length; i++)
|
||||
{
|
||||
string id = guid[i];
|
||||
var path = AssetDatabase.GUIDToAssetPath(id);
|
||||
|
||||
if (
|
||||
path.StartsWith("Assets/ManagedResources/Atlas")
|
||||
) continue;
|
||||
|
||||
EditorUtility.DisplayProgressBar(
|
||||
string.Format("Check Texture({0}/{1})", i, guid.Length)
|
||||
, path
|
||||
, i * 1f / guid.Length
|
||||
);
|
||||
var floder = Path.GetDirectoryName(path);
|
||||
var ti = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
if (ti == null)
|
||||
{
|
||||
//Debug.LogError("No TextureImporter:" + path);
|
||||
continue;
|
||||
}
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
||||
|
||||
var pAndSetting = ti.GetPlatformTextureSettings("Android");
|
||||
var piPSetting = ti.GetPlatformTextureSettings("iPhone");
|
||||
|
||||
if (!pAndSetting.overridden || !piPSetting.overridden)
|
||||
{
|
||||
if (!floders.Contains(floder)) floders.Add(floder);
|
||||
++errorTexCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pAndSetting.format < TextureImporterFormat.ASTC_RGB_4x4 || piPSetting.format < TextureImporterFormat.ASTC_RGB_4x4)
|
||||
{
|
||||
if (!floders.Contains(floder)) floders.Add(floder);
|
||||
++errorTexCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tex.width % 4 != 0 || tex.height % 4 != 0)
|
||||
{
|
||||
if (!floders.Contains(floder)) floders.Add(floder);
|
||||
++errorTexCount;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (floders.Count > 0)
|
||||
{
|
||||
Debug.Log("Error Tex Count:" + errorTexCount);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var f in floders)
|
||||
{
|
||||
sb.AppendLine(f);
|
||||
}
|
||||
Debug.Log(sb.ToString());
|
||||
}
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b0b25c9e7b8af7f49a106f68f3d14da5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue