118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
|
'''
|
||
|
Icon generator
|
||
|
==============
|
||
|
|
||
|
This tool will help you to generate all the icons wanted for Google Play Store,
|
||
|
App Store, Amazon store.
|
||
|
'''
|
||
|
|
||
|
import sys
|
||
|
from PIL import Image
|
||
|
from os.path import exists, join, realpath, basename, dirname
|
||
|
from os import makedirs
|
||
|
from argparse import ArgumentParser
|
||
|
|
||
|
|
||
|
class Converter(object):
|
||
|
|
||
|
converters = {
|
||
|
'appstore': {
|
||
|
'directory_name': 'ios',
|
||
|
'sizes': [
|
||
|
('App store high resolution', '{}-appstore-1024.png', 1024),
|
||
|
('App store normal resolution', '{}-appstore-512.png', 512),
|
||
|
# iOS 7
|
||
|
('iPhone (iOS 7)', '{}-60.png', 120),
|
||
|
('iPhone @2 (iOS 7)', '{}-60@2x.png', 120),
|
||
|
('iPad (iOS 7)', '{}-76.png', 76),
|
||
|
('iPad @2 (iOS 7)', '{}-60@2x.png', 152),
|
||
|
# iOS 6.1 and earlier
|
||
|
('iPhone (iOS >= 6.1)', '{}-57.png', 57),
|
||
|
('iPhone @2 (iOS >= 6.1)', '{}-57@2x.png', 114),
|
||
|
('iPad (iOS >= 6.1)', '{}-72.png', 72),
|
||
|
('iPad @2 (iOS >= 6.1)', '{}-72@2x.png', 114),
|
||
|
# iTunes artwork (ad-hoc)
|
||
|
('iTunes Artwork (ad-hoc)', 'iTunesArtwork', 512),
|
||
|
('iTunes Artwork @2 (ad-hoc)', 'iTunesArtwork@2x', 1024),
|
||
|
]},
|
||
|
'playstore': {
|
||
|
'directory_name': 'android',
|
||
|
'sizes': [
|
||
|
('Google Play icon', '{}-googleplay-512.png', 512),
|
||
|
('Launcher icon MDPI', '{}-48.png', 48),
|
||
|
('Launcher icon HDPI', '{}-72.png', 72),
|
||
|
('Launcher icon XHDPI', '{}-96.png', 96),
|
||
|
('Launcher icon XXHDPI', '{}-144.png', 48),
|
||
|
('Launcher icon XXXHDPI', '{}-192.png', 192),
|
||
|
]},
|
||
|
'amazonstore': {
|
||
|
'directory_name': 'amazon',
|
||
|
'sizes': [
|
||
|
('Small icon', '{}-114.png', 114),
|
||
|
('Large icon', '{}-512.png', 512),
|
||
|
]}}
|
||
|
|
||
|
def run(self):
|
||
|
parser = ArgumentParser(
|
||
|
description='Generate icons for various stores')
|
||
|
parser.add_argument('--dir', type=str, default=None,
|
||
|
help=('Output directory to generate all the icons,'
|
||
|
'defaults to the directory of the source icon'))
|
||
|
parser.add_argument('--force', type=bool, default=False,
|
||
|
help=('Generate all icons even if the source is not perfect.'))
|
||
|
parser.add_argument('icon', type=str,
|
||
|
help='Base icon (must be 1024x1024 or 512x512)')
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
if not exists(args.icon):
|
||
|
print('Error: No such icon file')
|
||
|
sys.exit(1)
|
||
|
|
||
|
# ensure the destination directory will be set
|
||
|
if args.dir is None:
|
||
|
args.dir = dirname(args.icon)
|
||
|
|
||
|
# read the source image, and do some quality checks
|
||
|
base_fn = basename(args.icon).rsplit('.', 1)[0]
|
||
|
source = Image.open(args.icon)
|
||
|
self.ensure_quality(source, args.force)
|
||
|
|
||
|
for directory_name, sizeinfo in self.iterate():
|
||
|
description, pattern_fn, size = sizeinfo
|
||
|
print('Generate {}: {}x{}'.format(description, size, size))
|
||
|
dest_dir = realpath(join(args.dir, directory_name))
|
||
|
if not exists(dest_dir):
|
||
|
makedirs(dest_dir)
|
||
|
icon_fn = join(dest_dir, pattern_fn.format('Icon'))
|
||
|
self.convert_to(source, icon_fn, size)
|
||
|
|
||
|
def convert_to(self, source, icon_fn, size):
|
||
|
dest = source.resize((size, size))
|
||
|
dest.save(icon_fn, 'png')
|
||
|
|
||
|
def ensure_quality(self, image, force=False):
|
||
|
messages = []
|
||
|
w, h = image.size
|
||
|
if w != h:
|
||
|
messages.append('Width and height should be the same')
|
||
|
if w not in (512, 1024):
|
||
|
messages.append(
|
||
|
'Source image is recommended to be 1024 (512 minimum)')
|
||
|
if not messages:
|
||
|
return
|
||
|
|
||
|
print('Quality check failed')
|
||
|
for message in messages:
|
||
|
print('- {}'.format(message))
|
||
|
if not force:
|
||
|
sys.exit(1)
|
||
|
|
||
|
def iterate(self):
|
||
|
for store, infos in Converter.converters.items():
|
||
|
for size in infos['sizes']:
|
||
|
yield infos['directory_name'], size
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
Converter().run()
|