Created
November 24, 2011 09:24
-
-
Save PaulGuo/1390952 to your computer and use it in GitHub Desktop.
Auto CSS Sprites
This file contains 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/env 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,align='left'): | |
def _basename(path): | |
return p.splitext(p.basename(path))[0] | |
data=[] | |
master_width=max(*[i.size[0] for i in images]) | |
master_height=sum([i.size[1] 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: | |
# print('Warning: Incorrect transparency mode: '+image.filename) | |
xpos=0 if(align=='left') else master_width-image.size[0] | |
sprite.paste(image,(xpos,location)) | |
data.append({ | |
'xpos':xpos, | |
'ypos':location, | |
'dir':_basename(p.dirname(image.filename)), | |
'file':_basename(image.filename), | |
'width':image.size[0], | |
'height':image.size[1], | |
}) | |
location+=image.size[1]+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,align='left',margin=10): | |
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,margin=margin,align=align) | |
# TODO | |
# convert png24 to png8 hack for ie6 | |
# sprite=sprite.convert('RGB').convert('P',palette=Image.ADAPTIVE) | |
# sprite.save(sprite_output,transparency=255) | |
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.') | |
parser.add_option('-a','--align',dest='align',default='left',help='Css sprites Image align.') | |
parser.add_option('-m','--margin',dest='margin',default='10',help='Css sprites Image margin.') | |
(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, | |
align=options.align, | |
margin=eval(options.margin)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment