前言
App瘦身是老生常談了,圖片壓縮算是一種最沒有技術(shù)含量,但效果也最好的方法。
圖片壓縮的工具有很多,有比這個(gè)更好也更方便的,但這里使用TinyPNG,原因有2個(gè),一是很久以前就在用,經(jīng)過了時(shí)間的考驗(yàn),二是出于興趣給自己寫了專用的工具,用起來也很方便。
最近在整理8年來的代碼,就將這個(gè)工具的代碼重構(gòu)一下,并開放到github上供有同樣興趣的人互相學(xué)習(xí)。
最后:tinypng是個(gè)好網(wǎng)址,每月有500次的免費(fèi)次數(shù)。身為一個(gè)程序猿,看到這個(gè)限制自然會忍不住把工具寫成了可以設(shè)置多個(gè)key,但這只涉及興趣,可以討論和學(xué)習(xí)。實(shí)際上500次已經(jīng)足夠大家使用了,很少有項(xiàng)目每月增加500張圖片這么多,就算偶爾超出,收費(fèi)也并不貴。大家有條件的話盡量付費(fèi)使用。
項(xiàng)目
源文件:
https://github.com/pkgogai/GYDFoundation/blob/master/GYDShellTools/Code/批量圖片壓縮/GYDShellTinifyTools.h
可執(zhí)行文件:(githubusercontent連不上的原因可自行百度,或者clone整個(gè)項(xiàng)目后去對應(yīng)位置拿?。?br>
https://github.com/pkgogai/GYDFoundation/blob/master/Help/tinify/compress_image.zip
流程
準(zhǔn)備工作:
- 從官網(wǎng)申請key。https://tinypng.com/developers
- 準(zhǔn)備圖片所在目錄的路徑,會深度遍歷處理。
- 再準(zhǔn)備一個(gè)用來記錄處理情況的文件路徑,處理結(jié)果會保存到這里,以便每次只做增量處理。
工具執(zhí)行步驟:
- 輸入?yún)?shù):
- key: 權(quán)限,有多個(gè)key的話用逗號分隔。
- path: 圖片路徑。
- log: 記錄文件路徑。
- 準(zhǔn)備圖片:
- 遍歷路徑找出所有png圖片。
- 使用記錄文件篩選出沒處理過的圖片。
- 從大到小排序。
- 處理圖片:
- 使用官網(wǎng)api處理每張圖片。
- 一個(gè)Key次數(shù)用盡則換下一個(gè)Key。
- 成功后直接替換原文件。
- 保存記錄。
- 結(jié)束情況:
- 處理完成。
- 所有key的次數(shù)用盡。
- 出錯(cuò):網(wǎng)絡(luò)、文件讀寫等錯(cuò)誤。
實(shí)現(xiàn)
官方API
官網(wǎng)上還有更簡單的api,但因?yàn)榇蹭亴ξ业木鞈?,沒有進(jìn)行嘗試。
https://api.tinify.com/shrink
POST
header填充 Authorization : Basic base64(api:$"key"),偽代碼:
key = 網(wǎng)站上申請到的key;
token = base64("api:"+key);
header["Authorization"] = "Basic " + token;
body為圖片文件數(shù)據(jù)。
處理成功的返回
{
input = {
size = 91733;
type = "image/png";
};
output = {
height = 1334;
ratio = "0.2585";
size = 23711;
type = "image/png";
url = "https://api.tinify.com/output/gah3v1eexhmty1gt8ujhjfhge2gbf1g2";
width = 750;
};
}
處理失敗的情況我們只關(guān)注一個(gè),http狀態(tài)碼429表示次數(shù)用光。
記錄處理結(jié)果
對于處理結(jié)果,這里只記錄一個(gè)md5,沒必要記錄文件名等其它信息。如果真有沒壓縮的圖片和壓縮過的圖片不一樣,md5卻相同,遇到這種千年難遇的情況也只是少壓一個(gè)文件而已,無傷大雅。
文件格式:plist,結(jié)構(gòu):字典,文件的md5為key,value如表:
| value | 說明 | 判定條件 |
|---|---|---|
| -1 | 已壓縮到極致 | 壓縮后md5沒有變化 |
| 0 | 沒處理 | 這種情況不會記錄,所以不存在 |
| 1 | 已壓縮 | 至少經(jīng)過經(jīng)過了1次壓縮(原本想記錄壓縮次數(shù),但后來感覺沒必要) |
注:不用數(shù)據(jù)庫的原因是,文本文件記錄更利于git處理。
源碼接口
剛發(fā)現(xiàn)是否深度遍歷的參數(shù)忘記處理了,現(xiàn)在必定深度遍歷。
@interface GYDShellTinifyTools : NSObject
/** 權(quán)限 */
@property (nonatomic, copy, nullable) NSArray<NSString *> *apiKeys;
/** 壓縮一張圖片,如果換別的壓縮工具,就修改這里吧 */
- (nullable NSData *)imageDataForCompressImageData:(nonnull NSData *)imageData output:(out NSString * _Nullable * _Nullable)output;
/**
批量壓縮一個(gè)目錄中的圖片并直接替換
@param path 目錄路徑
@param resursive 目錄是否遞歸查找
@param filePath 記錄處理狀態(tài)到文件,以便下次跳過已處理的文件
*/
- (BOOL)compressImagesAtPath:(nonnull NSString *)path resursive:(BOOL)resursive historyFile:(nullable NSString *)filePath;
@end