Created
October 27, 2018 07:45
-
-
Save cceasy/65fa3930f81d1055893192d2b2c00966 to your computer and use it in GitHub Desktop.
batch resize images
This file contains 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
#!/usr/bin/env python | |
import os | |
from PIL import Image, ExifTags | |
from shutil import copyfile | |
orientation = 0x0112 # image exif info for Orientation 274 | |
device = 0x010f # image exif info for Make 271 | |
src_dir = 'todo' | |
thumbnail_config = { | |
'max_size': 50 * 1024, # 50 kB | |
'min_wh': 400, # 0 measn not to resize height or width | |
'min_quality': 20, # jpg quality | |
'quality_fall': 5, # quality will decrease per step | |
'bytes_quality': 220 * 1024, # every x byte get 1 quality decrease | |
'debug': True, | |
'output_dir': 'todo', | |
} | |
opt_config = { | |
'max_size': 2 * 1024 * 1024, # 2 MB | |
'min_wh': 1560, # 0 measn not to resize height or width | |
'min_quality': 75, # jpg quality | |
'quality_fall': 3, # quality will decrease per step | |
'bytes_quality': 1024 * 1024, # every x byte get 1 quality decrease | |
'debug': True, | |
'output_dir': 'todo', | |
} | |
# config = thumbnail_config | |
config = opt_config | |
def init_exif_keys(): | |
global orientation | |
global device | |
for key in ExifTags.TAGS.keys(): | |
if ExifTags.TAGS[key] == 'Orientation': | |
orientation = key | |
elif ExifTags.TAGS[key] == 'Make': | |
device = key | |
def resize(src_path, output_path): | |
max_size = config['max_size'] | |
min_wh = config['min_wh'] | |
min_quality = config['min_quality'] | |
quality_fall = config['quality_fall'] | |
bytes_quality = config['bytes_quality'] | |
debug = config['debug'] | |
if not os.path.exists(output_path): | |
os.mkdir(output_path) | |
files = list(os.listdir(src_path)) | |
print('⬇ resize and copy {} files from {} to {}'.format(len(files), src_path, output_path)) | |
for file in files: | |
if debug: | |
print('# process file', file) | |
src_file = os.path.join(src_path, file) | |
src_size = os.path.getsize(src_file) | |
if os.path.isdir(src_file): | |
continue | |
if src_file.endswith('DS_Store'): | |
os.remove(src_file) | |
continue | |
output_file = os.path.join(output_path, file) | |
img = Image.open(src_file) | |
img = process_exif(img) | |
if (src_size > max_size): | |
min_px = min(img.size) | |
if min_px > min_wh: | |
scale = min_px / float(min_wh) | |
w, h = int(img.width / scale), int(img.height / scale) | |
img = img.resize((w, h), Image.ANTIALIAS) | |
quality = int(100 - src_size / bytes_quality) | |
if quality < min_quality: | |
quality = min_quality | |
if debug: | |
print('init quality is', quality) | |
img.save(output_file, optimize=True, quality=quality) | |
while os.path.getsize(output_file) > max_size and quality > min_quality: | |
quality -= quality_fall | |
if debug: | |
print('+ adjust quality to', quality) | |
img.save(output_file, optimize=True, quality=quality) | |
img.close() | |
else: | |
copyfile(src_file, output_file) | |
return len(files) | |
def process_exif(image): | |
if hasattr(image, '_getexif') and isinstance(image._getexif(), dict): | |
exif = image._getexif() | |
# if device in exif and exif[device] == 'Apple': # Canon XiaoMi Apple | |
if orientation in exif: | |
if exif[orientation] == 3: | |
image = image.rotate(180, expand=True) | |
elif exif[orientation] == 6: | |
image = image.rotate(270, expand=True) | |
elif exif[orientation] == 8: | |
image = image.rotate(90, expand=True) | |
return image | |
if __name__ == '__main__': | |
init_exif_keys() | |
cnt = 0 | |
output_dir = config['output_dir'] | |
for file in os.listdir(src_dir): | |
src_path = os.path.join(src_dir, file) | |
if os.path.isdir(src_path): | |
output_path = os.path.join(output_dir, file) | |
cnt += resize(src_path, output_path) | |
print('cnt:', cnt) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment