Skip to content

Instantly share code, notes, and snippets.

@tigerhawkvok
Last active July 5, 2021 04:56
Show Gist options
  • Save tigerhawkvok/2d5ecd4a56235edc06ac8f96984fb5d6 to your computer and use it in GitHub Desktop.
Save tigerhawkvok/2d5ecd4a56235edc06ac8f96984fb5d6 to your computer and use it in GitHub Desktop.
Webify a directory of images
#!python3
"""
Opens all .jpg files in a folder and
downsamples them to maximum 1280 pixels wide
and quality level 75
"""
import glob
import os
import imghdr
from typing import Union
from skimage.io import imread, imsave
from skimage.transform import rescale
import numpy as np
IGNORE_OPTIMIZE_LIST = frozenset([
"logo.png",
"fps_pfe_4x6.png",
])
def _getImage(filePath) -> Union[np.ndarray, None]:
"""
Tidy file return.
Renames the file if the extension doesn't match
the filetype.
"""
try:
if os.path.basename(filePath) in IGNORE_OPTIMIZE_LIST:
return None
fileExtension = os.path.splitext(filePath)[1][1:]
what = imghdr.what(filePath)
filePathNew = None
if what == "jpeg" and fileExtension.lower() not in ("jpg", "jpeg"):
filePathNew = filePath.replace(f".{fileExtension}", ".jpg")
elif what is not None and fileExtension.lower() != what:
filePathNew = filePath.replace(f".{fileExtension}", f".{what}")
if filePathNew is not None:
# Rename the file with the corrected resolution
os.rename(filePath, filePathNew)
filePath = filePathNew
return imread(filePath).astype(np.uint8)
except Exception: #pylint: disable= broad-except
return None
def downscaleJPGs(relativeDir:str= "./", maxResolution:int= 1280):
"""
Opens all .jpg files in a folder and downscale them to
maxResolution
"""
for jpgFile in glob.glob(os.path.join(relativeDir, '*.jpg')):
img = _getImage(jpgFile)
if img is None:
continue
scale = maxResolution / max(img.shape[0], img.shape[1])
if scale >= 1:
print(f"{jpgFile} OK size")
continue
print(f"Checking {jpgFile}")
img = rescale(img, scale, anti_aliasing= True, preserve_range= True, multichannel= True).astype(np.uint8)
try:
imsave(jpgFile, img)
except Exception as e: #pylint: disable= broad-except
print(f">> Failed to convert {jpgFile} of shape {img.shape}: {e}")
def optimizePNGs(relativeDir:str= "./", maxResolution:int= 1280):
"""
Call this function to optimize all .png files in a folder
"""
validPNG = set()
for pngFile in glob.glob(os.path.join(relativeDir, '*.png')):
img = _getImage(pngFile)
if img is None:
continue
scale = maxResolution / max(img.shape[0], img.shape[1])
if scale >= 1:
print(f"{pngFile} OK size")
validPNG.update([pngFile])
continue
print(f"Resizing {pngFile}")
img = rescale(img, scale, anti_aliasing= True, preserve_range= True, multichannel= True).astype(np.uint8)
try:
imsave(pngFile, img)
validPNG.update([pngFile])
except Exception as e: #pylint: disable= broad-except
print(f">> Failed to convert {pngFile} of shape {img.shape}: {e}")
# Now call optiPNG locally to optimize the rescaled images
for pngFile in validPNG:
print(f"Optimizing {pngFile}")
cmd = f"optipng -o5 -v {pngFile}"
os.system(cmd)
if __name__ == "__main__":
TARGET_MAX_RESOLUTION_PX = 1280
downscaleJPGs(maxResolution= TARGET_MAX_RESOLUTION_PX)
optimizePNGs(maxResolution= TARGET_MAX_RESOLUTION_PX)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment