简体   繁体   中英

Windows batch - getting the smallest filesize with jpegtran

I have recently discovered jpegtran, a tool that can losslessly optimize jpeg files. It is a command line tool that can do many different lossless operations on jpegs depending on the provided flags. In this case the flags of interest are -optimize, -copy none and -progressive. The first one optimizes the jpeg by optimizing the Huffman tables, the second one strips all meta data while the third one creates a progressive jpeg which allows browsers to display a lower quality version of the file before the entire file is downloaded.

Getting the smallest possible file size with jpegtran is not as easy as it may at first seem. It would stand to reason that the progressive jpegs should be larger since in case of gifs and pngs interlacing (which while not the same as progressive jpgs accomplishes a similar goal) always results in larger file sizes, however this is not the case for progressive jpegs. I have done a few tests and researched the problem online and it seems that there is no way to tell whether a given jpeg will be smaller when saved as baseline (-optimize) or progressive (-progressive). I have also tested using both flags but the file size when using both -optimize and -progressive flags is the same as when using just the -progressive flag.

My goal is to optimize several folders with hundreds of jpegs in each of them. As such a batch script seems to be the obvious solution. Unfortunately I don't have much experience with batch scripts and therefore I decided to look for one online. I found a couple but this is the one I decided to go with initially ( http://blog.stationfour.com/automating-png-jpg-image-optimization-in-windows/ ):

@echo none
cd %1
md "%~1\OptimizedJPEGS"
for %%i in (*.jpg) do "C:\Program Files\Image Optimization\jpegtran.exe" -optimize -copy none "%%i" "%~1\OptimizedJPEGS\%%i"
move /Y "%~1\OptimizedJPEGS\*.*" "%~1"
for %%i in (*.jpeg) do "C:\Program Files\Image Optimization\jpegtran.exe" -optimize -copy none "%%i" "%~1\OptimizedJPEGS\%%i"
move /Y "%~1\OptimizedJPEGS\*.*" "%~1"
rd "%~1\OptimizedJPEGS"

I did modify the code by removing the progressive flag and adding another loop to also optimize files with the .jpeg extension (the original script only optimized files with the .jpg extension).

The problem that I am facing right now is how to write a script that would save each jpeg in the target directory with -optimized and -progressive flags separately and would keep only the version with the smaller file size. I guess the main question is whether this can be done within one script or should there be one script for saving the files and another for choosing the version to keep.

Interesting question! First of all, a small detail: you don't need two separate for commands to process two extensions, you may insert both extensions in the same for this way:

for %%i in (*.jpg *.jpeg) do "C:\Program Files\Image Optimization\jpegtran.exe" -optimize -copy none "%%i" "%~1\OptimizedJPEGS\%%i"

Now about your problem: you must optimize all files twice: with and without -progressive flag, and then compare the size of each pair of files in order to get the smallest one:

@echo off
cd %1

rem Create optimizations with no Progressive
md "%~1\OptimizedNotProg"
for %%i in (*.jpg *.jpeg) do "C:\Program Files\Image Optimization\jpegtran.exe" -optimize -copy none "%%i" "%~1\OptimizedNotProg\%%i"

rem Create optimizations with Progressive
md "%~1\OptimizedProg"
for %%i in (*.jpg *.jpeg) do "C:\Program Files\Image Optimization\jpegtran.exe" -progressive -optimize -copy none "%%i" "%~1\OptimizedProg\%%i"

rem Delete the larger versions
for %%i in (*.jpg *.jpeg) do (
   for /F "tokens=1,2 delims=;" %%a in ("%~1\OptimizedNotProg\%%~NXi;%~1\OptimizedProg\%%~NXi") do (
      if %%~Za gtr %%~Zb (
         del "%%a"
      ) else (
         del "%%b"
      )
   )
)

rem Move the smaller versions
move /Y "%~1\OptimizedNotProg\*.*" "%~1"
rd "%~1\OptimizedNotProg"
move /Y "%~1\OptimizedProg\*.*" "%~1"
rd "%~1\OptimizedProg"
@ECHO OFF
SETLOCAL
:: temporary filename
:tmploop
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" GOTO tmploop
ECHO.>"%tempfile%.a"
pushd %1
md OptimizedJPEGS 2>nul
for %%i in (*.jpg *.jpeg) do (
 COPY /b "%%i" "%tempfile%.j1" >nul
 FOR %%m IN ("-optimize" "-progressive" "-progressive -optimize") DO (
  "C:\Program Files\Image Optimization\jpegtran.exe" %%~m -copy none "%%i" "%tempfile%.j2"
  FOR /f "skip=1delims=" %%e IN ('dir /b/os "%tempfile%.j*"') DO (
   DEL "%tempfile%%%~xe"
   REN "%tempfile%.j*" "%%~ne.j1"
  )
 )
 move /Y "%tempfile%.j*" ".\OptimizedJPEGS\%%i" >nul
)
POPD
DEL "%tempfile%*"
GOTO :EOF

This should tackle the problem.

First, create a temporary filename and make sure that it is unique.
Then go to the chosen directory
Find all of the target files; first copy the original to .j1
Then for each of the switch combinations, process to .j2 and delete whichever is the longer of .j1 and .j2
Finally move the shortest back to the OptimizedJPEGS subdirectory

I thought it would be better to build the new JPEG set in the Optimized directory and leave the original alone - just in case.

This should create a.bin and b.bin for JPG/JPEG files and compare the sizes , and move the smallest one to replace the JPG file.

It will process every JPG/JPEG file under c:\\base\\folder

Test it on a sample folder tree first.

@echo off
for /r "c:\base\folder" %%z in (*.jpg *.jpeg) do (
   del "%%~dpz\a.bin" "%%~dpz\b.bin" 2>nul
   "C:\Program Files\Image Optimization\jpegtran.exe" -optimize -copy none "%%z" "%%~dpz\a.bin"
   "C:\Program Files\Image Optimization\jpegtran.exe" -progressive -optimize -copy none "%%z" "%%~dpz\b.bin"
      for %%a in ("%%~dpz\a.bin") do for %%b in ("%%~dpz\b.bin") do (
         if %%~za GEQ %%~zb (move /y "%%~dpz\b.bin" "%%z") else (move /y "%%~dpz\a.bin" "%%z")
      )
   del "%%~dpz\a.bin" "%%~dpz\b.bin" 2>nul
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM