Contents

Image Compression Tool

The cover image was generated by ChatGPT.

Introduction

When creating website pages, we sometimes notice that some pages take a while to load, while others do not. After comparing different webpages, the conclusion is that if the images on the webpage are too large, it causes slower page loading speeds. Therefore, the idea arose to find a tool that can compress all the images under the current website directory.

However, after searching extensively online, no suitable application was found. In the end, the decision was made to create a program that can compress all images.

Requirements

Before starting development, I confirmed the following requirements:

  • Ability to adjust the compression level of images.
  • Option to keep the original images in their original directory for easy reuse later.
  • Ability to skip unnecessary images or those that have already been compressed.
  • Ability to generate a compression report to confirm the amount of space saved.

The tool introduced here is built based on the above requirements encountered so far. This article does not delve into how to develop this tool but only introduces how to use it. If you have any suggestions or corrections for this tool, you are welcome to leave a comment.

Project Image Compression Tool

Image Compression Tool is a command-line image compression utility developed in Python. It supports compressing all images in a specified folder, automatically backs up the original images, skips images that were already compressed, and generates detailed compression reports (CSV files).

This project is developed in Python, mainly using the PIL module for image compression. Supported image formats include: .jpg, .jpeg, .png, .webp, .bmp, .tiff, .gif, .avif, .heic.

Among these, .png format compression is less efficient. In some cases, if the image cannot be compressed further or if the compression quality is set too low, the compressed file may end up larger than the original.

  • Language: Traditional Chinese / English
  • Version: v.1.0 / v.1140621
  • Last updated: June 21, 2025

Development Environment

Operating system environment as follows:

ItemDescription
Operating SystemWindows 11 24H2
PythonVersion 3.12.9

Modules used:

Modulepip package nameVersion
PILpillow11.0.0
tqdmtqdm4.67.1
yamlPyYAML6.0.2

Please install the above modules before use. You can use requirements.txt to install all at once:

1
pip install -r requirements.txt

Parameter Description

ParameterOptionDescriptionDefault
--pathRequiredSpecify the folder path to compressNone
--compress_qualityOptionalCompression quality, range 1-100. Lower value means higher compression but possibly more damage85
--backupOptionalWhether to backup original images (True or False)True
--backup_folderOptionalFolder name to store backup original imagesoriginal image
--original_suffixOptionalSuffix added to backup original image filenames_original
--skip_suffixOptionalImages with filenames containing this suffix will be skipped_skip
--skip_originalOptionalWhether to skip already backed up images (filenames containing original_suffix)True
--skip_skipOptionalWhether to skip images marked to skip (filenames containing skip_suffix)True
--print_image_reducedOptionalWhether to print compression results of each imageTrue
--print_summaryOptionalWhether to print compression summary reportTrue
--save_summary_to_csvOptionalWhether to save the compression summary as a CSV fileTrue
--summary_folderOptionalFolder to save the compression summary reportsummary
--summary_filenameOptionalFilename for the compression summary report (without extension)report
--configOptionalPath to YAML configuration fileconfig.yaml
--lang_codeOptionalLanguage code, e.g., zh-tw, enzh-tw
--versionOptionalDisplay program version info and exitNone
--aboutOptionalDisplay author, version, license, Email, GitHub infoNone
--authorOptionalDisplay author informationNone
--licenseOptionalDisplay license informationNone
--statusOptionalDisplay current status (defined by the program)None
--githubOptionalDisplay GitHub page linkNone
--helpOptionalShow help documentationNone

How to Use

  • Direct compression with default settings (specify folder)
1
python compress_images.py --path images/
  • Use config.yaml configuration file and suppress per-image compression output
1
python compress_images.py --config my_config.yaml --print_image_reduced False
  • Display author information
1
python compress_images.py --author
  • Display help documentation
1
python compress_images.py --help

Configuration

Modify default values

If you want to modify the default values in the config file or create a new config file, please copy or edit the /config.yaml file in the project root directory.

config.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
path: ""                        # Folder path to process images
compress_quality: 85            # Compression quality (1-100)
backup: true                    # Whether to backup original images
skip_original: true             # Whether to skip images already backed up
skip_skip: true                 # Whether to skip images marked with '_skip' in name
print_summary: true             # Whether to print the compression summary report
print_image_reduced: true       # Whether to print info of compressed images
save_summary_to_csv: true       # Whether to save summary report as CSV file
summary_folder: summary         # Folder name to save summary reports
summary_filename: report        # Summary report filename (without extension)
backup_folder: original image   # Folder name to store backup images
original_suffix: _original      # Suffix added to original images
skip_suffix: _skip              # Suffix for images to skip
lang_code: zh-tw                # Language code, e.g., 'zh-tw', 'en', etc.

Add a New Language File

To modify the default values of the language file or add a new language file, please copy or edit the /language/language.yaml file located in the project root directory.

en.yaml

 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
# language/en.yaml
general:
  ask_input_path: "Please enter the folder path of images to compress:"
  folder_not_found: "Folder not found. Please check the path again."
  missing_param: "Missing parameter `{key}`, using default: {default}"
  start_processing: "Found {count} images. Start processing..."
  processing: "Compressing"
  finished_processing: "Folder \"{folder}\" processing complete!"
  saved_report: "Compression report saved to: {path}"

status:
  compressed: "Compressed successfully"
  skipped: "Backed up, skipped"
  skip_keyword: "Skip"
  error_keyword: "Error"
  backup_error: "Backup error: {error}"
  compress_error: "Compression error: {error}"

report:
  header_summary: "Compression Summary:"
  header_ext_summary: "File Extension Statistics:"

  start_time: "Start time: {time}"
  end_time: "End time: {time}"
  elapsed: "Elapsed time: {elapsed}"
  avg_time: "Average processing time: {seconds:.2f} seconds"

  total_images: "Total images processed: {count}"
  compressed_success: "Successfully compressed: {count}"
  skipped_backup: "Backed up / Skipped: {count}"
  skipped_named: "Skipped due to name: {count}"
  error_unreadable: "Unreadable / Unsupported: {count}"
  error_failed: "Compression errors: {count}"

  no_avg_time: "No successful compression, unable to calculate average time"

  size_before: "Original size: {size:.2f} {unit}"
  size_after: "Compressed size: {size:.2f} {unit}"
  size_saved: "Space saved: {size:.2f} {unit} ({percent:.1f}%)"
  ext_format: "{ext:<6}: {count} images  Saved {savings:.2f} {unit} ({percent:.1f}%)"
  KB: "KB"
  MB: "MB"
  GB: "GB"

csv:
  section_general: "Compression Summary:"
  section_ext: "File Extension Statistics:"
  section_detail: "File Details:"

  fields:
    key: "Item"
    value: "Value"

    start_time: "Start Time"
    end_time: "End Time"
    elapsed: "Elapsed Time"
    avg_time: "Average Time (seconds)"
    avg_time_unavailable: "Average Time"
    avg_time_cannot_calculate: "Unable to calculate"

    total_images: "Total Images"
    compressed: "Successfully Compressed"
    skipped_backup: "Backed up / Skipped"
    skipped_named: "Skipped by Name"
    unreadable: "Unreadable / Unsupported"
    errors: "Compression Errors"

    size_before: "Original Size (MB)"
    size_after: "Compressed Size (MB)"
    size_saved: "Space Saved (MB)"
    size_percent: "Space Saved (%)"

    ext: "Extension"
    ext_count: "Image Count"
    ext_before: "Original Size (MB)"
    ext_after: "Compressed Size (MB)"
    ext_saved: "Space Saved (MB)"
    ext_percent: "Space Saved (%)"

    detail_path: "File Path"
    detail_ext: "Extension"
    detail_before: "Original Size (KB)"
    detail_after: "Compressed Size (KB)"
    detail_percent: "Space Saved (%)"
    detail_status: "Status"
    detail_time: "Processing Time"

License

MIT License

Copyright © 2025 Josh-test-lab

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Tip
The license terms are based on the version found in the GitHub repository.

Conclusion

This project was entirely a spontaneous idea. As an amateur programming enthusiast without any formal training, being able to write a fully functional tool from scratch is an exciting accomplishment for me. Although this tool is far from perfect and still requires rewriting and improvement in many areas, it genuinely solved a real problem I encountered in practice. This kind of “made-for-myself” mindset has given it special value.

At school, most of our training focuses on using rigorous logic for mathematical reasoning and statistical analysis. Through this hands-on experience, I realized that such logical thinking can be extended and applied to a wide range of fields. I believe I didn’t just write a script, I took the first step toward real-world practice. Translating what I’ve learned into something tangible through a keyboard has given me a sense of achievement. I hope this passion will continue, allowing me to explore the unknown, bridge disciplines, and create more fun and useful tools.

If you have any suggestions about this project, or if there are parts of the code that need to be corrected or rewritten, feel free to leave a comment.

See Also