Created
April 3, 2011 17:44
-
-
Save gearheart/900606 to your computer and use it in GitHub Desktop.
Python lib to combine images to sprite and generate css.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import os | |
import os.path as p | |
import Image | |
css_inline_item_template = ''' | |
%(selector)s { | |
background: url(%(url)s) no-repeat -%(xpos)spx -%(ypos)spx; | |
width: %(width)spx; | |
height: %(height)spx; | |
} | |
''' | |
css_base_template = ''' | |
%(base_selector)s { | |
background-image: url(%(url)s); | |
background-repeat: no-repeat; | |
} | |
''' | |
css_base_item_template = ''' | |
%(selector)s { | |
background-position: -%(xpos)spx -%(ypos)spx; | |
width: %(width)spx; | |
height: %(height)spx; | |
} | |
''' | |
def generate_sprite(images, margin=10): | |
def _basename(path): | |
return p.splitext(p.basename(path))[0] | |
data = [] | |
master_height = max(*[i.size[1] for i in images]) | |
master_width = sum([i.size[0] for i in images]) + margin * (len(images) - 1) | |
sprite = Image.new( | |
mode='RGBA', | |
size=(master_width, master_height), | |
color=(0,0,0,0)) # fully transparent | |
location = 0 | |
for image in images: | |
if 'transparency' in image.info: | |
raise Exception('Incorrect transparency mode: ' + image.filename) | |
sprite.paste(image,(location, 0)) | |
data.append({ | |
'xpos': location, | |
'ypos': 0, | |
'dir': _basename(p.dirname(image.filename)), | |
'file': _basename(image.filename), | |
'width': image.size[0], | |
'height': image.size[1], | |
}) | |
location += image.size[0] + margin | |
return sprite, data | |
def render_css(base_template, item_template, css_data, sprite_url, base_selector, selector): | |
base_info = { | |
'base_selector': base_selector, | |
'url': sprite_url, | |
} | |
base_css = base_template % base_info | |
items_css = '\n'.join([ | |
item_template % dict([('selector', selector % image_data)] | |
+ image_data.items() | |
+ base_info.items()) | |
for image_data in css_data]) | |
return base_css + items_css | |
def create_sprite_and_css(images_dir, css_output, sprite_output, | |
selector='.%(file)s', base_selector='.sprite', url=None, inline=False): | |
images = [Image.open(p.join(images_dir, filename)) | |
for filename in os.listdir(images_dir) | |
if not filename.startswith('.')] | |
sprite, css_data = generate_sprite(images) | |
sprite.save(sprite_output) | |
sprite_url = url or p.basename(sprite_output) | |
if inline: | |
css = render_css('', css_inline_item_template, css_data, sprite_url, base_selector, selector) | |
else: | |
css = render_css(css_base_template, css_base_item_template, css_data, sprite_url, base_selector, selector) | |
css_file = open(css_output, 'w') | |
css_file.write(css) | |
css_file.close() | |
if __name__ == '__main__': | |
from optparse import OptionParser | |
usage = "usage: %prog [options] images_dir css_output sprite_output" | |
parser = OptionParser(usage=usage) | |
parser.add_option("-i", "--inline", action="store_true", dest="inline", default=False, | |
help="When set, image url will be put in css rule for every item.") | |
parser.add_option("-s", "--selector", dest="selector", default='.%(file)s', | |
help="Selector template. You can use dir, file, width, height here.") | |
parser.add_option("-S", "--base-selector", dest="base_selector", default='.sprite', | |
help="Base selector template for base css rule (when -i is not set).") | |
parser.add_option("-u", "--url", dest="url", default='', | |
help="Css rule Image url template.") | |
(options, args) = parser.parse_args() | |
if len(args) < 3: | |
print 'You must provide all 3 arguments.' | |
else: | |
images_dir, css_output, sprite_output = [p.realpath(arg) for arg in args] | |
create_sprite_and_css(images_dir, css_output, sprite_output, | |
selector=options.selector, | |
base_selector=options.base_selector, | |
inline=options.inline, | |
url=options.url) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment