1:resize_pic.py腳本仪糖,這種直接改了原圖片的寬+高找前。
python->PIL
import os
from PIL import Image
import struct
#
#檢查并調(diào)整bg圖片的寬高栏妖,確保寬高都是4的倍數(shù),這樣才可以使用ETC壓縮格式
#'''
#遍歷目錄中的png文件
def list_pic(dirpath):
print(dirpath)
for root, dirs, fs in os.walk(dirpath):
for f in fs:
if f.endswith('.jpg') or f.endswith('.png'):
yield os.path.join(root, f)
#獲取圖片實(shí)際尺寸
def get_png_size(fpath):
with open(fpath, 'rb') as f:
f.seek(4*4, 0)
return (struct.unpack(">II", f.read(8)) )
def getSize(path):
img = Image.open(path)
imgSize = img.size #大小/尺寸
w = img.width #圖片的寬
h = img.height #圖片的高
f = img.format #圖像格式
return w,h
#列出寬高不是4的倍數(shù)的圖片
def list_not_4_pic(dirpath):
for f in list_pic(dirpath):
w,h = getSize(f)
print(f+"---"+str(w)+"---"+str(h))
if w%4 != 0 or h%4 != 0:
yield f
#調(diào)整圖片的尺寸辜窑,確保寬高是4的倍數(shù)
def resize_4_pic(dirpath):
with open('resize_4_pic.output.log', 'w') as log:
for f in list_not_4_pic(dirpath):
img = Image.open(f)
(w,h) = img.size
nw = (w%4==0) and w or (w + (4-(w%4)))
nh = (h%4==0) and h or (h + (4-(h%4)))
print( (w, h),'->',(nw,nh), f)
log.write("%s | (%d,%d)-> (%d,%d)\n"%(f,w, h,nw,nh))
img = img.resize( (nw,nh), Image.ANTIALIAS)
img.save(f)
if '__main__' == __name__:
resize_4_pic('.')
2:unity編輯器代碼處理
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
public class TextureSizeEditorWindow:EditorWindow
{
private int curNumber;
private string curFilePath;
private PlatformType platformType;
private List<string> allTexturePaths = new List<string>();
private List<string> allTextureExtension = new List<string>();
//查找不是4倍數(shù)的腳本
public const string ETC2_FILE_PATH = "_CheckETC2Size.log";
private FileStream fs;
private string etc2logFullPath;
private byte[] writeBytes;
private string ignoreDir = "Assets\\Art/Spine_special"; //
private List<string> noCheckDir = new List<string> {"Assets\\Main/Atlas", "Assets\\Main/Sprites"};
[MenuItem("Texture/TextureCompressSize")]
static void OpenTextureCompressPanel()
{
TextureSizeEditorWindow window = (TextureSizeEditorWindow)EditorWindow.GetWindow(typeof(TextureSizeEditorWindow), false, "TextureCompressSizeEditor", true);
window.Show();
}
private void OnGUI()
{
GUILayout.Label("請(qǐng)輸入你要壓縮的貼圖的文件路徑");
curFilePath = GUILayout.TextField(curFilePath);
//Android--ETC2格式需要是4的倍數(shù)
GUILayout.Label("查找不是4的倍數(shù)的圖片-ETC2 :");
if (GUILayout.Button("按照路徑查找-按鈕"))
{
curNumber = 0;
allTexturePaths.Clear();
string newFilePath = curFilePath.Replace("\\", "_");
newFilePath = newFilePath.Replace(":", "_");
newFilePath = newFilePath.Replace("Assets/", "");
etc2logFullPath = Application.dataPath + "/" + newFilePath + ETC2_FILE_PATH;
if (File.Exists(etc2logFullPath))
File.Delete(etc2logFullPath);
fs = new FileStream(etc2logFullPath, FileMode.OpenOrCreate);
GetAllTexturePath();
CheckAllTextureSizeCompress();
Debug.LogError("Android下查找不是4的倍數(shù)的圖片-ETC2钩述,PATH = " + etc2logFullPath);
writeBytes = null;
fs.Close();
}
GUILayout.Label("設(shè)置圖片為4的倍數(shù) : ");
if (GUILayout.Button("按照路徑修改-按鈕"))
{
curNumber = 0;
allTexturePaths.Clear();
allTextureExtension.Clear();
GetAllTexturePath();
ChangeAllTextureSizeCompress();
}
GUILayout.Label("關(guān)閉進(jìn)度條 : ");
if (GUILayout.Button("CloseBar-btn "))
{
EditorUtility.ClearProgressBar();
}
}
void GetAllTexturePath()
{
if (string.IsNullOrEmpty(curFilePath))
{
Debug.LogError("輸入的路徑有錯(cuò),curFilePath = " + curFilePath);
return;
}
SetAllTexturePath(curFilePath);
}
void SetAllTexturePath(string path)
{
DirectoryInfo info = new DirectoryInfo(path);
DirectoryInfo[] dirInfo = info.GetDirectories();
FileInfo[] files = info.GetFiles();
foreach (var fileInfo in files)
{
if (fileInfo.Extension == ".meta")
continue;
if (fileInfo.Extension == ".png" || fileInfo.Extension == ".tga" || fileInfo.Extension == ".jpg")
{
string curPath = path + "/" + fileInfo.Name;
Debug.LogError("文件的路徑==" + curPath);
allTexturePaths.Add(curPath);
allTextureExtension.Add(fileInfo.Extension);
}
}
foreach (DirectoryInfo nextDirInfo in dirInfo)
{
SetAllTexturePath(path + "/" + nextDirInfo.Name);
}
}
void CheckAllTextureSizeCompress()
{
if (allTexturePaths == null || allTexturePaths.Count == 0)
{
Debug.LogError("allTexturePaths is nil or length =0 , 輸入的路徑有錯(cuò)穆碎,curFilePath = " + curFilePath);
return;
}
for (int i = 0; i < allTexturePaths.Count; i++)
{
curNumber++;
if (!string.IsNullOrEmpty(allTexturePaths[i]))
{
EditorUtility.DisplayProgressBar(string.Format("Spine Export{0}/{1}",curNumber,allTexturePaths.Count),allTexturePaths[i],(float)curNumber/(float)(allTexturePaths.Count));
if(allTexturePaths[i].Contains(ignoreDir))
continue;
bool isExist = false;
for(int j = 0; j<noCheckDir.Count; j++)
{
if (allTexturePaths[i].Contains(noCheckDir[j]))
{
isExist = true;
}
}
if (isExist)
continue;
SetTextureSize(allTexturePaths[i]);
}
}
}
void SetTextureSize(string path)
{
Texture2D texture2D = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;
if (texture2D != null)
{
if (!((texture2D.width % 4 == 0) && (texture2D.height % 4 == 0)))
{
writeBytes = Encoding.UTF8.GetBytes( path + ", width =" + texture2D.width + ",height =" +texture2D.height + "\n");
fs.Write(writeBytes, 0, writeBytes.Length);
}
if (allTexturePaths != null && allTexturePaths.Count == curNumber)
{
EditorUtility.ClearProgressBar();
}
}
}
void ChangeAllTextureSizeCompress()
{
if (allTexturePaths == null || allTexturePaths.Count == 0)
{
Debug.LogError("allTexturePaths is nil or length =0 , 輸入的路徑有錯(cuò)牙勘,curFilePath = " + curFilePath);
return;
}
for (int i = 0; i < allTexturePaths.Count; i++)
{
if (!string.IsNullOrEmpty(allTexturePaths[i]))
{
curNumber++;
EditorUtility.DisplayProgressBar(string.Format("Spine Export{0}/{1}",curNumber,allTexturePaths.Count),allTexturePaths[i],(float)curNumber/(float)(allTexturePaths.Count));
if(allTexturePaths[i].Contains(ignoreDir))
continue;
bool isExist = false;
for(int j = 0; j<noCheckDir.Count; j++)
{
if (allTexturePaths[i].Contains(noCheckDir[j]))
{
isExist = true;
}
}
if (isExist)
continue;
ChangeTextureSize(allTexturePaths[i], allTextureExtension[i]);
}
}
}
void ChangeTextureSize(string path, string extension)
{
Texture2D texture2D = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;
bool needChange = false;
if(texture2D != null)
needChange = !((texture2D.width % 4 == 0) && (texture2D.height % 4 == 0));
if (needChange)
{
TextureImporterFormat lastTextureFormat;
bool lastIsReadable;
TextureImporter ti = (TextureImporter)TextureImporter.GetAtPath(path);
lastTextureFormat = ti.textureFormat;
lastIsReadable = ti.isReadable;
ti.isReadable = true;
ti.textureFormat = TextureImporterFormat.ARGB32;
AssetDatabase.ImportAsset(path);
Texture2D resultTexture = new Texture2D(texture2D.width + (4-texture2D.width%4), texture2D.height + (4-texture2D.height%4), TextureFormat.RGBA32, false);
resultTexture.name = texture2D.name;
int widthStart = (resultTexture.width - texture2D.width) / 2;
int heightStart = (resultTexture.height - texture2D.height) / 2;
Color outColor = new Color(0, 0, 0, 0);
//左下角開始
for (int wIndex = 0; wIndex < resultTexture.width; wIndex++)
{
for (int hIndex = 0; hIndex < resultTexture.height; hIndex++)
{
if ((widthStart + wIndex) > texture2D.width + widthStart)
{
// if (wIndex % 2 == 0)
// outColor = Color.black;
// else
// outColor = Color.red;
resultTexture.SetPixel(wIndex, hIndex, outColor);
}else if ( (heightStart + hIndex )> texture2D.height + heightStart)
{
// if (hIndex % 2 == 0)
// outColor = Color.black;
// else
// outColor = Color.red;
resultTexture.SetPixel(wIndex, hIndex, outColor);
}
else if(wIndex < widthStart)
{
// if (wIndex % 2 == 0)
// outColor = Color.black;
// else
// outColor = Color.red;
resultTexture.SetPixel(wIndex, hIndex, outColor);
}else if (hIndex < heightStart)
{
// if (hIndex % 2 == 0)
// outColor = Color.black;
// else
// outColor = Color.red;
resultTexture.SetPixel(wIndex, hIndex, outColor);
}
else
{
resultTexture.SetPixel(wIndex, hIndex, texture2D.GetPixel(wIndex-widthStart, hIndex-heightStart));
}
}
}
byte[] textuteByte = new byte[]{};
if (extension == ".png")
{
textuteByte = resultTexture.EncodeToPNG();
}
else if(extension == ".tga")
{
textuteByte = resultTexture.EncodeToTGA();
}else if (extension == ".jpg")
{
textuteByte = resultTexture.EncodeToJPG();
}
string filePath = Application.dataPath + path.Replace("Assets","");
File.WriteAllBytes(filePath, textuteByte);
ti = (TextureImporter)TextureImporter.GetAtPath(path);
ti.isReadable = lastIsReadable;
ti.textureFormat = lastTextureFormat;
AssetDatabase.ImportAsset(path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.LogError( "圖片尺寸更改完成, " + path + ", width =" + texture2D.width + ",height =" +texture2D.height + "\n");
}
if (allTexturePaths != null && allTexturePaths.Count == curNumber)
{
EditorUtility.ClearProgressBar();
}
}
}
3:也可以導(dǎo)入的時(shí)候設(shè)置2的N次方,但是感覺不適用所禀。