JAXA - convert image files to JXL/AVIF

JAXA (JPEG-XL and AVIF Exchange Assistant) - User friendly bash script to convert image files to JPEG-XL or AVIF. Requires libjxl and libavif.

AVIF is an open image file format. After Microsoft Edge added support for AVIF, it now works across all major web browsers. AVIF image files usually have lower file sizes. So there’s no reason not to use it besides incovenience.

JPEG-XL is another competing alternative, which usually provides better image quality, but produce larger file sizes and is not supported by major web browsers.

This bash script provides a command-line menu for converting image files in the current directory to either JPEG-XL or AVIF. You can choose the conversion type and specify the encoding speed. The bash script supports images with jpg, jpeg, png, webp, and gif file extensions but you can add additional formats.

Requirements #

Bash script #

View in Gist

#!/usr/bin/env bash

# JAXA (JPEG-XL and AVIF Exchange Assistant) - User friendly bash script to convert image files to JPEG-XL or AVIF. Requires libjxl and libavif. 

# Add supported input image formats
IMAGE_FORMATS="jpg jpeg png webp gif"

show_menu() {
    echo "Select option:"
    echo "1. Convert to JXL"
    echo "2. Convert to AVIF"
    echo "3. Exit"
}

get_speed() {
    local default_speed
    local max_speed=10
    local max_effort=9
    if [ "$1" == "cjxl" ]; then
        default_speed=9
        echo "Enter speed for cjxl (1 is slowest, 9 is fastest, default is $default_speed):"
    elif [ "$1" == "avifenc" ]; then
        default_speed=10
        echo "Enter speed for avifenc (1 is slowest, 10 is fastest, default is $default_speed):"
    fi

    read -rp "Speed: " speed
    if [ -z "$speed" ]; then
        speed=$default_speed
    fi

    if [ "$1" == "cjxl" ]; then
        if [ "$speed" -lt 1 ] || [ "$speed" -gt $max_effort ]; then
            echo "Invalid speed. Setting to default speed $default_speed."
            speed=$default_speed
        fi
        speed=$(( $max_effort - $speed + 1 ))
    elif [ "$1" == "avifenc" ]; then
        if [ "$speed" -lt 1 ] || [ "$speed" -gt $max_speed ]; then
            echo "Invalid speed. Setting to default speed $default_speed."
            speed=$default_speed
        fi
    fi
}

while true; do
    show_menu
    read -rp "Option: " option

    case $option in
        1)
            get_speed cjxl
            echo "Running cjxl with effort $speed"
            for ext in $IMAGE_FORMATS; do
                for file in *.$ext; do
                    if [ -f "$file" ]; then
                        cjxl -e $speed "$file" "${file%.*}.jxl"
                        if [ $? -eq 0 ]; then
                            rm "$file"
                        else
                            echo "Failed to convert $file"
                        fi
                    fi
                done
            done
            echo "Conversion to JXL completed successfully."
            exit 0
            ;;
        2)
            get_speed avifenc
            echo "Running avifenc with speed $speed"
            for ext in $IMAGE_FORMATS; do
                for file in *.$ext; do
                    if [ -f "$file" ]; then
                        avifenc --speed $speed "$file" "${file%.*}.avif"
                        if [ $? -eq 0 ]; then
                            rm "$file"
                        else
                            echo "Failed to convert $file"
                        fi
                    fi
                done
            done
            echo "Conversion to AVIF completed successfully."
            exit 0
            ;;
        3)
            echo "Exit"
            exit 0
            ;;
        *)
            echo "Invalid option. Please choose 1, 2, or 3."
            ;;
    esac
done

I tested this for a collection of wallpapers with default speed and this is the result.

$ du -sh *
74M     jpg
51M     jpg-to-avif
69M     jpg-to-jxl
161M    png
35M     png-to-avif
68M     png-to-jxl