#!/usr/bin/env python # -*- coding: utf-8 -*- # -*- mode: python;Encoding: utf8n -*- #------------------------------------------------------------------------------- # Name: make_analog_watch_image.py # Purpose: アナログ時計盤の画像を作成 # PyCairoが必要 # Windows7 x64 + Python 2.6.6 + PyCairo で動作確認 # Author: mieki256 # Created: 2012/01/23 # Copyright: (c) mieki256 2012 # Licence: NYSL #------------------------------------------------------------------------------- import cairo import math import os import subprocess # 出力画像ファイル名 outfilename = "watch_base.png" # 画像サイズ # w,h = 640*2,480*2 w,h = 480*2,480*2 # FPS fps = 24 # 数字の描画 Trueなら描画する/Falseなら描画しない draw_number_enable = True # Trueにすると画像ファイルと関連付けされたアプリで開く # dbg = True dbg = False def draw_watch(cr, cx, cy, r): """時計盤を描画する. cx,cy は中心点の座標 r は半径 """ # 円や目盛の位置(半径に対する割合) rd = [0.97, 0.90, 0.87, 0.84, 0.82] # 数字の表示位置決め用 rdnum = [0.80, 0.76, 0.66] # 小さい数字用, 大きい数字用, 大きい数字の横用 # 目盛の色の濃さ lv = [0.0, 0.0, 0.0, 0.0] # 線の太さ wd = 1 # 円を描画 c = 0.0 # 線の明度(黒~白を、0.0~1.0で指定) cr.set_source_rgb(c, c, c) cr.set_line_width(wd) cr.arc( cx, cy, r * rd[0], 0, 2 * math.pi) cr.arc( cx, cy, r * rd[1], 0, 2 * math.pi) cr.arc( cx, cy, r * rd[2], 0, 2 * math.pi) cr.stroke() # 目盛の線を描画 for i in xrange(6 * fps): ang = math.radians((360.0 * i / (6 * fps)) - 90.0) x0 = (r * rd[0]) * math.cos(ang) + cx y0 = (r * rd[0]) * math.sin(ang) + cy if (i % fps) == 0: rr = r * rd[4] c = lv[3] # 線の明度 l = wd * 3.0 # 線の太さ elif (i % (fps / 4)) == 0: rr = r * rd[3] c = lv[2] l = wd elif (i % (fps / 8)) == 0: rr = r * rd[2] c = lv[1] l = wd else: rr = r * rd[1] c = lv[0] l = wd x1 = rr * math.cos(ang) + cx y1 = rr * math.sin(ang) + cy cr.set_source_rgb(c, c, c) cr.set_line_width(l) cr.move_to(x0,y0) cr.line_to(x1,y1) cr.stroke() if draw_number_enable: # 目盛の数字を描画 cr.set_source_rgb(0.0, 0.0, 0.0) cr.select_font_face("Bitstream Vera Serif", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) for i in xrange(6*4): ang = math.radians((360.0 * i / (6*4)) - 90.0) if (i % 4) == 0: # 大きい数字 s = ["6", "1", "2", "3", "4", "5"][i / 4] fsize = r * 0.13 r5 = r * rdnum[1] else: # 小さい数字 s = ["0", "6", "12", "18"][i % 4] fsize = r * 0.05 r5 = r * rdnum[0] x0 = r5 * math.cos(ang) + cx y0 = r5 * math.sin(ang) + cy cr.set_font_size(fsize) x_bearing, y_bearing, width, height = cr.text_extents(s)[:4] cr.move_to(x0 - width / 2 - x_bearing, y0 - height / 2 - y_bearing) cr.show_text(s) # 大きい数字の横の小さい数字を描画 for i in xrange(6): ang = math.radians((360.0 * i / 6) - 90.0) s = ["", "7", "8", "9", "10", "11"][i] fsize = r * 0.05 r5 = r * rdnum[2] x0 = r5 * math.cos(ang) + cx y0 = r5 * math.sin(ang) + cy cr.set_font_size(fsize) x_bearing, y_bearing, width, height = cr.text_extents(s)[:4] cr.move_to(x0 - width / 2 - x_bearing, y0 - height / 2 - y_bearing) cr.show_text(s) def main(): surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h) # surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) cr = cairo.Context(surface) # 背景色を白にして塗る cr.set_source_rgb(1.0, 1.0, 1.0) cr.paint() # 中心点を求める cx = w/2 cy = h/2 # 基準となる半径を求める rb = min(w,h) / 2 # 時計盤を描画する draw_watch(cr, cx, cy, rb) # ファイルに保存する surface.write_to_png(outfilename) print outfilename + " output." if dbg: # 動作確認用 # 関連付けされたアプリを起動する subprocess.call('start ' + outfilename, shell=True) # 以下は古い書き方らしい # os.system('start ' + outfilename) if __name__ == '__main__': main()