Batch Convert WebP and AVIF images using PowerShell

Unfortunately, WebP and AVIF are not supported by most graphics software. Here’s a script that converts PNG files to WebP and AVIF using PowerShell.

By Squirrel Logic on Sep 23, 2020

With the launch of the AVIF image format, I’ve been seeing requests about AVIF support in Affinity Designer. I’m not optimistic, looking at recent history. None of the major graphics applications out there support WebP which has been around for a decade. The new AVIF image format with its impressive results is probably going to follow that same fate.

But there’s still a solution to easily getting your WebP and AVIF files quickly. And because we are running a script, we can get some added benefits too, like making your PNG and JPEG files even smaller without any loss in quality.

At Squirrel Logic, we’ve been using PowerShell scripts to prepare artwork for the web. It optimizes all PNG and JPEG files in place, and converts the PNG files to WebP and AVIF.

What the script does

The script creates an array of all PNG and JPEG files in a folder. The $inputFolder variable specifies the location of the input folder. The PowerShell script will search for all files contained in that folder, including all subfolders using the -Recurse attribute.

If it’s a JPEG file, it will run jpegoptim to strip any unnecessary data and reduce the file size without harming the image quality.

If it’s a PNG file, it will losslessly optimize the PNG file in place to dramatically reduce the file size, but then it will also create a WebP file, a AVIF file, and losslessly optimize the PNG file to make it smaller. We use PNG as the source file to create the other lossy formats (WebP and AVIF). This means that even though you may intend to use only the lossy version of the image file on your site (JPG, )

1. Download the binaries

This PowerShell script depends on a handful of files to be downloaded and placed in a /bin folder:

2. PowerShell script source code

Save this script in a .ps1 file. I have it named web-image-optimizer.ps1, but the name doesn’t matter.

# Configuration
$inputFolder = ".\input\"

# Setup
$pngs = Get-ChildItem -Path $inputFolder -Include "*.png" -Recurse
$jpgs = Get-ChildItem -Path $inputFolder -Include "*.jpg" -Recurse
$imagesTotal = ($pngs.Length * 3) + $jpgs.Length
$imagesDone = 0

foreach ($jpg in $jpgs) {
    # Optimize JPGs
    $imageName = $jpg.Name
    $imageFullName = $jpg.FullName
    $percent = ( $imagesDone / $imagesTotal ) * 100
    Write-Progress -Activity "Optimizing $imageName" -PercentComplete $percent -Status "jpegoptim"
    Invoke-Expression ".\bin\jpegoptim.exe -s `"$imageFullName`""
    $imagesDone++
}

foreach ($png in $pngs) {
    # Optimize PNGs
    $imageName = $png.Name
    $imageBaseName = $png.BaseName
    $imageFullName = $png.FullName
    $percent = ( $imagesDone / $imagesTotal ) * 100
    Write-Progress -Activity "Optimizing $imageName" -PercentComplete $percent -Status "optipng"
    Invoke-Expression ".\bin\optipng.exe `"$imageFullName`" -nc -nb -o1 -strip all -quiet"
    $imagesDone++

    # Create WebP 
    $percent = ( $imagesDone / $imagesTotal ) * 100
    Write-Progress -Activity "Converting $imageName to WebP" -PercentComplete $percent -Status "cwebp"
    Invoke-Expression ".\bin\cwebp.exe -q 75 `"$inputFolder$imageName`" -o `"$inputFolder$imageBaseName.webp`""
    $imagesDone++

    # Create AVIF
    $percent = ( $imagesDone / $imagesTotal ) * 100
    Write-Progress -Activity "Converting $imageName to AVIF" -PercentComplete $percent -Status "avif-win-x64.exe"
    Invoke-Expression ".\bin\avif-win-x64.exe -q 20 -e `"$inputFolder$imageName`" -o `"$inputFolder$imageBaseName.avif`""
    $imagesDone++
}

Write-Progress -Activity "Optimizing finished!" -Status "DONE" -Completed

3. Usage

Just run the script via command line or right-click on the file and select “Run with PowerShell”. It will run the script using the input folder specified in the script.

Running a PowerShell script for the first time

If you have never run a PowerShell script before, you’ll need to do some initial setup first. By default the ability to run PowerShell scripts is disabled.

To enable PowerShell scripts, first you need to run Windows PowerShell as an admin.

  • Type “PowerShell” in the Start Menu search, right-click on the icon, and select “Run as administrator”

  • In the terminal, type run the command Set-ExecutionPolicy RemoteSigned

This will allow you to run scripts on your computer, but not scripts downloaded from the Internet. If for some reason you want to run a script that PowerShell blocks, right click on the .ps1 file, choose properties, On the General tab, under Security, click the Unblock check-box, click OK.

At this point the scripts should work.

How to use WebP and AVIF images on the web with fallbacks

As we wait for Apple to catch up with a 10-year-old image format, WebP is not universally supported. At time of writing, AVIF is so new that less than 1% of web users are running supporting browsers. Although you can check out caniuse.com’s AVIF support table and the WebP support table to check current browser support.

You can still use these new formats safely using the <picture> element to specify fallback images.

Here’s an example:

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="">
</picture>

I like to implement this using partials or components in my front-end framework. If you are using WordPress, just stick with JPEG and PNGs for now.

Share: