# -*- coding: utf-8 -*- # # Compare desktop/mobile shots of all themes from publik-base-theme. # # Usage: # --input1-directory -- directory to find version 1 screenshots # --input2-directory -- directory to find version 2 screenshots # --output-directory DIRECTORY -- directory to store comparison results, defaults to results/ # --overlay OVERLAY -- limit to given overlay ("none" to exclude overlays) # --theme THEME -- theme to shot (substring match) # # Example: # hobo-manage tenant_command runscript compare_them_all.py -d hobo.fred.local.0d.be # import argparse import os import sys from hobo.theme.utils import get_themes from django.template import Template, Context from PIL import Image, ImageDraw parser = argparse.ArgumentParser() parser.add_argument('--input1-directory', dest='input1_directory', type=str, required=True) parser.add_argument('--input2-directory', dest='input2_directory', type=str, required=True) parser.add_argument('--output-directory', dest='output_directory', type=str, default='results') parser.add_argument('--overlay', dest='overlay', type=str, default='none') parser.add_argument('--theme', dest='theme', type=str) args = parser.parse_args() if not os.path.exists(args.output_directory): os.mkdir(args.output_directory) result = [] for theme in get_themes(): theme_id = theme['id'] if args.overlay == 'all': pass elif args.overlay == 'none' and not theme.get('overlay'): pass elif args.overlay == theme.get('overlay'): pass else: continue if args.theme and args.theme not in theme['id']: continue sys.stderr.write("%-25s" % theme_id) shots = [ 'desktop', 'mobile', 'mobile-horizontal', ] def process_region(image, x, y, width, height): region_total = 0 # This can be used as the sensitivity factor, the larger it is the less sensitive the comparison factor = 100 for coordinate_y in range(y, y + height): for coordinate_x in range(x, x + width): try: pixel = image.getpixel((coordinate_x, coordinate_y)) region_total += sum(pixel) / 4 except Exception: return return region_total / factor theme_data = { 'label': theme['label'], 'shots': [], } for shot in shots: filepath_1 = os.path.join(args.input1_directory, '%s-%s.png' % (theme_id, shot)) filepath_2 = os.path.join(args.input2_directory, '%s-%s.png' % (theme_id, shot)) filepath_output = os.path.join(args.output_directory, '%s-%s.png' % (theme_id, shot)) try: screenshot_1 = Image.open(filepath_1) screenshot_2 = Image.open(filepath_2) except FileNotFoundError: continue width, height = screenshot_1.size columns = 60 rows = 80 screen_width, screen_height = screenshot_1.size block_width = ((screen_width - 1) // columns) + 1 block_height = ((screen_height - 1) // rows) + 1 for y in range(0, screen_height, block_height + 1): for x in range(0, screen_width, block_width + 1): region_1 = process_region(screenshot_1, x, y, block_width, block_height) region_2 = process_region(screenshot_2, x, y, block_width, block_height) if region_1 is not None and region_2 is not None and region_1 != region_2: draw = ImageDraw.Draw(screenshot_1) draw.rectangle((x, y, x + block_width, y + block_height), outline="red") screenshot_1.save(filepath_output) theme_data['shots'].append({ 'label': shot, 'width': width, 'height': height, 'before': '../%s' % filepath_1, 'after': '../%s' % filepath_2, 'diff': '../%s' % filepath_output, }) result.append(theme_data) sys.stderr.write(u'\n') with open('index_template.html', 'r') as f: template = Template(f.read()) context = Context({'themes': result}) html = template.render(context) with open(os.path.join(args.output_directory, 'index.html'), 'w') as f: f.write(html)