wxWidgets/wxPython/wx/tools/img2py.py
Robin Dunn cbfc9df676 Merge recent changes from 2.8 branch.
Make updates for recent changes on CVS HEAD.
Remove or workaround deprecated items.
Fix compile errors.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45088 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2007-03-27 01:49:46 +00:00

340 lines
11 KiB
Python

#----------------------------------------------------------------------
# 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
#
"""
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_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 <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.
-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 <LogiplexSoftware@earthlink.net>
# 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:])