Created
January 21, 2024 10:46
-
-
Save kristofmulier/8ab75068b79acc793a7ec36f25cb335f to your computer and use it in GitHub Desktop.
Convert Images to webp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Copyright 2018-2023 Johan Cockx, Matic Kukovec and Kristof Mulier | |
''' | |
# NOTE: | |
# COMMAND TO CONVERT IMAGES IS | |
# cwebp {input_filename} -o {output_filename} | |
import os, sys, argparse, subprocess, math | |
q = "'" | |
size_db = {} | |
def show_help() -> None: | |
''' | |
Print help info and quit. | |
''' | |
print('Provide a folder to be converted.') | |
def convert_images(directory:str) -> None: | |
''' | |
Convert all images in the given directory. | |
''' | |
print(f'\nConvert all images in {q}{directory}{q}:') | |
print(f'{"-" * 61}') | |
for root, dirs, files in os.walk(directory): | |
for f in files: | |
if not f.endswith(('.png', '.jpg', '.jpeg')): | |
continue | |
filepath = os.path.join(root, f).replace('\\', '/') | |
convert(filepath) | |
continue | |
continue | |
print(f'{"-" * 61}') | |
# Print how much space has been freed | |
total_input_size = sum(s[0] for k,s in size_db.items()) | |
total_output_size = sum(s[1] for k,s in size_db.items()) | |
difference = total_input_size - total_output_size | |
print('') | |
print(f'Total size of original files: {convert_size(total_input_size)}') | |
print(f'Total size after conversion: {convert_size(total_output_size)}') | |
print(f'Difference: {convert_size(difference)}') | |
return | |
def delete_originals(directory:str) -> None: | |
''' | |
Delete the original .png, .jpg and .jpeg images | |
''' | |
if not yes_no('Delete original images?'): | |
return | |
print(f'{"-" * 42}') | |
for root, dirs, files in os.walk(directory): | |
for f in files: | |
if not f.endswith(('.png', '.jpg', '.jpeg')): | |
continue | |
filepath = os.path.join(root, f).replace('\\', '/') | |
os.remove(filepath) | |
print(f'| Delete: {f.ljust(30)} |') | |
continue | |
continue | |
print(f'{"-" * 42}') | |
return | |
def convert(input_filepath:str) -> None: | |
''' | |
Convert the given image and store it with the '.webp' extension. | |
''' | |
input_filepath = input_filepath.replace('\\', '/') | |
input_filename = input_filepath.split('/')[-1] | |
output_filename = input_filename\ | |
.replace('.png', '.webp')\ | |
.replace('.jpg', '.webp')\ | |
.replace('.jpeg', '.webp') | |
output_filepath = os.path.join( | |
os.path.dirname(input_filepath), | |
output_filename, | |
).replace('\\', '/') | |
cmd = f'cwebp {input_filename} -o {output_filename}' | |
result = subprocess.run( | |
cmd, | |
stdin = subprocess.DEVNULL, | |
stdout = subprocess.PIPE, | |
stderr = subprocess.PIPE, | |
cwd = os.path.dirname(input_filepath).replace('\\', '/'), | |
encoding = 'utf-8', | |
) | |
if result.returncode: | |
print(f'\nERROR: Cannot convert {input_filepath}\n') | |
sys.stdout.flush() | |
sys.exit(1) | |
input_size = os.path.getsize(input_filepath) | |
output_size = os.path.getsize(output_filepath) | |
size_db[input_filepath] = (input_size, output_size, input_size - output_size) | |
input_size_str = convert_size(input_size) | |
output_size_str = convert_size(output_size) | |
print(f'| {input_filename.ljust(30)} | {input_size_str.ljust(10)} -> {output_size_str.ljust(10)} |') | |
return | |
def convert_size(size_bytes:int) -> str: | |
''' | |
Format a size in bytes for pretty printing. | |
''' | |
if size_bytes == 0: | |
return '0B' | |
size_name = ('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB') | |
i = int(math.floor(math.log(size_bytes, 1024))) | |
p = math.pow(1024, i) | |
s = round(size_bytes / p, 2) | |
return f'{s} {size_name[i]}' | |
def yes_no(question:str) -> bool: | |
''' | |
Ask user a yes/no question | |
''' | |
check = str(input(f'{question} (Y/N): ')).lower().strip() | |
try: | |
if check[0] == 'y': | |
return True | |
elif check[0] == 'n': | |
return False | |
else: | |
print('Invalid Input') | |
return yes_no(question) | |
except Exception as error: | |
print('Please enter valid inputs') | |
print(error) | |
return yes_no(question) | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser( | |
description = 'Convert images to .webp format', | |
add_help = False, | |
) | |
parser.add_argument('-h', '--help', action='store_true') | |
parser.add_argument('-d', '--directory', action='store') | |
args = parser.parse_args() | |
if args.help: | |
show_help() | |
if args.directory is not None: | |
convert_images(args.directory) | |
delete_originals(args.directory) | |
print('\nQuit image converter tool\n') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment