root/lang/python/csskit/make_sprite.py @ 32029

Revision 22693, 5.6 kB (checked in by shn, 5 years ago)

modify help

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2# -*- coding:utf-8 -*-
3"""
4<ja>
5yamlファイルで指定した組版を元にCSSスプライトを生成する
6
7= 簡単な使い方 =
8
9make_sprite -b ./imgs --print-coordinates sprite.yaml
10
11sprite.yamlと、 /imgs ディレクトリ内の画像を元に、sprite.pngを生成します。
12標準出力に各画像の座標が出ます。 これはspire_css.pyの方で使います。
13
14= yamlの書式 =
15
16(stub)
17
18</ja>
19"""
20
21__version__ = '0.1'
22__author__ = 'shn@glucose.jp'
23
24#
25import sys, os
26import yaml
27import PIL.Image
28
29basedir = None
30
31S_HORIZONTAL = 'horizontal'
32
33HORIZONTAL = 0
34VERTICAL = 1
35
36class SpriteBase(object):
37    def __init__(self, parent):
38        self.parent = parent
39        self.topleft = None
40   
41    def set_topleft(self, tl):
42        self.topleft = tl
43   
44    #
45    def make_position(self):
46        pass
47   
48class Sprite(SpriteBase):
49    def __init__(self, parent, filename, image):
50        super(Sprite, self).__init__(parent)
51
52        self.filename = filename
53        self.image = image
54   
55    def get_size(self):
56        return self.image.size
57    size = property(get_size)
58   
59    def build_image(self):
60        return self.image
61   
62class SpriteSet(SpriteBase):
63    def __init__(self, parent, direction):
64        assert direction in (HORIZONTAL, VERTICAL)
65        super(SpriteSet, self).__init__(parent)
66       
67        self.direction = direction
68        self.sprites = []
69        self.size = None
70   
71    def add_image(self, image):
72        #assert isinstance(image, SpriteBase)
73        self.sprites.append(image)
74   
75    def make_position(self):
76        # calc sprite size
77        get_size_f = lambda x: x
78        if self.direction == VERTICAL:
79            get_size_f = lambda x: (x[1], x[0])
80       
81        corner = 0
82        max_size = 0
83        for sprite in self.sprites:
84            sprite.make_position()
85           
86            if self.direction == HORIZONTAL:
87                tl = corner, 0
88            else:
89                tl = 0, corner
90            sprite.set_topleft(tl)
91           
92            # next
93            pri, sec = get_size_f(sprite.size)
94            corner += pri
95            max_size = max(max_size, sec)
96       
97        if self.direction == HORIZONTAL:
98            self.size = corner, max_size
99        else:
100            self.size = max_size, corner
101
102    def build_image(self):
103        image = PIL.Image.new('RGBA', self.size, 0x000000FF)
104       
105        for sprite in self.sprites:
106            tl = sprite.topleft
107            sz = sprite.size
108            bounds = (tl[0], tl[1], tl[0] + sz[0], tl[1] + sz[1])
109            image.paste(sprite.build_image(), bounds)
110        return image
111
112    def print_coords(self, base_topleft=(0, 0)):
113        for sprite in self.sprites:
114            tl = base_topleft[0] + sprite.topleft[0], base_topleft[1] + sprite.topleft[1]
115            if isinstance(sprite, SpriteSet):
116                sprite.print_coords(tl)
117            else:
118                print "%s,%d,%d" % (sprite.filename, tl[0], tl[1])
119
120class ImageLoader(object):
121    def __init__(self, base_dir='.'):
122        self.base_dir = base_dir
123   
124    def load(self, yamlfile):
125        sprite = self.load_sprite(None, yaml.load(open(yamlfile)))
126        sprite.make_position()
127       
128        return sprite
129   
130    def load_sprite(self, parent, dataset):
131        assert parent is None or isinstance(parent, SpriteSet)
132       
133        if isinstance(dataset, str):
134            # is sprite image file name.
135            image = PIL.Image.open(os.path.join(self.base_dir, dataset))
136            return Sprite(parent, dataset, image)
137        elif isinstance(dataset, dict):
138            # is sprite set
139            assert 'images' in dataset
140           
141            direction = HORIZONTAL if dataset.get('direction', S_HORIZONTAL) == S_HORIZONTAL else VERTICAL
142            imagelist = dataset['images']
143           
144            return self.load_sprite_set(parent, direction, imagelist)
145        elif isinstance(dataset, list):
146            # is sprite set by simple alsfjleaflasef. inverted direction of parent
147            direction = HORIZONTAL
148            if parent:
149                direction = 1 - parent.direction
150            return self.load_sprite_set(parent, direction, dataset)
151
152    def load_sprite_set(self, parent, direction, imagelist):
153        ss = SpriteSet(parent, direction)
154        for dataset in imagelist:
155            ss.add_image(self.load_sprite(ss, dataset))
156        return ss
157
158###
159def build_sprite(yamlfile, output_file='sprite.png', base_dir='.', print_coords=False):
160    sprite = ImageLoader(base_dir).load(yamlfile)
161    sprite_image = sprite.build_image()
162    sprite_image.save(output_file, 'PNG')
163   
164    if print_coords:
165        sprite.print_coords()
166   
167def get_options():
168    import optparse
169   
170    parser = optparse.OptionParser(
171        usage='%prog [options] YAML_FILE'
172    )
173    parser.add_option(
174        '-o', '--output-file',
175        action='store', type='string',
176        dest='output_file',
177        default='sprite.png',
178        help="output sprite image file name. default 'sprite.png'"
179    )
180    parser.add_option(
181        '-b', '--base-dir',
182        action='store', type='string',
183        dest='base_dir',
184        default='',
185        help="image file's base directory. default current directory"
186    )
187    parser.add_option(
188        '--print-coordinates',
189        action='store_true', default=False,
190        dest='print_coords',
191        help="print destination coordinates"
192    )
193   
194    options, args = parser.parse_args()
195   
196    if len(args) != 1:
197        parser.print_help()
198        parser.exit()
199   
200    return options, args
201
202if __name__ == "__main__":
203    options, args = get_options()
204    build_sprite(args[0], **options.__dict__)
Note: See TracBrowser for help on using the browser.