Skip to content

Instantly share code, notes, and snippets.

@gearheart
Created April 3, 2011 17:44
Show Gist options
  • Save gearheart/900606 to your computer and use it in GitHub Desktop.
Save gearheart/900606 to your computer and use it in GitHub Desktop.
Python lib to combine images to sprite and generate css.
#!/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