Exemplo n.º 1
0
def main(show=False, test=""):
    start_time = time.time()

    doc = loads(open(
        os.path.join(get_project_root(), 'config', 'covers.toml'), ).read())

    output_size = (doc['config']['output-size'], doc['config']['output-size'])

    logo_size = get_logo_size(output_size)
    padded_logo_location = get_logo_location(output_size)

    w_base = resize_and_fade_logo(get_white_logo(), logo_size, output_size, padded_logo_location, logo_transparency_percentage)
    b_base = resize_and_fade_logo(get_black_logo(), logo_size, output_size, padded_logo_location, logo_transparency_percentage)

    if test != "":
        test_image = get_test_image(output_size, test)
    else:
        test_image = None

    for cover in doc['cover']:
        try:
            cover_image = get_cover_image(cover)

            # Add alpha channel so mode matches images with transparency,
            # allowing us to use alpha_composite
            if cover_image.mode == 'RGB':
                cover_image.putalpha(255)

            # If scale defined, resize cover to scaled size, using pad to
            # avoid any cropping, otherwise scale to output size to fit
            if cover.get('scale'):
                cover_image = scale_and_pad_cover(cover_image, output_size, cover.get('scale'), cover.get('position'))
            else:
                cover_image = ImageOps.fit(
                    cover_image, output_size, Image.ANTIALIAS)

            # If a background colour is defined, create a new image with
            # that colour, and composite the cover onto it.
            if cover.get('bg-colour'):
                base = Image.new('RGBA', output_size, cover.get('bg-colour'))
                cover_image = Image.alpha_composite(base, cover_image)

            if cover.get('colour-gradient'):
                if not cover.get('do-not-greyscale', False):
                    cover_image = cover_image.convert('L').convert('RGBA')
                gradient_image = ImageOps.fit(get_gradient(cover.get('colour-gradient')), output_size, Image.ANTIALIAS)
                gradient_image.putalpha(255)
                opacity = cover.get('gradient-opacity', 70)/100
                cover_image = Image.blend(cover_image, gradient_image, opacity)

            # Composite the logo watermark on top, black logo as default
            if cover.get('use-white-logo'):
                if cover.get('logo-opacity'):
                    cover_image = Image.alpha_composite(cover_image,
                        resize_and_fade_logo(get_white_logo(), logo_size, output_size, padded_logo_location, cover.get('logo-opacity')))
                else:
                    cover_image = Image.alpha_composite(cover_image, w_base)
            else:
                if cover.get('logo-opacity'):
                    cover_image = Image.alpha_composite(cover_image,
                        resize_and_fade_logo(get_black_logo(), logo_size, output_size, padded_logo_location, cover.get('logo-opacity')))
                else:
                    cover_image = Image.alpha_composite(cover_image, b_base)

            # Write text
            if cover.get('main-text'):
                size = 1
                font = ImageFont.truetype('CircularStd-Bold.otf', size)
                max_area = get_text_area(output_size)
                max_height = get_text_height(output_size)
                main_text_line = cover.get('main-text')
                # Calculate maximum font size. Increase size until width of text exceeds defined max area,
                # or height of an example text with no dangling letters, e.g. "Genre Glitch", at that size
                # exceeds defined maximum.
                draw = ImageDraw.Draw(cover_image)
                while (draw.textsize(main_text_line, font)[0] < max_area and draw.textsize(text_height_example_string, font)[1] < max_height):
                    size += 1
                    font = ImageFont.truetype('CircularStd-Bold.otf', size)
                # Put in a variable so sub-text can use to calculate area already covered
                main_text_size = draw.textsize(main_text_line, font)
                if cover.get('centre-text'):
                    text_location = calculate_centred_font_location(output_size, font, main_text_line, draw)
                else:
                    text_location = calculate_font_location(output_size, font, main_text_line, draw)
                draw.text(text_location, main_text_line, cover.get('font-colour', 'white'), font, align="center")

            if cover.get('sub-text'):
                size = 1
                font = ImageFont.truetype('CircularStd-Bold.otf', size)
                max_area = get_text_area(output_size)
                max_height = get_sub_text_height(output_size)
                main_text_line = cover.get('sub-text')
                # Calculate maximum font size. Increase size until width of text exceeds defined max area,
                # or height of an example text with no dangling letters, e.g. "Genre Glitch", at that size
                # exceeds defined maximum.
                draw = ImageDraw.Draw(cover_image)
                while (draw.textsize(main_text_line, font)[0] < max_area and draw.textsize(text_height_example_string, font)[1] < max_height):
                    size += 1
                    font = ImageFont.truetype('CircularStd-Bold.otf', size)
                if cover.get('sub-text-above'):
                    main_start = text_location[1]
                    sub_text_location = (int(output_size[0]/2 - draw.textsize(main_text_line, font)[0]/2), main_start - get_padding_height(output_size) - draw.textsize(text_height_example_string, font)[1])
                else:
                    main_end = text_location[1] + main_text_size[1]
                    sub_text_location = (int(output_size[0]/2 - draw.textsize(main_text_line, font)[0]/2), get_padding_height(output_size) + main_end)

                draw.text(sub_text_location, main_text_line, cover.get('sub-font-colour', 'white'), font, align="center")

        except IOError:
            print("Unable to load image")
            sys.exit(1)

        if show:
            cover_image.show()
        else:
            if not os.path.exists(os.path.join(get_project_root(), 'images', 'covers')):
                os.makedirs(os.path.join(get_project_root(), 'images', 'covers'))

            # Ensure unique filenames by first trying to append config strings, then appending numbers if the file still exists already
            parts = [cover.get('main-text'), cover.get('sub-text'), cover.get('bg-image'), cover.get('colour-gradient')]
            parts = [i for i in parts if i is not None]
            i = 0
            file_name = ""
            while i < len(parts):
                file_name += parts[i]
                file_path = os.path.join(get_project_root(), 'images', 'covers', sanitize_filename(file_name + ".jpg"))
                if os.path.exists(file_path) and os.path.getmtime(file_path) > start_time:
                    i += 1
                    file_name += "_"
                else:
                    break
            else:
                x = 0
                while os.path.exists(file_path) and os.path.getmtime(file_path) > start_time:
                    x += 1
                    file_path = os.path.join(get_project_root(), 'images', 'covers', sanitize_filename(file_name + str(x) + ".jpg"))

            cover_image.convert("RGB").save(file_path, quality=95)

        if test_image is not None:
            Image.blend(cover_image, test_image, 0.65).show()
Exemplo n.º 2
0
def get_cover_image(cover):
    return Image.open(os.path.join(get_project_root(), 'images', cover['bg-image']))
Exemplo n.º 3
0
def get_gradient(gradient_name):
    return Image.open(os.path.join(get_project_root(), 'images', 'gradient', gradient_name + '.jpg'))
Exemplo n.º 4
0
def get_black_logo():
    return Image.open(os.path.join(get_project_root(), 'images', 'logo', 'Spotify_Icon_RGB_Black.png'))
Exemplo n.º 5
0
def get_white_logo():
    return Image.open(os.path.join(get_project_root(), 'images', 'logo', 'Spotify_Icon_RGB_White.png'))
Exemplo n.º 6
0
def get_test_image_3():
    return Image.open(os.path.join(get_project_root(), 'images', 'test', 'test_3.jpg'))