| #!/usr/bin/env python |
| # |
| # Copyright 2013 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """This script generates a PNG file according to the specified text message and |
| attributes. |
| |
| The attributes are saved as a text chunk in the PNG file. If we are |
| overwriting an existing PNG file and the attributes are the same as that used |
| to generate the existing PNG file, we just skip this file. |
| """ |
| |
| |
| import argparse |
| import os |
| import sys |
| |
| import cairo |
| import pango # pylint: disable=import-error |
| import pangocairo # pylint: disable=import-error |
| from PIL import Image |
| from PIL import PngImagePlugin |
| import yaml |
| |
| |
| def WriteAttrData(img_path, attr): |
| i = Image.open(img_path) |
| meta = PngImagePlugin.PngInfo() |
| meta.add_text('text_attr', yaml.dump(attr).encode('UTF-8')) |
| i.save(img_path, 'png', pnginfo=meta) |
| |
| |
| def GetAttrData(img_path): |
| try: |
| i = Image.open(img_path) |
| return yaml.load(i.info['text_attr'].decode('UTF-8')) |
| except Exception: |
| return None |
| |
| |
| def CheckDuplicate(attr, img_path): |
| if not os.path.exists(img_path): |
| return False |
| return GetAttrData(img_path) == attr |
| |
| |
| def GetFont(attr): |
| FONT = 'sans-serif, %dpx' |
| return pango.FontDescription(FONT % attr['font_size']) |
| |
| |
| def ColorTriplet(color): |
| if color[0] == '#': |
| color = color[1:] |
| assert len(color) == 6 |
| return (int(color[0:2], 16), |
| int(color[2:4], 16), |
| int(color[4:6], 16)) |
| |
| |
| def FillInDefaultAttr(attr): |
| attr.setdefault('bg_color', '#000000') |
| attr.setdefault('fg_color', '#ffffff') |
| attr.setdefault('font_size', 20) |
| |
| |
| def GetTextLayout(pangocontext, attr): |
| layout = pangocontext.create_layout() |
| font = GetFont(attr) |
| layout.set_font_description(font) |
| layout.set_text(attr['text']) |
| return layout |
| |
| |
| def GetTextSize(attr): |
| surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1000, 1000) |
| pangocontext = pangocairo.CairoContext(cairo.Context(surface)) |
| return GetTextLayout(pangocontext, attr).get_pixel_size() |
| |
| |
| def CreateMessageImage(attr): |
| FillInDefaultAttr(attr) |
| img_path = attr['image'] |
| if CheckDuplicate(attr, img_path): |
| sys.stdout.write('%s is up-to-date. Skipping.\n' % img_path) |
| return |
| |
| w, h = GetTextSize(attr) |
| |
| surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) |
| context = cairo.Context(surface) |
| |
| context.rectangle(0, 0, w, h) |
| context.set_source_rgb(*ColorTriplet(attr['bg_color'])) |
| context.fill() |
| |
| pangocontext = pangocairo.CairoContext(context) |
| layout = GetTextLayout(pangocontext, attr) |
| context.set_source_rgb(*ColorTriplet(attr['fg_color'])) |
| pangocontext.update_layout(layout) |
| pangocontext.show_layout(layout) |
| |
| with open(img_path, 'w') as image_output: |
| surface.write_to_png(image_output) |
| WriteAttrData(img_path, attr) |
| |
| sys.stdout.write('Generated %s.\n' % img_path) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| description='Make text image.') |
| parser.add_argument('--input_file', '-i', |
| help='Yaml file with the following field:\n' |
| ' text - The text to draw\n' |
| ' font_size - The size of text\n' |
| ' fg_color - Foreground color\n' |
| ' bg_color - Background color\n' |
| 'If an input file is specified, other arguments\n' |
| 'are ignored.', |
| required=False) |
| parser.add_argument('--output', '-o', help='Output image file name', |
| required=False) |
| parser.add_argument('--text', '-t', help='Text to draw', required=False) |
| parser.add_argument('--fg_color', '-f', help='Foreground color', |
| default='#ffffff', required=False) |
| parser.add_argument('--bg_color', '-b', help='Background color', |
| default='#000000', required=False) |
| parser.add_argument('--font_size', '-s', help='Font size in px', |
| type=int, default=20, required=False) |
| args = parser.parse_args() |
| |
| if args.input_file: |
| attrs = yaml.load(open(args.input_file, 'r').read()) |
| elif args.text and args.output: |
| attrs = [{'image': args.output, 'text': args.text}] |
| for k in ['fg_color', 'bg_color', 'font_size']: |
| if args.__dict__[k]: |
| attrs[0][k] = args.__dict__[k] |
| else: |
| sys.stderr.write(parser.format_usage()) |
| sys.exit(1) |
| |
| for attr in attrs: |
| attr['text'] = attr['text'].replace('\\n', '\n') |
| CreateMessageImage(attr) |
| |
| if __name__ == '__main__': |
| main() |