imagebatch-filepngquant

How to perform batch PNG compression with PNGQUANT and save all converted images with their source names to another folder?


I want to compress all png image files existing in a directory and save all these converted/compressed image files into a different folder with their original image names using pngquant:

Syntax for batch compression:

pngquant.exe --quality=40-55 images\*.png

It compresses all the PNG image files in images directory and saves compressed files as new files in the same directory with appending -fs8 after the name of original file, e.g.

arrow.png
arrow-fs8.png

arrow.png is the source file and arrow-fs8.png is the output file.

I want to save all converted files with their original names in a separate folder.

Does anyone know how to do this with pngquant.exe?

Help output by pngquant on running it with option -h:

pngquant, 2.5.2 (October 2015), by Greg Roelofs, Kornel Lesinski.
   Compiled without support for color profiles. Using libpng 1.6.18.

usage:  pngquant [options] [ncolors] -- pngfile [pngfile ...]
        pngquant [options] [ncolors] - >stdout <stdin

options:
  --force           overwrite existing output files (synonym: -f)
  --skip-if-larger  only save converted files if they're smaller than original
  --output file     destination file path to use instead of --ext (synonym: -o)
  --ext new.png     set custom suffix/extension for output filenames
  --quality min-max don't save below min, use fewer colors below max (0-100)
  --speed N         speed/quality trade-off. 1=slow, 3=default, 11=fast & rough
  --nofs            disable Floyd-Steinberg dithering
  --posterize N     output lower-precision color (e.g. for ARGB4444 output)
  --verbose         print status messages (synonym: -v)

Quantizes one or more 32-bit RGBA PNGs to 8-bit (or smaller) RGBA-palette.
The output filename is the same as the input name except that
it ends in "-fs8.png", "-or8.png" or your custom extension (unless the
input is stdin, in which case the quantized image will go to stdout).
The default behavior if the output file exists is to skip the conversion;
use --force to overwrite. See man page for full list of options.

Solution

  • Here is the commented batch code for the task with additional features.

    @echo off
    setlocal
    
    rem It is expected that pngquant.exe is in same directory as the
    rem batch file and %~dp0 returns this path ending with a backslash.
    set "ToolPath=%~dp0"
    
    rem Use as source directory either the first specified parameter
    rem on calling this batch file or the current working directory.
    set "SourceFolder=%~f1"
    if "%SourceFolder%" == "" set "SourceFolder=%CD%"
    
    rem Replace all slashes by backslashes.
    set "SourceFolder=%SourceFolder:/=\%"
    rem Remove last character if it is a backslash.
    if  "%SourceFolder:~-1%" == "\" set "SourceFolder=%SourceFolder:~0,-1%"
    
    rem Use as output directory either the second specified parameter
    rem on calling this batch file or the current working directory.
    set "OutputFolder=%~f2"
    if "%OutputFolder%" == "" set "OutputFolder=%CD%"
    set "OutputFolder=%OutputFolder:/=\%"
    if  "%OutputFolder:~-1%" == "\" set "OutputFolder=%OutputFolder:~0,-1%"
    
    rem Set source directory as current directory. The source directory
    rem can be also specified with an UNC path which is the reason why
    rem command PUSHD is used and not command CD.
    pushd "%SourceFolder%"
    
    rem Either optimize all PNG files in source directory with output
    rem also in source directory using default new file name or process
    rem in a loop each PNG file separately with writing the optimized
    rem image to output directory with same name as source file.
    
    if /I "%SourceFolder%" == "%OutputFolder%" (
        "%ToolPath%pngquant.exe" --quality=40-55 --force *.png
    ) else (
        if not exist "%OutputFolder%" (
            md "%OutputFolder%"
            if errorlevel 1 (
                echo Failed to create the output folder:
                echo.
                echo %OutputFolder%
                echo.
                pause
                goto RestoreEnviroment
            )
        )
        for %%I in (*.png) do (
            "%ToolPath%pngquant.exe" --quality=40-55 --force --output "%OutputFolder%\%%I" "%%I"
        )
    )
    
    :RestoreEnviroment
    rem Restore the previous current directory and delete the local copy of
    rem the environment variables table, i.e. restore previous environment.
    popd
    endlocal
    

    It is possible to specify source folder as first parameter and output folder as second parameter on starting/calling this batch file.

    If the source folder should be the same folder as the batch file and just an output folder should be specified on starting/calling this batch file, specify as first parameter just . for current folder.

    For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.