Introduction

Modern web development demands optimized images that load quickly while maintaining visual quality. The WebP format, developed by Google, offers superior compression compared to traditional JPEG and PNG formats, typically reducing file sizes by 25-35% without noticeable quality loss. This guide walks through converting images to WebP format and embedding copyright metadata using command-line tools on Ubuntu Linux.

Prerequisites

This tutorial assumes you’re running Ubuntu 22.04 LTS or newer with the following tools installed:

Step 1: Converting Images to WebP Format

The first step is converting your existing JPEG images to the WebP format using ImageMagick’s convert or mogrify commands.

Why WebP?

WebP provides several advantages over traditional image formats:

Basic Conversion Command

For converting a single file:

1
convert input.jpeg -quality 80 output.webp

The -quality parameter accepts values from 0-100, where higher values preserve more detail but result in larger files. A value of 80 provides an excellent balance between quality and file size.

Batch Conversion

To convert all JPEG files in a directory, use the mogrify command:

1
cd raw && mogrify -format webp -quality 80 -path ../new *.JPEG

This command:

For handling both uppercase and lowercase extensions:

1
cd raw && mogrify -format webp -quality 80 -path ../new *.{JPEG,jpeg}

After converting images to WebP, the next step is embedding copyright information into the file metadata. This protects your intellectual property and provides attribution information.

Installing the Latest ExifTool

Ubuntu 22.04’s default ExifTool version doesn’t support writing to WebP files. WebP write support was added in ExifTool version 12.46 (October 2022). To install the latest version from source, download Image-ExifTool-13.38.tar.gz or a newer version from https://exiftool.org/ and copy it to /tmp. Then issue the following commands.

1
2
3
4
5
cd /tmp
tar -xzf Image-ExifTool-12.96.tar.gz
cd Image-ExifTool-12.96
perl Makefile.PL
sudo make install

Verify the installation:

1
exiftool -ver

To add copyright metadata to your WebP files:

1
2
3
4
5
exiftool -overwrite_original \
  -Copyright="Copyright © 2025 Markus Werle" \
  -Artist="Markus Werle" \
  -CopyrightNotice="Copyright © 2025 Markus Werle" \
  assets/images/new/*.webp

This command sets three metadata fields:

The -overwrite_original flag prevents ExifTool from creating backup files (.webp_original).

Handling Minor Warnings

You may encounter warnings like "[minor] Incorrect XMP tag ID" for some images. These warnings indicate improperly formatted XMP metadata in the original files and don’t prevent the copyright information from being written successfully. To suppress these warnings, add the -m flag:

1
2
3
4
5
exiftool -m -overwrite_original \
  -Copyright="Copyright © 2025 Markus Werle" \
  -Artist="Markus Werle" \
  -CopyrightNotice="Copyright © 2025 Markus Werle" \
  assets/images/new/*.webp

The warning doesn’t affect the functionality of your images or prevent metadata from being written. If you still feel inclined to fixthe XMP Metadata, you can rewrite their XMP tags to correct the formatting:

1
exiftool -xmp:all= -tagsfromfile @ -xmp:all problematic_file.webp

This command removes all XMP tags and rewrites them cleanly, which resolves the “Incorrect XMP tag ID” warning.

Step 3: Automated Script

For repeated use, the following bash script automates the entire conversion and copyright embedding process.

The Complete Script: to_webp_with_copyright.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#!/bin/bash

# Script: to_webp_with_copyright.sh
# Description: Convert any image file to WebP format and add copyright metadata
# Author: Markus Werle
# Date: 2025-10-02

set -euo pipefail

# Constants
readonly SCRIPT_NAME="$(basename "$0")"
readonly REQUIRED_EXIFTOOL_VERSION="13.38"
readonly COPYRIGHT_TEXT="Copyright © 2025 Markus Werle"
readonly ARTIST="Markus Werle"

# Variables
INPUT_FILE=""
OUTPUT_FILE=""

# Function: Print usage information
usage() {
    cat << EOF
Usage: $SCRIPT_NAME -i|--input <input-file> -o|--output-file <output-file>

Convert any image file to WebP format and add copyright metadata.

Required arguments:
  -i, --input <file>        Input image file (any format supported by ImageMagick)
  -o, --output-file <file>  Output WebP file (will auto-append .webp if missing)

Optional arguments:
  -h, --help               Display this help message and exit

Examples:
  $SCRIPT_NAME -i photo.jpg -o photo.webp
  $SCRIPT_NAME --input image.png --output-file converted

Requirements:
  - ImageMagick (convert command)
  - exiftool version >= $REQUIRED_EXIFTOOL_VERSION

EOF
    exit 0
}

# Function: Print error message and exit
error_exit() {
    echo "Error: $1" >&2
    exit 1
}

# Function: Compare version numbers (semver compatible)
version_ge() {
    # Returns 0 (true) if $1 >= $2
    local ver1="$1"
    local ver2="$2"
    
    # Use sort -V to compare versions
    if [[ "$ver1" == "$ver2" ]]; then
        return 0
    fi
    
    local highest
    highest=$(echo -e "$ver1\n$ver2" | sort -V | tail -n 1)
    
    [[ "$ver1" == "$highest" ]]
}

# Function: Check if required commands exist
check_dependencies() {
    # Check for ImageMagick convert
    if ! command -v convert &> /dev/null; then
        error_exit "ImageMagick 'convert' command not found. Please install ImageMagick."
    fi
    
    # Check for exiftool
    if ! command -v exiftool &> /dev/null; then
        error_exit "exiftool not found. Please install exiftool version $REQUIRED_EXIFTOOL_VERSION or higher."
    fi
    
    # Check exiftool version
    local exiftool_version
    exiftool_version=$(exiftool -ver 2>/dev/null) || error_exit "Failed to determine exiftool version."
    
    if ! version_ge "$exiftool_version" "$REQUIRED_EXIFTOOL_VERSION"; then
        error_exit "exiftool version $exiftool_version is too old. Required: >= $REQUIRED_EXIFTOOL_VERSION"
    fi
    
    echo "Dependencies check passed: exiftool v$exiftool_version" >&2
}

# Function: Validate input file
validate_input() {
    local file="$1"
    
    if [[ -z "$file" ]]; then
        error_exit "Input file not specified. Use -i or --input option."
    fi
    
    if [[ ! -f "$file" ]]; then
        error_exit "Input file does not exist: $file"
    fi
    
    if [[ ! -r "$file" ]]; then
        error_exit "Input file is not readable: $file"
    fi
    
    # Check if ImageMagick can identify the file
    if ! identify "$file" &> /dev/null; then
        error_exit "Input file is not a valid image format: $file"
    fi
}

# Function: Prepare output filename
prepare_output_filename() {
    local output="$1"
    
    if [[ -z "$output" ]]; then
        error_exit "Output file not specified. Use -o or --output-file option."
    fi
    
    # Add .webp extension if not present
    if [[ "$output" != *.webp ]]; then
        output="${output}.webp"
        echo "Auto-appending .webp extension: $output" >&2
    fi
    
    # Check if output directory exists
    local output_dir
    output_dir=$(dirname "$output")
    
    if [[ ! -d "$output_dir" ]]; then
        error_exit "Output directory does not exist: $output_dir"
    fi
    
    if [[ ! -w "$output_dir" ]]; then
        error_exit "Output directory is not writable: $output_dir"
    fi
    
    echo "$output"
}

# Function: Convert image to WebP
convert_to_webp() {
    local input="$1"
    local output="$2"
    
    echo "Converting $input to WebP format..." >&2
    
    if ! convert "$input" -quality 90 "$output" 2>/dev/null; then
        error_exit "Failed to convert image to WebP format."
    fi
    
    if [[ ! -f "$output" ]]; then
        error_exit "Conversion completed but output file not found: $output"
    fi
    
    echo "Conversion successful: $output" >&2
}

# Function: Add copyright metadata
add_copyright_metadata() {
    local file="$1"
    
    echo "Adding copyright metadata..." >&2
    
    if ! exiftool -m -overwrite_original \
        -Copyright="$COPYRIGHT_TEXT" \
        -Artist="$ARTIST" \
        -CopyrightNotice="$COPYRIGHT_TEXT" \
        "$file" > /dev/null 2>&1; then
        error_exit "Failed to add copyright metadata to: $file"
    fi
    
    echo "Copyright metadata added successfully." >&2
}

# Function: Parse command line arguments
parse_arguments() {
    if [[ $# -eq 0 ]]; then
        usage
    fi
    
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -h|--help)
                usage
                ;;
            -i|--input)
                if [[ -n "${2:-}" ]] && [[ "${2:0:1}" != "-" ]]; then
                    INPUT_FILE="$2"
                    shift 2
                else
                    error_exit "Option $1 requires an argument."
                fi
                ;;
            -o|--output-file)
                if [[ -n "${2:-}" ]] && [[ "${2:0:1}" != "-" ]]; then
                    OUTPUT_FILE="$2"
                    shift 2
                else
                    error_exit "Option $1 requires an argument."
                fi
                ;;
            *)
                error_exit "Unknown option: $1. Use -h or --help for usage information."
                ;;
        esac
    done
    
    # Validate that required arguments are provided
    if [[ -z "$INPUT_FILE" ]]; then
        error_exit "Missing required option: -i|--input. Use -h for help."
    fi
    
    if [[ -z "$OUTPUT_FILE" ]]; then
        error_exit "Missing required option: -o|--output-file. Use -h for help."
    fi
}

# Main execution
main() {
    # Parse command line arguments
    parse_arguments "$@"
    
    # Check dependencies
    check_dependencies
    
    # Validate input file
    validate_input "$INPUT_FILE"
    
    # Prepare output filename
    OUTPUT_FILE=$(prepare_output_filename "$OUTPUT_FILE")
    
    # Convert to WebP
    convert_to_webp "$INPUT_FILE" "$OUTPUT_FILE"
    
    # Add copyright metadata
    add_copyright_metadata "$OUTPUT_FILE"
    
    echo "✓ Successfully created: $OUTPUT_FILE" >&2
    exit 0
}

# Run main function with all arguments
main "$@"

Script Features

The script performs several tasks:

Argument Parsing: Supports both short (-i, -o, -h) and long options (--input, --output-file, --help) with comprehensive validation.

Version Checking: Automatically verifies that ExifTool version 13.38 or higher is installed using semantic version comparison with the sort -V method.

Comprehensive Error Handling: Validates all potential failure points including:

Automatic File Extension: If the output filename doesn’t end with .webp, the script automatically appends the extension.

Usage Examples

Make the script executable:

1
chmod +x to_webp_with_copyright.sh

Convert a single image:

1
./to_webp_with_copyright.sh -i photo.JPEG -o photo.webp

The script automatically appends .webp if omitted:

1
2
./to_webp_with_copyright.sh --input image.png --output-file converted
# Creates: converted.webp

Display help information:

1
./to_webp_with_copyright.sh --help

Verification

To verify that the copyright metadata was successfully embedded, use ExifTool to inspect the output file:

1
exiftool -Copyright -Artist -CopyrightNotice photo.webp

This displays the three copyright-related metadata fields you added.