我制作了一个批处理文件,它能够压缩许多png
文件(使用ffmpeg
)以及删除任何不需要的元数据(使用exiftool
)。
@echo off
title Compress png to png
color 08
FOR %%a IN (*.png) DO (
echo Compressing: %%~na
exiftool "%%a" -all= -overwrite_original
ffmpeg -i "%%a" "converted\%%~na.png"
del "%%a"
)
这样文件大小最多可缩小 60 倍!(至少对于小型 png 图标而言)
不幸的是,有时压缩ffmpeg
实际上并没有减小文件大小,反而增加了文件大小(尤其是当图像较大时),这破坏了该过程的整个目的。
所以我想知道是否有办法检查输出(一旦压缩ffmpeg
)并查看其大小是否小于输入。然后采取相应的措施。
像这样...
@echo off
title Compress png to png
color 08
FOR %%a IN (*.png) DO (
echo Compressing: %%~na
exiftool "%%a" -all= -overwrite_original
ffmpeg -i "%%a" "converted\%%~na.png"
CHECK: Is compressed file smaller in size than "%%a" ?
If not, then delete converted\%%~na.png, and move* "%%a" in \converted
If it is, then just delete "%%a"
del "%%a"
)
还请告诉我是否有更好的方法来完成所有这些工作。
答案1
以下是一些 PowerShell 逻辑,仅当新文件小于我jpg
过去用于文件的原始文件时才执行复制操作。
这还会将新的较小文件重置为原始文件的CreationTime
,LastWriteTime
,并且LastAccessTime
本质上在该过程的一部分中保留该元数据。
我根据您的评论针对您的特定需求做了一些调整。我还提供了一个批处理脚本示例,以便在提取后根据需要执行 PowerShell 脚本。
通过批处理执行 PowerShell
笔记:这是解压出来的批处理脚本,双击执行解压到同一位置的PS脚本。
SET PSScriptName=Compress.ps1
CD /D "C:\Windows\System32\WindowsPowerShell\v1.0"
PowerShell -NoProfile -ExecutionPolicy Bypass -file "%~dp0%PSScriptName%"
电源外壳
$scriptPath = (Split-Path $MyInvocation.MyCommand.Path -Parent);
$imagelocation = "$scriptPath";
$convertedlocation = "$env:LOCALAPPDATA\Temp";
If(!(Test-Path $convertedlocation)){New-Item -Path $convertedlocation -ItemType Directory -Force;};
$src = Get-ChildItem -LiteralPath "$imagelocation\" -File | ? {$_.extension -match ".jpg|.jpeg|.jfif"};
$dest = $convertedlocation;
$originals = "$scriptPath\_originals";
If(!(Test-Path "$($originals)")){New-Item -Path "$($originals)" -ItemType Directory -Force;};
$scnt = $src.count;
$cnt = 0;
Write-Host "LOSSY COMPRESSION" -ForegroundColor Gray;
$src | % { Process {
$cnt += 1;
$sz = [math]::round(($_.Length / 1MB),2);
If($_.extension -match ".jpg|.jpeg|.jfif"){
If(Test-Path "$($originals)"){Copy-Item -LiteralPath $_.FullName -Destination "$originals\$($_.basename)$($_.Extension)_original" -Force -ErrorAction SilentlyContinue};
Start-Process exiftool -WorkingDirectory $scriptPath -ArgumentList "`"$($_.FullName)`" -all= -overwrite_original" -Wait -WindowStyle Hidden;
Start-Process ffmpeg -WorkingDirectory $scriptPath -ArgumentList "-i `"$($_.FullName)`" `"$($dest)\$($_.Basename).jpg`"" -Wait -WindowStyle Hidden;
$osize = "";
$dsize = "";
$osize = (Get-Childitem -LiteralPath $_.FullName -ErrorAction SilentlyContinue).Length;
$dsize = (Get-Childitem -LiteralPath "$($dest)\$($_.Basename).jpg" -ErrorAction SilentlyContinue).Length;
$nsz = [math]::round(($dsize / 1MB),2)
$osz = [math]::round(($osize / 1MB),2)
If($osize -gt $dsize){
$ct = $_.CreationTime;
$wt = $_.LastWriteTime;
$at = $_.LastAccessTime;
Copy-Item -LiteralPath "$($dest)\$($_.Basename).jpg" -Destination "$($_.Directory.FullName)\$($_.Basename).jpg" -Force;
Set-ItemProperty -LiteralPath "$($_.Directory.FullName)\$($_.Basename).jpg" -Name CreationTime -Value $ct;
Set-ItemProperty -LiteralPath "$($_.Directory.FullName)\$($_.Basename).jpg" -Name LastWriteTime -Value $wt;
Set-ItemProperty -LiteralPath "$($_.Directory.FullName)\$($_.Basename).jpg" -Name LastAccessTime -Value $at;
Write-Host "$cnt of $scnt from $osz MB to $nsz MB ==> $($_.Directory.FullName)\$($_.Basename).jpg" -ForegroundColor Green;
If(Test-Path "$($scriptPath)\$($_.Basename).jpeg"){Remove-Item -Path "$($scriptPath)\$($_.Basename).jpeg" -Force};
If(Test-Path "$($scriptPath)\$($_.Basename).jfif"){Remove-Item -Path "$($scriptPath)\$($_.Basename).jfif" -Force};
Remove-Item -LiteralPath "$($dest)\$($_.Basename).jpg" -Force -ErrorAction SilentlyContinue;
} Else { Remove-Item -LiteralPath "$($dest)\$($_.Basename).jpg" ; Write-Host "$cnt of $scnt orig size $osz MB smaller than new size $nsz MB ==> $($_.Directory.FullName)\$($_.Basename).jpg" -ForegroundColor Yellow; }
};
}};
支持资源
-
-
Get-ChildItem
通常返回一个FileInfo
对象。这些对象包含一些有用的属性,其中包括...- 完整路径、文件名和扩展名 (
FullName
), - 路径本身(
DirectoryName
), - 文件名 (
Name
),以及 - 不带扩展名的文件名 (
BaseName
)
- 完整路径、文件名和扩展名 (
-