C#编写批量jpg文件压缩小工具
有一天,客户领导说网站加载慢
客户的网站请广告公司设计的,堆叠了大量的高精度美图。忽然有一天,老总说网站怎么这么慢?
客户不懂技术,只管提需求
网站在建立的时候就已经告知会有什么优点和弱项了,但是客户都是善于遗忘的人。他们只管现在,不管过去。所以唯一不必的是变化这句话就又被验证了一次。
怎么办呢?
- 全新的界面设计 ,重构网站?显然不太现实,刚做好没两个月。
- 缩小图片文件大小是唯一可行可试的方案。第一步缩小时将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
Let code dance.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗