blob: d66d4cba0e530ce5901de04db4ee89d1508bbe62 [file] [log] [blame]
#!/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()