X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1fded56b375bf7a4687af1cdb182899614c1b2a8..b39fc8d7b1b853cb15f39d51617214b7b90a8872:/wxPython/wx/tools/img2py.py diff --git a/wxPython/wx/tools/img2py.py b/wxPython/wx/tools/img2py.py index de1d5e2a58..5d9425054e 100644 --- a/wxPython/wx/tools/img2py.py +++ b/wxPython/wx/tools/img2py.py @@ -1,11 +1,339 @@ +#---------------------------------------------------------------------- +# Name: wxPython.tools.img2py +# Purpose: Convert an image to Python code. +# +# Author: Robin Dunn +# +# RCS-ID: $Id$ +# Copyright: (c) 2002 by Total Control Software +# Licence: wxWindows license +#---------------------------------------------------------------------- +# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net) +# +# +# 2/25/2007 - Gianluca Costa (archimede86@katamail.com) +# +# +# o V2.5 compatibility update +# -"""Renamer stub: provides a way to drop the wx prefix from wxPython objects.""" +""" +img2py.py -- Convert an image to PNG format and embed it in a Python + module with appropriate code so it can be loaded into + a program at runtime. The benefit is that since it is + Python source code it can be delivered as a .pyc or + 'compiled' into the program using freeze, py2exe, etc. -__cvsid__ = "$Id$" -__revision__ = "$Revision$"[11:-2] +Usage: -from wx import _rename -from wxPython.tools import img2py -_rename(globals(), img2py.__dict__, modulename='tools.img2py') -del img2py -del _rename + img2py.py [options] image_file python_file + +Options: + + -m <#rrggbb> If the original image has a mask or transparency defined + it will be used by default. You can use this option to + override the default or provide a new mask by specifying + a colour in the image to mark as transparent. + + -n Normally generic names (getBitmap, etc.) are used for the + image access functions. If you use this option you can + specify a name that should be used to customize the access + fucntions, (getNameBitmap, etc.) + + -c Maintain a catalog of names that can be used to reference + images. Catalog can be accessed via catalog and + index attributes of the module. + If the -n option is specified then + is used for the catalog key and index value, otherwise + the filename without any path or extension is used + as the key. + + -a This flag specifies that the python_file should be appended + to instead of overwritten. This in combination with -n will + allow you to put multiple images in one Python source file. + + -u Don't use compression. Leaves the data uncompressed. + + -i Also output a function to return the image as a wxIcon. + + +You can also import this module from your Python scripts, and use its img2py() +function. See its docstring for more info. +""" + +# +# Changes: +# - Cliff Wells +# 20021206: Added catalog (-c) option. +# +# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net) +# +# +# 2/25/2007 - Gianluca Costa (archimede86@katamail.com) +# -Refactorization of the script-creation code in a specific "img2py()" function +# -Added regex parsing instead of module importing +# -Added some "try/finally" statements +# -Added default values as named constants +# -Made some parts of code a bit easier to read +# -Updated the module docstring +# -Corrected a bug with EmptyIcon +# +# o V2.5 compatibility update +# +import cPickle +import cStringIO +import getopt +import glob +import os +import os.path +import sys +import tempfile +import zlib +import re + +import wx +import img2img + + +def crunch_data(data, compressed): + # compress it? + if compressed: + data = zlib.compress(data, 9) + + # convert to a printable format, so it can be in a Python source file + data = repr(data) + + # This next bit is borrowed from PIL. It is used to wrap the text intelligently. + fp = cStringIO.StringIO() + data += " " # buffer for the +1 test + c = i = 0 + word = "" + octdigits = "01234567" + hexdigits = "0123456789abcdef" + while i < len(data): + if data[i] != "\\": + word = data[i] + i += 1 + else: + if data[i+1] in octdigits: + for n in xrange(2, 5): + if data[i+n] not in octdigits: + break + word = data[i:i+n] + i += n + elif data[i+1] == 'x': + for n in xrange(2, 5): + if data[i+n] not in hexdigits: + break + word = data[i:i+n] + i += n + else: + word = data[i:i+2] + i += 2 + + l = len(word) + if c + l >= 78-1: + fp.write("\\\n") + c = 0 + fp.write(word) + c += l + + # return the formatted compressed data + return fp.getvalue() + + +app = None +DEFAULT_APPEND = False +DEFAULT_COMPRESSED = True +DEFAULT_MASKCLR = None +DEFAULT_IMGNAME = "" +DEFAULT_ICON = False +DEFAULT_CATALOG = False + +#THIS IS USED TO IDENTIFY, IN THE GENERATED SCRIPT, LINES IN THE FORM "index.append('Image name')" +indexPattern = re.compile(r"\s*index.append\('(.+)'\)\s*") + +def img2py(image_file, python_file, append=DEFAULT_APPEND, compressed=DEFAULT_COMPRESSED, maskClr=DEFAULT_MASKCLR, imgName=DEFAULT_IMGNAME, icon=DEFAULT_ICON, catalog=DEFAULT_CATALOG): + """ + Converts an image file to a data structure written in a Python file + --image_file: string; the path of the source image file + --python_file: string; the path of the destination python file + --other arguments: they are equivalent to the command-line arguments + """ + global app + if not wx.GetApp(): + app = wx.PySimpleApp() + + # convert the image file to a temporary file + tfname = tempfile.mktemp() + try: + ok, msg = img2img.convert(image_file, maskClr, None, tfname, wx.BITMAP_TYPE_PNG, ".png") + if not ok: + print msg + return + + data = open(tfname, "rb").read() + data = crunch_data(data, compressed) + finally: + if os.path.exists(tfname): + os.remove(tfname) + + + old_index = [] + if catalog and append: + # check to see if catalog exists already (file may have been created + # with an earlier version of img2py or without -c option) + pyPath, pyFile = os.path.split(python_file) + + append_catalog = True + + sourcePy = open(python_file, "r") + try: + for line in sourcePy: + + if line == "catalog = {}\n": + append_catalog = False + else: + lineMatcher = indexPattern.match(line) + if lineMatcher: + old_index.append(lineMatcher.groups()[0]) + finally: + sourcePy.close() + + + if append_catalog: + out = open(python_file, "a") + try: + out.write("\n# ***************** Catalog starts here *******************") + out.write("\n\ncatalog = {}\n") + out.write("index = []\n\n") + out.write("class ImageClass: pass\n\n") + finally: + out.close() + + + + if append: + out = open(python_file, "a") + else: + out = open(python_file, "w") + + try: + if catalog: + imgPath, imgFile = os.path.split(image_file) + + if not imgName: + imgName = os.path.splitext(imgFile)[0] + print "\nWarning: -n not specified. Using filename (%s) for catalog entry." % imgName + + out.write("#" + "-" * 70 + "\n") + if not append: + out.write("# This file was generated by %s\n#\n" % sys.argv[0]) + out.write("from wx import ImageFromStream, BitmapFromImage, EmptyIcon\n") + if compressed: + out.write("import cStringIO, zlib\n\n\n") + else: + out.write("import cStringIO\n\n\n") + + if catalog: + out.write("catalog = {}\n") + out.write("index = []\n\n") + out.write("class ImageClass: pass\n\n") + + if compressed: + out.write("def get%sData():\n" + " return zlib.decompress(\n%s)\n\n" + % (imgName, data)) + else: + out.write("def get%sData():\n" + " return \\\n%s\n\n" + % (imgName, data)) + + + out.write("def get%sBitmap():\n" + " return BitmapFromImage(get%sImage())\n\n" + "def get%sImage():\n" + " stream = cStringIO.StringIO(get%sData())\n" + " return ImageFromStream(stream)\n\n" + % tuple([imgName] * 4)) + if icon: + out.write("def get%sIcon():\n" + " icon = EmptyIcon()\n" + " icon.CopyFromBitmap(get%sBitmap())\n" + " return icon\n\n" + % tuple([imgName] * 2)) + + if catalog: + if imgName in old_index: + print "Warning: %s already in catalog." % imgName + print " Only the last entry will be accessible.\n" + old_index.append(imgName) + out.write("index.append('%s')\n" % imgName) + out.write("catalog['%s'] = ImageClass()\n" % imgName) + out.write("catalog['%s'].getData = get%sData\n" % tuple([imgName] * 2)) + out.write("catalog['%s'].getImage = get%sImage\n" % tuple([imgName] * 2)) + out.write("catalog['%s'].getBitmap = get%sBitmap\n" % tuple([imgName] * 2)) + if icon: + out.write("catalog['%s'].getIcon = get%sIcon\n" % tuple([imgName] * 2)) + out.write("\n\n") + + + if imgName: + n_msg = ' using "%s"' % imgName + else: + n_msg = "" + + if maskClr: + m_msg = " with mask %s" % maskClr + else: + m_msg = "" + + print "Embedded %s%s into %s%s" % (image_file, n_msg, python_file, m_msg) + finally: + out.close() + + + +def main(args): + if not args or ("-h" in args): + print __doc__ + return + + append = DEFAULT_APPEND + compressed = DEFAULT_COMPRESSED + maskClr = DEFAULT_MASKCLR + imgName = DEFAULT_IMGNAME + icon = DEFAULT_ICON + catalog = DEFAULT_CATALOG + + try: + opts, fileArgs = getopt.getopt(args, "auicn:m:") + except getopt.GetoptError: + print __doc__ + return + + for opt, val in opts: + if opt == "-a": + append = True + elif opt == "-u": + compressed = False + elif opt == "-n": + imgName = val + elif opt == "-m": + maskClr = val + elif opt == "-i": + icon = True + elif opt == "-c": + catalog = True + + if len(fileArgs) != 2: + print __doc__ + return + + image_file, python_file = fileArgs + img2py(image_file, python_file, append, compressed, maskClr, imgName, icon, catalog) + + + +if __name__ == "__main__": + main(sys.argv[1:])