Skip to content

Instantly share code, notes, and snippets.

@Maxty99
Created August 11, 2021 08:15
Show Gist options
  • Save Maxty99/e8d3d46233d05c1094ea8232a966fa79 to your computer and use it in GitHub Desktop.
Save Maxty99/e8d3d46233d05c1094ea8232a966fa79 to your computer and use it in GitHub Desktop.
Quick python script for converting a buncha random image formats to one. No extensive debugging but should work
import os
import shutil
import tempfile
import logging
from PIL import Image
import concurrent.futures
from math import ceil
import sys
SUPPORTED_EXT = [
"JPG",
"JPEG",
"PNG",
"GIF",
"BMP",
"PPM"
]
def verifyArgs(args: list[str]):
# First part of argv is the executed script so I work with args[1:]
# because I dont care about the scripts name
#
# I dont know why I would but I could change this in the future
if args[1:] == []:
print("Arguments cannot be empty")
return False
for arg in args[1:]:
if arg.upper() not in SUPPORTED_EXT:
print(f"Format {arg} not supported")
return False
return True
if __name__ == "__main__" and verifyArgs(sys.argv):
NUM_OF_THREADS = 8
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S", filename='log.log')
directory = os.getcwd()
files = []
logging.debug(f"Started with args: {sys.argv}")
for file in os.listdir(directory):
filename = os.fsdecode(file)
# Horrible syntax makes this hard to read but essentially
# I take the final string after a dot in a filnameand check
# if its part of the supplied arguments
if file.split(".")[-1].upper() in sys.argv[2:]:
files.append(filename)
groupSize = ceil(len(files) / NUM_OF_THREADS)
threads = []
def threadFunc(name: str, files: list[str]):
try:
with tempfile.TemporaryDirectory() as tmpdirname:
for filename in files:
# Open image handle
img = Image.open(filename)
logging.info(f"Workign on file {filename}: {name}")
# Prepare paths to move image around
ext = filename.split(".")[-1]
if sys.argv[1].upper() == "JPG":
newExt = "JPEG"
img = img.convert("RGB")
else:
newExt = sys.argv[1]
newFileName = filename.replace(ext, newExt.lower())
tmpFilePath = os.path.join(tmpdirname, newFileName)
newFilePath = os.path.join(directory, newFileName)
logging.debug(f"New file name: {newFileName}")
logging.debug(f"Tmp file path: {tmpFilePath}")
logging.debug(f"New file path: {newFilePath}")
# Save the image
img.save(tmpFilePath, newExt)
os.remove(filename)
shutil.move(tmpFilePath, newFilePath)
logging.info(f"Finished with file {filename}: {name}")
logging.info(f"Finished thread {name}")
except Exception:
logging.info("oops something happened, take a look...")
logging.exception(Exception)
# The multithreading aspect
with concurrent.futures.ThreadPoolExecutor(max_workers=NUM_OF_THREADS) as executor:
for threadNum in range(NUM_OF_THREADS):
# Last group might not be full
if threadNum == NUM_OF_THREADS - 1:
logging.info(f"Thread responsible for files {files[threadNum*groupSize:]} to the end")
executor.submit(threadFunc, str(threadNum + 1), files[threadNum*groupSize:])
else:
logging.info(f"Thread responsible for files {files[threadNum*groupSize:(threadNum+1)*groupSize]}")
executor.submit(threadFunc, str(threadNum + 1), files[threadNum*groupSize:(threadNum+1)*groupSize])
logging.info(f"Added thread {threadNum + 1}")
else:
print("""
Usage : script.py formatToConvertTo formatToConvertFrom ...
To use this script you must pass the format you want to convert
as the first argument without the dot before it(PNG, JPG). Then list
the formats you are trying to convert from.
""")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment