#----------------------------------------------------------------------# Name: wxPython.tools.img2py# Purpose: Convert an image to Python code.## Author: Robin Dunn## RCS-ID: $Id: img2py.py 61388 2009-07-10 22:25:20Z RD $# Copyright: (c) 2002 by Total Control Software# Licence: wxWindows license#----------------------------------------------------------------------## Changes:# - Cliff Wells <LogiplexSoftware@earthlink.net># 20021206: Added catalog (-c) option.## 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)# V2.5 compatibility update ## 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## 11/26/2007 - Anthony Tuininga (anthony.tuininga@gmail.com)# -Use base64 encoding instead of simple repr# -Remove compression which doesn't buy anything in most cases and# costs more in many cases# -Use wx.lib.embeddedimage.PyEmbeddedImage class which has methods# rather than using standalone methods#"""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.Usage: img2py.py [options] image_file python_fileOptions: -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 <name> 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 <name> option is specified then <name> 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. -i Also output a function to return the image as a wxIcon. -f Generate code compatible with the old function interface. (This option is ON by default in 2.8, use -F to turn off.)You can also import this module from your Python scripts, and use its img2py()function. See its docstring for more info."""importbase64importgetoptimportglobimportosimportreimportsysimporttempfileimportwximportimg2imgtry:b64encode=base64.b64encodeexceptAttributeError:b64encode=base64.encodestringapp=NoneDEFAULT_APPEND=FalseDEFAULT_COMPRESSED=TrueDEFAULT_MASKCLR=NoneDEFAULT_IMGNAME=""DEFAULT_ICON=FalseDEFAULT_CATALOG=FalseDEFAULT_COMPATIBLE=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*")defconvert(fileName,maskClr,outputDir,outputName,outType,outExt):# if the file is already the right type then just use it directlyifmaskClr==DEFAULT_MASKCLRandfileName.upper().endswith(outExt.upper()):ifoutputName:newname=outputNameelse:newname=os.path.join(outputDir,os.path.basename(os.path.splitext(fileName)[0])+outExt)file(newname,"wb").write(file(fileName,"rb").read())return1,"ok"else:returnimg2img.convert(fileName,maskClr,outputDir,outputName,outType,outExt)defimg2py(image_file,python_file,append=DEFAULT_APPEND,compressed=DEFAULT_COMPRESSED,maskClr=DEFAULT_MASKCLR,imgName=DEFAULT_IMGNAME,icon=DEFAULT_ICON,catalog=DEFAULT_CATALOG,functionCompatible=DEFAULT_COMPATIBLE,functionCompatibile=-1,# typo version for backward compatibility):""" 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 """# was the typo version used?iffunctionCompatibile!=-1:functionCompatible=functionCompatibileglobalappifnotwx.GetApp():app=wx.PySimpleApp()# convert the image file to a temporary filetfname=tempfile.mktemp()try:ok,msg=convert(image_file,maskClr,None,tfname,wx.BITMAP_TYPE_PNG,".png")ifnotok:printmsgreturnlines=[]data=b64encode(open(tfname,"rb").read())whiledata:part=data[:72]data=data[72:]output=' "%s"'%partifnotdata:output+=")"lines.append(output)data="\n".join(lines)finally:ifos.path.exists(tfname):os.remove(tfname)old_index=[]ifcatalogandappendandpython_file!='-':# 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=TruesourcePy=open(python_file,"r")try:forlineinsourcePy:ifline=="catalog = {}\n":append_catalog=Falseelse:lineMatcher=indexPattern.match(line)iflineMatcher:old_index.append(lineMatcher.groups()[0])finally:sourcePy.close()ifappend_catalog:out=open(python_file,"a")try:out.write("\n# ***************** Catalog starts here *******************")out.write("\n\ncatalog = {}\n")out.write("index = []\n\n")finally:out.close()ifpython_file=='-':out=sys.stdoutelifappend:out=open(python_file,"a")else:out=open(python_file,"w")try:imgPath,imgFile=os.path.split(image_file)ifnotimgName:imgName=os.path.splitext(imgFile)[0]print"\nWarning: -n not specified. Using filename (%s) for name of image and/or catalog entry."%imgNameout.write("#"+"-"*70+"\n")ifnotappend:out.write("# This file was generated by %s\n#\n"%sys.argv[0])out.write("from wx.lib.embeddedimage import PyEmbeddedImage\n\n")ifcatalog:out.write("catalog = {}\n")out.write("index = []\n\n")letters=[]forletterinimgName:ifnotletter.isalnum():letter="_"letters.append(letter)ifnotletters[0].isalpha()andletters[0]!='_':letters.insert(0,"_")varName="".join(letters)out.write("%s = PyEmbeddedImage(\n%s\n"%(varName,data))ifcatalog:ifimgNameinold_index:print"Warning: %s already in catalog."%imgNameprint" Only the last entry will be accessible.\n"old_index.append(imgName)out.write("index.append('%s')\n"%imgName)out.write("catalog['%s'] = %s\n"%(imgName,varName))iffunctionCompatible:out.write("get%sData = %s.GetData\n"%(varName,varName))out.write("get%sImage = %s.GetImage\n"%(varName,varName))out.write("get%sBitmap = %s.GetBitmap\n"%(varName,varName))ificon:out.write("get%sIcon = %s.GetIcon\n"%(varName,varName))out.write("\n")ifimgName:n_msg=' using "%s"'%imgNameelse:n_msg=""ifmaskClr:m_msg=" with mask %s"%maskClrelse:m_msg=""print"Embedded %s%s into %s%s"%(image_file,n_msg,python_file,m_msg)finally:ifpython_file!='-':out.close()defmain(args=None):ifnotargs:args=sys.argv[1:]ifnotargsor("-h"inargs):print__doc__returnappend=DEFAULT_APPENDcompressed=DEFAULT_COMPRESSEDmaskClr=DEFAULT_MASKCLRimgName=DEFAULT_IMGNAMEicon=DEFAULT_ICONcatalog=DEFAULT_CATALOGcompatible=DEFAULT_COMPATIBLEtry:opts,fileArgs=getopt.getopt(args,"auicfFn:m:")exceptgetopt.GetoptError:print__doc__returnforopt,valinopts:ifopt=="-a":append=Trueelifopt=="-n":imgName=valelifopt=="-m":maskClr=valelifopt=="-i":icon=Trueelifopt=="-c":catalog=Trueelifopt=="-f":compatible=Trueelifopt=="-F":compatible=Falseiflen(fileArgs)!=2:print__doc__returnimage_file,python_file=fileArgsimg2py(image_file,python_file,append,compressed,maskClr,imgName,icon,catalog,compatible)if__name__=="__main__":main(sys.argv[1:])