windows图片压缩脚本
windows图片压缩脚本
windows图片压缩脚本
概述
compress-images.ps1
是一个 PowerShell 脚本,用于自动压缩中指定目录下的图片文件,将大于指定大小的图片压缩到目标大小以内,可用于优化博客等网站加载速度。
功能特性
- 🔍 自动扫描: 递归扫描指定目录下的所有图片文件
- 📏 智能压缩: 通过调整图片质量和尺寸实现压缩
- 🔄 多次尝试: 自动降低质量直到达到目标大小
- 💾 安全备份: 自动创建备份,失败时自动恢复
- 🎯 精确控制: 支持自定义目标文件大小
- 📊 详细报告: 显示压缩前后的文件大小对比
系统要求
- Windows 10/11
- PowerShell 5.1+
- .NET Framework(系统自带)
使用方法
基本用法
1
2
# 使用默认设置压缩图片
powershell -ExecutionPolicy Bypass -File "compress-images.ps1"
自定义参数
如需修改压缩参数,请编辑脚本中的以下变量:
1
2
$ImagePath = "/img # 图片目录路径
$MaxSizeKB = 30 # 目标文件大小(KB)
执行策略说明
如果遇到执行策略限制,可以使用以下方式:
1
2
3
4
5
6
# 方式1:绕过执行策略(推荐)
powershell -ExecutionPolicy Bypass -File "compress-images.ps1"
# 方式2:临时修改执行策略
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
.\compress-images.ps1
压缩策略
支持的图片格式
- JPG/JPEG
- PNG
压缩算法
- 尺寸调整: 将图片缩放到最大 800×600 像素(保持宽高比)
- 质量压缩: 从质量 60 开始,每次降低 10,最低到 10
- 智能选择: 选择满足大小要求的最低质量设置
安全机制
- 自动创建
.backup
备份文件 - 压缩失败时自动恢复原图
- 资源自动释放,避免文件占用
注意事项
- 备份重要: 脚本会自动备份原图,但建议在运行前手动备份重要图片
- 不可逆: 压缩后的图片会替换原图,请确保有备份
- 质量损失: 压缩会降低图片质量,请根据实际需求调整参数
- 文件占用: 确保图片文件没有被其他程序打开
完整脚本代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# Image compression script
# Compress images to under 30KB
$ImagePath = "/img"
$MaxSizeKB = 30
# Add System.Drawing assembly
Add-Type -AssemblyName System.Drawing
function Compress-Image {
param(
[string]$FilePath,
[int]$MaxSizeKB
)
try {
$file = Get-Item $FilePath
$originalSizeKB = [math]::Round($file.Length / 1KB, 1)
Write-Host "Processing: $($file.Name) - Original size: ${originalSizeKB}KB"
if ($originalSizeKB -le $MaxSizeKB) {
Write-Host " Skip - already under ${MaxSizeKB}KB" -ForegroundColor Green
return
}
# Create backup
$backupPath = $FilePath + ".backup"
Copy-Item $FilePath $backupPath -Force
# Load image
$image = [System.Drawing.Image]::FromFile($FilePath)
# Calculate new dimensions
$maxWidth = 800
$maxHeight = 600
$ratio = [Math]::Min($maxWidth / $image.Width, $maxHeight / $image.Height)
$newWidth = [int]($image.Width * $ratio)
$newHeight = [int]($image.Height * $ratio)
if ($ratio -ge 1) {
$newWidth = $image.Width
$newHeight = $image.Height
}
# Create new bitmap
$bitmap = New-Object System.Drawing.Bitmap($newWidth, $newHeight)
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
# Set high quality interpolation
$graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$graphics.DrawImage($image, 0, 0, $newWidth, $newHeight)
# Try multiple compressions with decreasing quality
$success = $false
for ($quality = 60; $quality -ge 10; $quality -= 10) {
$tempFile = $FilePath + ".tmp"
$encoder = [System.Drawing.Imaging.ImageCodecInfo]::GetImageDecoders() | Where-Object { $_.FormatID -eq [System.Drawing.Imaging.ImageFormat]::JPEG.Guid }
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
$encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter([System.Drawing.Imaging.Encoder]::Quality, [long]$quality)
$bitmap.Save($tempFile, $encoder, $encoderParams)
$compressedSizeKB = [math]::Round((Get-Item $tempFile).Length / 1KB, 1)
if ($compressedSizeKB -le $MaxSizeKB) {
$success = $true
break
}
Remove-Item $tempFile -Force
}
# Clean up resources
$graphics.Dispose()
$bitmap.Dispose()
$image.Dispose()
if ($success) {
Remove-Item $FilePath -Force
Move-Item $tempFile $FilePath -Force
$finalSizeKB = [math]::Round((Get-Item $FilePath).Length / 1KB, 1)
Write-Host " Success: ${finalSizeKB}KB (reduced ${($originalSizeKB - $finalSizeKB):F1}KB)" -ForegroundColor Green
Remove-Item $backupPath
} else {
Write-Host " Still too large after all attempts" -ForegroundColor Yellow
Copy-Item $backupPath $FilePath -Force
Remove-Item $backupPath
}
} catch {
Write-Host " Failed: $($_.Exception.Message)" -ForegroundColor Red
if (Test-Path $backupPath) {
Copy-Item $backupPath $FilePath -Force
Remove-Item $backupPath
}
}
}
# Get all image files (fix: use -Recurse and -File, and correct -Include usage)
$imageFiles = Get-ChildItem $ImagePath -Recurse -File | Where-Object { ($_.Extension -match "jpg|jpeg|png") -and ($_.Length / 1KB -gt $MaxSizeKB) }
Write-Host "Found $($imageFiles.Count) images larger than ${MaxSizeKB}KB" -ForegroundColor Cyan
foreach ($file in $imageFiles) {
Compress-Image -FilePath $file.FullName -MaxSizeKB $MaxSizeKB
}
Write-Host "Compression completed!" -ForegroundColor Green
本文由作者按照 CC BY 4.0 进行授权