C#編寫批量jpg檔案壓縮小工具
阿新 • • 發佈:2021-01-21
有一天,客戶領導說網站載入慢
客戶的網站請廣告公司設計的,堆疊了大量的高精度美圖。忽然有一天,老總說網站怎麼這麼慢?
客戶不懂技術,只管提需求
網站在建立的時候就已經告知會有什麼優點和弱項了,但是客戶都是善於遺忘的人。他們只管現在,不管過去。所以唯一不必的是變化這句話就又被驗證了一次。
怎麼辦呢?
- 全新的介面設計 ,重構網站?顯然不太現實,剛做好沒兩個月。
- 縮小圖片檔案大小是唯一可行可試的方案。第一步縮小時將png全部改為了jpg,因為不用考慮透明度的問題。第二步就是降低jpg圖片的質量,隨之減小檔案大小。
在tinypng.com 做了幾張,感覺太麻煩了,這要做到幾時去呢?
於是自己寫了一個小工具,可以批量的縮小jpg檔案的大小,當然圖片質量會略有下降了,但是普通訪問者都幾乎無法注意到,是可以接受的。
為了方便,寫了一個Console應用,命令列方式執行:
Please enter resize argument.
Usage: JpgResizer
Usage: JpgResizer *.jpg -r 75 -o -b -s
-b : 備份原始檔案,在覆蓋模式時有用 backup the original file. use when -o is set.
-o : 覆蓋模式,直接重寫原檔案 overwrite the original file.
-s : 搜尋當前目錄下的所有子目錄下的檔案 search all jpg files in sub-directories. ignore filename.
-r : 壓縮後圖片質量級別 compress level. default is 75, 100 is best.
原始碼,複製可用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using System.Drawing.Imaging; using System.IO; namespace JpgResizer { class Program { static bool isOverwrite = false; static Int64 ratio = 75L; static bool isIncludeSubDirectories = false; static bool isBackup = false; static void Main(string[] args) { string filename = "*.jpg"; if (args.Length == 0) { Console.WriteLine("============== JPG Compress tool =================="); Console.WriteLine("= Author : shrek"); Console.WriteLine("= Contact: (QQ390652)"); Console.WriteLine("= Date : 2021.01.21"); Console.WriteLine("= Hangzhou Codans Cyberinfo Company. "); Console.WriteLine("==================================================="); Console.WriteLine("Please enter resize argument."); Console.WriteLine("Usage: JpgResizer <filename> -r 75 -o -b"); Console.WriteLine("Usage: JpgResizer *.jpg -r 75 -o -b -s"); Console.WriteLine(" -b : backup the original file. use when -o is set."); Console.WriteLine(" -o : overwrite the original file. "); Console.WriteLine(" -s : search all jpg files in sub-directories. ignore filename."); Console.WriteLine(" -r : compress level. default is 75, 100 is best."); return; } filename = args[0]; if (!filename.Contains(".jpg") && !filename.Contains(".jpeg") && !filename.Contains("*")) { Console.WriteLine(" missing filename."); return; } var index = 1; foreach (var item in args.Skip(1)) { if (item.ToLower() == "-o") { isOverwrite = true; } if (item.ToLower() == "-b") { isBackup = true; } else if (item.ToLower()== "-s") { isIncludeSubDirectories = true; } else if (item.ToLower()=="-r") { if (args.Length >= index+1) { ratio = Int64.Parse(args[index + 1]); } else { Console.WriteLine(" missing ratio paramenter."); return; } } index++; } if (isIncludeSubDirectories) { ListJpg(AppContext.BaseDirectory); } else { VaryQualityLevel(filename, ratio, isOverwrite); } } private static void ListJpg(string dir) { DirectoryInfo d = new DirectoryInfo(dir); FileInfo[] files = d.GetFiles("*.jpg");//檔案 DirectoryInfo[] directs = d.GetDirectories();//資料夾 foreach (FileInfo f in files) { VaryQualityLevel(f.FullName, ratio, isOverwrite); } //獲取子資料夾內的檔案列表,遞迴遍歷 foreach (DirectoryInfo dd in directs) { ListJpg(dd.FullName); } } private static ImageCodecInfo GetEncoder(ImageFormat format) { ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.FormatID == format.Guid) { return codec; } } return null; } private static void VaryQualityLevel(string fileName,Int64 ratio,bool isOverwrite) { Console.WriteLine($"filename : {fileName}"); // Get a bitmap. The using statement ensures objects // are automatically disposed from memory after use. var originalSize = new FileInfo(fileName).Length; var newSize = 0L; var newFileName = Path.GetFileNameWithoutExtension(fileName) + "_new" + Path.GetExtension(fileName); if (isOverwrite) { newFileName = fileName; if (isBackup) { var backupFileName = Path.GetFileNameWithoutExtension(fileName) + "_original" + Path.GetExtension(fileName); File.Copy(fileName, backupFileName, true); } } using (Bitmap bmp0 = new Bitmap(fileName)) { var bmp1 = new Bitmap(bmp0); bmp0.Dispose(); ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg); // Create an Encoder object based on the GUID // for the Quality parameter category. System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; // Create an EncoderParameters object. // An EncoderParameters object has an array of EncoderParameter // objects. In this case, there is only one // EncoderParameter object in the array. EncoderParameters myEncoderParameters = new EncoderParameters(1); EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, ratio); myEncoderParameters.Param[0] = myEncoderParameter; bmp1.Save(newFileName, jpgEncoder, myEncoderParameters); newSize = new FileInfo(newFileName).Length; Console.WriteLine($" resize ok. {originalSize} -> {newSize} { ((originalSize - newSize) * 100 / originalSize).ToString("0.#") }% compressed."); } } } }
總結
參考了以下資訊,站在別人的肩膀上就看得遠一些。
【日月談】是自己維護的一個微信小程式,可以線上寫日記,有好多朋友寫了快20年,您如果有興趣,可以去用用看。
https://everyday.yuelvsu.com