Comment ca marche?

C'est très simple: fournissez une liste d'images, éventuellement une orientation et un fichier en sortie (par défaut, il utilise output.png dans le répertoire courant) et hop, le script vous génére un collage de toutes vos images, et vous sort la CSS associée. Idéalement, ca donne:

% collage.py *.png > style.css

La CSS obtenue ressemblera a:

  1. #i_image1
  2. {
  3. background-image: url(output.png);
  4. background-repeat: no-repeat;
  5. background-position: -0px -0px;
  6. height: 70px;
  7. width: 200px;
  8. }
  9.  
  10. #i_image2
  11. {
  12. background-image: url(output.png);
  13. background-repeat: no-repeat;
  14. background-position: -200px -0px;
  15. height: 100px;
  16. width: 300px;
  17. }

Téléchargement et notes

Vous pouvez télecharger la version 0.1 du script ou le lire ci-dessous, ce n'est pas très long. Attention par contre: le script utilisera le mode (RGB / 8 bits / RGBA) de la première image de la liste, et tentera de convertir toutes les autres images dans ce mode. Ceci fait que si vous voulez combinez plusieurs images en 8 bits, il faut qu'elles aient la même palette, vu que seule celle de la première image sera utilisée. Il ne devrait y avoir aucun problèmes avec les images en RGB/A. J'ai essayé de contourner ce problème en travaillant en RGB pour ensuite ré-enregistrer en 8 bits, mais je n'arrive pas à générer de palette correcte lorsque j'effectue la conversion avec PIL, donc pour le moment, bah faudra faire avec cette limitation :-)

  1. #!/usr/bin/python
  2.  
  3. import sys
  4. import os
  5. import re
  6. from optparse import OptionParser
  7. import Image
  8.  
  9. def parse_options():
  10. parser = OptionParser(usage="Usage: %prog [options] SOURCE...",
  11. version="%prog 0.1")
  12. parser.add_option("-v", "--verbose",
  13. dest="verbose",
  14. action="store_true",
  15. default=False,
  16. help="turn on verbose output [default: %default]")
  17. parser.add_option("-f", "--file",
  18. dest="filename",
  19. default="output.png",
  20. metavar="FILE",
  21. help="write output to FILE [default: %default]")
  22. parser.add_option("-o", "--orientation",
  23. dest="orientation",
  24. default="horizontal",
  25. metavar="ORIENTATION",
  26. help="set orientation to ORIENTATION [default: %default]")
  27.  
  28. (options, args) = parser.parse_args()
  29.  
  30. if options.orientation != "horizontal" and options.orientation != "vertical":
  31. parser.error("orientation must be 'horizontal' or 'vertical'")
  32. return (options, args)
  33. def draw_output(options, args):
  34. x = 0
  35. y = 0
  36. buffer = None
  37. transindex = -1
  38. images = []
  39. for imagename in args:
  40. # Do not include the resulting file in the process, allowing lazy people
  41. # to just use collage.py * :)
  42. if imagename == options.filename:
  43. continue
  44. try:
  45. image = Image.open(imagename)
  46. if options.verbose:
  47. print "Adding %s (%s, %s, %s)" % (imagename, image.size, image.mode, image.format)
  48. except IOError:
  49. print >> sys.stderr, "Error opening file '%s', moving on." % (imagename, )
  50. continue
  51. if not buffer:
  52. # FIXME: warn the user if the other image's palettes do not match!!
  53. buffer = Image.new(image.mode, image.size, None)
  54. if image.mode == "P":
  55. if image.info and image.info.has_key('transparency'):
  56. transindex = image.info['transparency']
  57. palette = image.getpalette()
  58. buffer.putpalette(palette)
  59. owidth = width = buffer.size[0]
  60. oheight = height = buffer.size[1]
  61. if width < image.size[0] + x:
  62. width = image.size[0] + x
  63. if height < image.size[1] + y:
  64. height = image.size[1] + y
  65. if width != owidth or height != oheight:
  66. if options.verbose:
  67. print "Need to transform buffer from %d, %d to %d, %d" % (owidth, oheight, width, height)
  68. buffer = buffer.transform((width, height), Image.EXTENT, (0, 0, width, height))
  69. buffer.paste(image, (x, y))
  70. images.append({'name' : imagename, 'x': x, 'y': y, 'width': image.size[0], 'height': image.size[1]})
  71. if options.orientation == "horizontal":
  72. x += image.size[0]
  73. else:
  74. y += image.size[1]
  75. if transindex != -1:
  76. try:
  77. buffer.save(options.filename, transparency=transindex)
  78. return images
  79. except:
  80. pass
  81. try:
  82. buffer.save(options.filename)
  83. except:
  84. print >> sys.stderr, "Can't save image to %s, giving up" % (options.filename, )
  85. sys.exit(0)
  86. return images
  87. def print_stylesheet(images, filename):
  88. for image in images:
  89. selector = os.path.splitext(os.path.basename(image['name']))[0]
  90. selector = "i_" + re.sub(r"[^A-Za-z0-9_:.-]", "", selector)
  91. print "#%s" % (selector, )
  92. print "{"
  93. print "\tbackground-image: url(%s);" % (filename)
  94. print "\tbackground-repeat: no-repeat;"
  95. print "\tbackground-position: -%dpx -%dpx;" % (image['x'], image['y'])
  96. print "\theight: %dpx;" % (image['height'])
  97. print "\twidth: %dpx;" % (image['width'])
  98. print "}"
  99. print
  100.  
  101. if __name__ == "__main__":
  102. (options, args) = parse_options()
  103. images = draw_output(options, args)
  104. print_stylesheet(images, options.filename)