Attachment 'Image2PyFile.PY'
Download
"""
Image2PyFile.py
Convert disk graphics image files to importable Pyhon code.
This code is intended for embedding it in any Python application
so the graphics image data is available without having to read
external disk graphics image files at runtime.
Inspired from img2py.py by Robin Dunn.
img2py.py crashes on Win7 64-bit as of 2012-04-26.
Command Line Usage:
> python.exe Image2PyFile.py [options] imgFile1 [ imgFile2 ...] \
[ pyImagesExist1.py ...] pyImagesNew.py
Usage Within a Python Application:
import Image2PyFile as i2p
i2p.Image2PyFile( [options] imgFile1 [ imgFile2 ...] \
[ pyImagesExist1.py ...] pyImagesNew.py )
Arguments for image files, options and .py pyImages files
may intermixed in any order.
NOTE:
All filenames ending with ".py" are assumed to be PyImages files.
The last given .py file will always be written or rewritten.
Any .py filenames preceding the last are assumed to exist.
The directory of the output pyImage filename determines
where that file will be written.
ACTION, PROGRESS, NOTE and WARNING message are written to stdout.
FAILURE messages indicate file I/O failures.
They do NOT terminate the application and these messages
are wriiten to stderr.
ERROR messages indicate a fatal application error and are wriiten
to stderr. They cannot be suppressed, thus there are
no associated command line options available for them .
Options: (NOTE: The following options are just that: Optional !
None *need* to be specified.)
-a -A Enable/Disable ACTION messages. Disabled by default.
-f -F Enable/Disable FAULURE messages. Enabled by default.
-n -N Enable/Disable NOTE: messages. Disabled by default.
-p -P Enable/Disable PROGRESS messages. Enabled by default.
-w -W Enable/Disable WARNING messages. Disabled by default.
-q -Q Disable/Enable all non-fatal messages.
To enable only specific messages specify '-q' followed
with the desired lower case message option letters.
E.g.: -qfw
E.g.: -q -f -w
-h List this help and exit.
-H List this help THEN CONTINUE.
A PROGRESS message indicates an attempt to do something
such as read a file while an ACTION message indicates
an actual accomplishment.
This module can be used internally by instantiating
an Image2PyFile() class object.
E.g., the following:
- Disables all messaging except for PROGRESS messages;
- Reads all existing image data from file pyimagesIn.py and
- appends them to file pyimagesOut.py;
- Processes images from all give .PNG files and writes their
data to pyimagesOut.py
import Image2PyFile as i2p
args = '-qp image1.png pyimagesIn.py pyImagesOut.py image2.gif'
args = args.split() # Args are in a list just like sys.argv[ 1: ]
i2p.Image2PyFile( args )
E.g.:
An initial command line runs and its results when file PyImages.PY
does not yet exist:
> python.exe Image2PyFile.py About-16.PNG About-32.PNG PyImages.PY
PROGRESS: Reading New Image Files
ACTION: Adding Image: [ About_16_PNG ] File: [ About-16.PNG]
ACTION: Adding Image: [ About_32_PNG ] File: [ About-32.PNG]
PROGRESS: Writing New PyImages File: [ PyImages.PY ]
A following run when file PyImages.PY does exist:
> python.exe Image2PyFile.py Cut-32.PNG Delete-16.PNG
PROGRESS: Reading EXISTING PyImages File: [ PyImages.PY ]
PROGRESS: Reading New Image Files
ACTION: Adding Image: [ Cut_32_PNG ] File: [ Cut-32.PNG]
ACTION: Adding Image: [ Delete_16_PNG ] File: [ Delete-16.PNG]
PROGRESS: OVERWRITING PyImages File: [ PyImages.PY ]
Ray Pasco
pascor(at)verizon(dot)net
Version:
1.2 2102-04-29 All functions specific to pyImages files are now methods
within the Image2PyFile class. PyImages files not located
in os.cwd are now read properly (they're imported).
Better file existance checks.
The last PyImages file (the output) is no longer read in
to accumulate its image data.
1.1 2012-04-26 Better messaging. Bug fixes.
Tested on:
Windows 6.1.7601 {Windows 7 64-bit}
Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)]
Wx Version 2.8.12.0
Wx Pltform ('__WXMSW__', 'wxMSW', 'unicode', 'wx-assertions-on', 'SWIG-1.3.29')
Windows 5.1.2600 {Windows XP 32-bit}
Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)]
Wx Version 2.8.12.0
Wx Pltform ('__WXMSW__', 'wxMSW', 'unicode', 'wx-assertions-on', 'SWIG-1.3.29')
"""
import os, sys
import getopt
import glob
import re
import tempfile
import base64
import binascii
import wx
import time
try :
THISPYFILENAME = os.path.basename( __file__ )
except NameError : # Doesn't exist if this app is frozen.
THISPYFILENAME = 'Image2PyFile.exe'
#------------------------------------------------------------------------------
#==============================================================================
#------------------------------------------------------------------------------
class Image2PyFile() :
"""Convert disk graphics image files to embeddable Python code.
Image2PyFile allows embedding external disk graphics image files's data
in any Python application so that data is available without having to
read external files at runtime.
"""
def __init__( self, args=None ) :
defName = 'Image2PyFile()'
enabledMsgs, fileArgs, opts = self.ProcessArgs( args )
inPyImageFilesList, outPyImageFileName, imageFileList = \
self.SortFilenames( fileArgs, enabledMsgs )
# Determine the dir for the output pyImages file.
outPyImageFileDir, outPyImageFileName = \
os.path.split( os.path.abspath( outPyImageFileName ) )
if not wx.GetApp() : # Has the user's program already created a wx.App ?
#app = wx.App( redirect=True ) # Create a dummy app to enable accessinng all wx's methods.
app = wx.App( redirect=False ) # Create a dummy app to enable accessinng all wx's methods.
#-----
# Import any given PyImages files and populate an imageDict from their contents.
# There must be at least one pyImages file.
# All input PyImages files have already been checked for existance.
imageDict = dict() # Brand new, empty
for anInpPyImgFileGiven in inPyImageFilesList :
anInpPyImgFilePath = os.path.abspath( anInpPyImgFileGiven )
anInpPyImgFileDir, anInpPyImgFileName = os.path.split( anInpPyImgFilePath )
if ('progress' in enabledMsgs) :
print 'PROGRESS: Reading EXISTING PyImages File [ %s ] in:\n [ %s ]' \
%( anInpPyImgFileName, anInpPyImgFileDir )
# Add to imageDict{} given the current content of imageDict{}.
imageDict = self.ImportPyImages( anInpPyImgFilePath, imageDict, enabledMsgs )
#ListImageDict( imageDict ) # DEBUG
#end for
#-----
if imageFileList : # Might be "None" if just accumulating pyImagefile image defs.
if ('progress' in enabledMsgs) :
print 'PROGRESS: Reading New Image Files'
# Add the new images to imageDict
for imgFilename in imageFileList :
# Convert the filename to a legal Python identifier string.
baseName = os.path.basename( imgFilename )
mainName, fileExt = os.path.splitext( baseName )
idName = String2Identifier( baseName )
# Check if the image name already exists imageDict.
overWriting = False
for imgObj in imageDict.values() :
if (idName == imgObj.idName) :
overWriting = True
break # Process the next image filename.
#-----
#end for
# Convert any type image to an equivalent PNG file data format.
# Result will be set to None if any kind of error occurs.
pngImageData = CreatePngFileData( imgFilename, enabledMsgs )
if pngImageData :
# This is all images' storage format.
encPngData = B64EncodeBinaryData( pngImageData )
# Create a new ImageObject and populate it.
imgObj = ImageObject( idName, baseName, mainName, fileExt, encPngData )
# Add (accumulate) the new encoded image data object to the image dictionary.
imageDict[ idName ] = imgObj
if overWriting :
if ('warning' in enabledMsgs) :
print 'WARNING: OVERWITING PyImage: [ %s ] from Existing File: [ %s ]' \
%( idName, baseName )
else :
if ('action' in enabledMsgs) :
print 'ACTION: Adding PyImage: [ %s ] from Existing File: [ %s ]' \
%( idName, baseName )
#end
#end if pngImageData
#end for imgFilename in imageFileList
#end if imageFileList
#ListImageDict( imageDict ) # DEBUG
#-----
# Write a brand new new PiImages.py file, overwriting any existing one
# of the same name.
outPyImageFilePath = os.path.join( outPyImageFileDir, outPyImageFileName )
self.WritePyImageFile( imageDict, outPyImageFilePath, enabledMsgs )
#end __init__
#----------------------------------
def WritePyImageFile( self, imageDict, outPyImageFilePath, enabledMsgs ) :
""" Writes a new pyImages file from an imageDict. """
defName = DefName() # For DEBUG
outPyImageFileDir, outPyImageFileName = os.path.split( outPyImageFilePath )
if not imageDict : # Is an empty dict
if ('warning' in enabledMsgs) :
print 'WARNING: NO IMAGES TO WRITE to PyImages File: [ %s ]' \
%( outPyImageFileName )
return
#-----
if (not os.path.exists( outPyImageFilePath )) :
if ('progress' in enabledMsgs) :
print 'PROGRESS: Writing NEW PyImages File: [ %s ] in:\n [ %s ]' \
%( outPyImageFileName, outPyImageFileDir )
else :
if ('progress' in enabledMsgs) :
print 'PROGRESS: OVERWRITING PyImages File: [ %s ] in:\n [ %s ]' \
%( outPyImageFileName, outPyImageFileDir )
# If one already exist, delete it and rewrite it from scratch
# appending any new image defs that have been accumulated.
pyImagesFile = open( outPyImageFilePath, 'w' ) # Delete any existing file.
# Write the header once,
self.WritePyImagesFileHeader( pyImagesFile )
# For each imgObject write its encoded data and functions.
for imgObj in imageDict.itervalues() :
self.WritePyImageDataAndFuncs( imgObj, pyImagesFile, enabledMsgs )
pyImagesFile.close()
#end WritePyImageFile def
#----------------------------------
def ProcessArgs( self, args=None ) :
"""
Command line parsing. Separates args into three groups:
1) List of pyImages files that will be read from and/or written to;
2) A Python set of message type strings indicating which kinds
of message types will be enabled to be emitted if necessary.
"""
defName = DefName() # For DEBUG
if not args :
msg = 'ERROR: %s::%s: No Commandline Args Given\n' \
%( THISPYFILENAME, defName )
print >> sys.stderr, msg
print >> sys.stderr, __doc__
sys.exit(1)
#end if
#-----
try :
opts, fileArgs = getopt.gnu_getopt( args, 'aA fF hH nN pP qQ wW' )
except getopt.GetoptError :
msg = '\nERROR: %s::%s: UNKNOWN SWITCH ARG in:\n\n%s\n' \
%( THISPYFILENAME, defName, args )
print >> sys.stderr, msg
sys.exit(1)
#-----
# [ opts ] is returned as list of tuples.
# A set is used rather than a tuple because sets automatically
# prevent duplicate items when added multiple times.
enabledMsgs = set( [ 'action', 'progress' ] )
for key, valIgnored in opts :
if key == '-a' :
enabledMsgs.add( 'action' ) # Enable these messages
elif key == '-A' :
enabledMsgs.discard( 'action' ) # Suppress these messages
elif key == '-f' :
enabledMsgs.add( 'failure' )
elif key == '-F' :
enabledMsgs.discard( 'failure' )
elif key == '-h' :
print __doc__
sys.exit(1)
elif key == '-H' :
print __doc__
elif key == '-n' :
enabledMsgs.add( 'note' )
elif key == '-N' :
enabledMsgs.discard( 'note' )
elif key == '-p' :
enabledMsgs.add( 'progress' )
elif key == '-P' :
enabledMsgs.discard( 'progress' )
elif key == '-q' :
enabledMsgs = list() # Suppress all messages
elif key == '-Q' :
enabledMsgs.add( 'action' ) # Enable these messages
enabledMsgs.add( 'failure' )
enabledMsgs.add( 'note' )
enabledMsgs.add( 'progress' )
enabledMsgs.add( 'warning' )
elif key == '-w' :
enabledMsgs.add( 'warning' )
elif key == '-W' :
enabledMsgs.discard( 'warning' )
else :
print >> sys.stderr, 'UNRECOGNIZED Arg Switch [ %s ]' %( key )
#end if
#end for
##print 'enabledMsgs: ', enabledMsgs; print # DEBUG
if (len( fileArgs ) < 1) : # Sanity check.
msg = '\nERROR - %s::%s: At Least One PyImages Filename Must Be Given.\n' \
%( THISPYFILENAME, defName )
print >> sys.stderr, msg
sys.exit(1)
#-----
return (enabledMsgs, fileArgs, opts)
#end ProcessArgs
#----------------------------------
def ListImageDict( self, imageDict ) :
""" Simple DEBUG utiliy to list all an imageDict's values
except for the image data.
"""
defName = DefName() # For DEBUG
print '\n---- imageDict :'
for imgObj in imageDict.itervalues() :
print ' baseName = %s' %( imgObj.baseName )
print ' createdExt = %r' %( imgObj.createdExt )
print ' mainName = %s' %( imgObj.mainName )
print ' idName = %s' %( imgObj.idName )
print
#end for
#end def
#------------------------------------------------------------------------------
def SortFilenames( self, fileArgs, enabledMsgs ) :
""" Sorts a list of filenames into sets:
1) inPyImageFilesList - a list of pyImage files to be input;
2) outPyImageFileName - the pyImages filename intended to be written;
3) imageFileList - a list of image files to add the the output pyImages file.
At minimum, one pyImages filename must be given in the args.
The last given pyImages file will be the output pyImages file.
This determines where the output pyImages file will be written.
It doen't have to exist if 1 or more previous existing piImages.py files
have been given.
A lone given pyImages filename will be both input and then overwritten.
"""
defName = DefName() # For DEBUG
allPyImageFilesList = list()
imageFileList = list()
# Sort the filenames in two groups: 1) PyImages files, 2) image files.
for filename in fileArgs :
if filename.lower().endswith( '.py' ) : # A pyImages filename.
allPyImageFilesList.append( filename )
else : # Must be an image filename.
if os.path.exists( filename ) :
imageFileList.append( filename )
else :
if ('warning' in enabledMsgs) :
print 'WARNING: Input Image File DOES NOT EXIST [ %s ]' \
%( filename )
#end if os.path.exists
#end if filename.lower().endswith( '.py' )
#end for filename in fileArgs
# Create inpPyimgFileList and outPyImageFileName from allPyImageFilesList.
numTotalPyImgFiles = len( allPyImageFilesList )
inPyImageFilesList = list()
if (numTotalPyImgFiles == 0) :
print >> sys.stderr, 'ERROR: %s::%s: NO GIVEN Output PyImages Filename\n' \
%( THISPYFILENAME, defName )
sys.exit(1)
#-----
else :
# It's not necessary that this file already exist.
outPyImageFileName = allPyImageFilesList[ -1 ] # ALWAYS the last filename in the list.
if numTotalPyImgFiles == 1 :
pass # DON'T include the output .py file.
else : # numTotalPyImgFiles >= 2
allPyImageFilesList = allPyImageFilesList[ :-1 ] # Check all but the last the given files.
for anInpPyImgFile in allPyImageFilesList : # The last is ALWAYS the output file.
if (not os.path.exists( anInpPyImgFile )) :
if ('failure' in enabledMsgs) :
msg = 'FAILURE: Given Input PyImages File DOES NOT EXIST:\n [ %s ]' \
%( anInpPyImgFile )
print msg
else :
inPyImageFilesList.append( os.path.abspath( anInpPyImgFile ) )
#end for
#end if
#end if
if (not imageFileList) :
if ('note' in enabledMsgs) :
print 'NOTE: NO GIVEN Image Files to Encode\n'
""" DEBUG
print '$$$$ inPyImageFilesList'
print ' ', inPyImageFilesList
print
print '$$$$ outPyImageFileName'
print ' ', outPyImageFileName
print
print '$$$$ imageFileList'
print ' ', imageFileList
print
"""
return inPyImageFilesList, outPyImageFileName, imageFileList
#end SortFilenames def
#----------------------------------
def ImportPyImages( self, inpPyImgFileNameGiven, imageDict, enabledMsgs ) :
""" Import the pyImages file and add its images to imageDict{}.
The file's existance is expected to have been already verified.
"""
defName = DefName() # For DEBUG
inpPyImgFilePath = os.path.abspath( inpPyImgFileNameGiven )
inPyImagesFileDir, inPyImagesFileName = os.path.split( inpPyImgFilePath )
# Tempoirarily add to sys.path in case the pyImages file is located somewhere
# other then os.cwd().
sys.path.insert( 0, os.path.join( inPyImagesFileDir ) )
# Remove the file extension to be able to import the file.
pyImagesFileMainName, pyImagesFileExt = os.path.splitext( os.path.basename( inpPyImgFileNameGiven ) )
pyImportStr = 'from %s import *' %( pyImagesFileMainName )
if (os.path.exists( os.path.abspath( inpPyImgFileNameGiven ) )) :
try :
exec( pyImportStr )
except : # Is a FAILURE, but not a fatal error.
if ('failure' in enabledMsgs) :
if os.path.exists( inpPyImgFileNameGiven ) :
print >> sys.stderr, 'FAILURE: PyImages File Has BAD PYTHON SYNTAX [ %s ] in:' \
%( inPyImagesFileName )
print >> sys.stderr, ' [ %s ]' %( inPyImagesFileDir )
#end if
del sys.path[ 0 ] # Remove the temporary search path.
return imageDict # Return an empty dictionary.
#-----
#end try
else :
print >> sys.stderr, 'FAILURE: PyImages File DOES NOT EXIST [ %s ]' \
%( inpPyImgFileNameGiven )
#end if
del sys.path[ 0 ] # Remove the temporary search path.
# Check if the Py file is actually a PyImages file.
try:
catalog.iteritems() # Should have been defined
except NameError :
if ('failure' in enabledMsgs) :
msg = 'FAILURE: NOT A PYIMAGES File: [ %s ]' %( inpPyImgFileNameGiven )
print >> sys.stderr, msg
#end if
return imageDict
#-----
#end try
# Assume, for now, that the key is a baseName and not a mainName.
for baseName, catIdName in catalog.iteritems() :
# Construct the callable function name from the catalog's idName.
funcStr = 'GetData_' + catIdName + '()'
pngImageData = eval( funcStr )
# Encode the binary data into viewable 7-bit characters.
encPngData = B64EncodeBinaryData( pngImageData )
# Create an ImageObject for each encoded image and add it to imageDict.
# Assume that the baseName from the catalog dict has an extension appended.
# ImageObject () will create a nominal extName if none exists in baseName.
imgObj = ImageObject( idName=catIdName, baseName=baseName, encPngData=encPngData )
newIdName = imgObj.idName # Extract the possibley-corrected idName.
# Check if idName already exists.
alreadyInDict = False
for anIdName in imageDict.iterkeys() :
# imageDict keys are the corrected idNames.
if (newIdName == anIdName) :
alreadyInDict = True
break # Search no further - dictionaries can't have duplicate keys.
#-----
#end for
baseName = imgObj.baseName
if alreadyInDict :
if ('warning' in enabledMsgs) :
print 'WARNING: REDEFINING PyImage: [ %s ] Original Filename: [ %s ]' \
%( newIdName, baseName )
else :
if ('note' in enabledMsgs) :
print 'NOTE: Reading PyImage: [ %s ] Original Filename: [ %s ]' \
%( newIdName, baseName )
#end if
# Use the extension-appended idName for the key,
# not the original, possibly extension-less idName read from the pyImages file.
imageDict[ imgObj.idName ] = imgObj
#end for baseName, catIdName in catalog.iteritems()
return imageDict
#end ImportPyImages def
#----------------------------------
def WritePyImagesFileHeader( self, pyImagesFile ) :
""" Writes syntactically correct Python statements to the output pyImages file.
"""
defName = DefName() # For DEBUG
pyImagesFile.write( '#' + '-'*69 + '\n\n' )
line = '# This file was generated by %s\n\n' %( THISPYFILENAME )
pyImagesFile.write( line )
pyImagesFile.write( 'from wx.lib.embeddedimage import PyEmbeddedImage\n' )
pyImagesFile.write( '\n' )
pyImagesFile.write( 'catalog = {}\n' )
#end WritePyImagesFileHeader def
#----------------------------------
def WritePyImageDataAndFuncs( self, imgObj, pyImagesFile, enabledMsgs ) :
""" Writes the Python code to the output pyImages file that both defines image data
and function defs that can read generate the associated image data, wx.Image,
wx.Bitmap and wx.Icon objects when its pyImmages file is imported by a Python app
and the appropriate function calls are made.
"""
defName = DefName() # For DEBUG
pyImagesFile.write( '#' + '-'*69 + '\n\n' )
pyImagesFile.write( '%s = PyEmbeddedImage( \n%s\n' \
%( imgObj.idName, imgObj.encPngData) )
pyImagesFile.write( ' )\n\n' ) # Data definition statement termination
# When the PyImages file is imported the following dictionary idName value
# will become part of the function names.
pyImagesFile.write( 'catalog["%s"] = "%s"\n' %( imgObj.baseName, imgObj.idName) )
pyImagesFile.write( 'GetData_%s = %s.GetData\n' %( imgObj.idName, imgObj.idName ) )
pyImagesFile.write( 'GetImage_%s = %s.GetImage\n' %( imgObj.idName, imgObj.idName ) )
pyImagesFile.write( 'GetBitmap_%s = %s.GetBitmap\n' %( imgObj.idName, imgObj.idName ) )
pyImagesFile.write( 'GetIcon_%s = %s.GetIcon\n' %( imgObj.idName, imgObj.idName ) )
pyImagesFile.write( '\n' )
""" DEBUG
print '$$$$ Image2PyFile::ImageFileEncodeAndWrite:'
print ' '*8 + 'Embedding image as callable identifier [ %s ]' %( imgObj.idName )
"""
#end WritePyImagesFileFunctions def
#end Image2PyFile class
__all__ = [ Image2PyFile ]
#------------------------------------------------------------------------------
#==============================================================================
#------------------------------------------------------------------------------
class ImageObject() :
"""Encoded image data and meta information storage.
A collection of useful attributes created when reading image data from
existing pyImages files. This also contains all info needed for generating
a new embeddable PyImage filew encoded image entry.
"""
def __init__( self, idName='', baseName='', mainName='', fileExt='', encPngData='' ) :
defName = 'ImageObject()'
# Instantiate, while documenting, all the necessary attributes.
self.idName = idName # Suitable for use as a Python identifier.
self.baseName = baseName # The image's source file basename.
self.mainName = mainName # The "main" part of the source basename
self.fileExt = fileExt # The extension of the image source file basename
self.createdExt = False # First assume a baseName was originally supplied.
self.encPngData = encPngData # Image's .PNG file binary data
# All the most common 3-letter image file extensions that wxPython can read.
# To Do: jpeg, tiff, any other non-3-letter image file extensions (if there are any).
IMG_EXTS = [ '.bmp', '.gif', '.ico', '.jpg', '.png', '.tif' ]
if baseName : # [is given]; A file extension may or may not be appended.
extLen = 4 # Includes the leading dot char.
extStartIndex = len( self.baseName ) - extLen # Doesn't now allow for 4-letter ext's.
# Is the file extension appended to the mainName ?
if self.baseName.lower()[ extStartIndex: ] in IMG_EXTS :
self.mainName, self.fileExt = os.path.splitext( baseName )
else : # File extension is not appended: Asume a .PNG file.
self.mainName = self.baseName
self.fileExt = '.png'
self.createdExt = True
self.baseName = self.baseName + self.fileExt
elif self.mainName : # [is given] Has no fileExt
if self.fileExt : # The fileExt is defined, so create the baseName.
if not self.fileExt.startswith( '.' ) :
self.fileExt = self.fileExt + '.'
self.baseName = self.mainName + self.fileExt
else : # No fileExt defined - create a reasonable one.
print >> sys.stderr, '\nERROR: %s::%s: NEITHER baseName NOR mainName Given.' \
%( THISPYFILENAME, defName )
sys.exit(1)
#-----
#end if self.baseName is defined
self.idName = String2Identifier( self.baseName )
#end __init__
#end ImageObject class
#------------------------------------------------------------------------------
def WhatsInstalled() :
"""
List the versions of Python and wxPython.
"""
defName = DefName() # For DEBUG
# Which vesrions of Python and wxPython are installed ?
import os, sys, platform
print
print defName + '():'
if os.name == 'nt' :
print 'Windows ', platform.win32_ver()[1]
else :
print 'Platform ', platform.system()
#end if
print 'Python ', sys.version
addon_pkgs = [ ('Wx Version', 'wx.VERSION_STRING'),
('Wx Pltform', 'wx.PlatformInfo'), ]
for addonStr, attribute in addon_pkgs :
try :
print addonStr, eval( attribute )
except NameError :
print
#end try
#end for
print
#end WhatsInstalled def
#------------------------------------------------------------------------------
def CallersName():
return sys._getframe(2).f_code.co_name
#------------------------------------------------------------------------------
# Credit to Alex Martelli, "Python Cookbook" p. 440
def DefName() :
"""
Returns the name of the function calling DefName.
Does not work inside class __init__() definitions.
"""
import sys
return sys._getframe(1).f_code.co_name + '()'
#end def
#------------------------------------------------------------------------------
def String2Identifier( s ) :
"""
Simple character substitution to produce a legal Python identifier string.
"""
defName = DefName() # For DEBUG
letters = []
for letter in s :
if not letter.isalnum() :
letter = '_'
letters.append( letter )
#end for
if not letters[ 0 ].isalpha() and letters[ 0 ] != '_' :
letters.insert( 0, '_' )
identifierString = ''.join( letters )
return identifierString
#end String2Identifier def
#------------------------------------------------------------------------------
def B64Encode( s, altchars=None ) :
"""
Encode a string using Base64. Meant for processing binary strings
into readable characters.
Optional altchars must be a string of at least length 2 (additional
characters are ignored) which specifies an alternative alphabet for
the '+' and '/' characters. This allows an application, e.g.,
to generate a url or filesystem-safe Base64 strings.
The encoded string is returned.
"""
defName = DefName() # For DEBUG
# Eliminate the trailing newline returned.
encoded = binascii.b2a_base64( s )[ :-1 ]
if altchars :
encoded = _translate( encoded, {'+': altchars[0], '/': altchars[1]} )
return encoded
#end B64Encode def
#------------------------------------------------------------------------------
def BitmapToPngFile( wxBmap, outFileDir=None, outFileName='', enabledMsgs=None ) :
"""
Save a wx.Bitmap to a PNG file. The binary contents of this file is intended
to be b64 encoded in order to save the encoded data to the output pyImages file.
Returns None if any error occurs.
"""
defName = DefName() # For DEBUG
if outFileName :
outFilePathname = outFileName
else :
newMainName = os.path.basename( os.path.splitext( imgFilename )[0] )
newfileBasename = newMainName + '.png'
outFilePathname = os.path.join( outFileDir, newfileBasename )
#end if
if wxBmap.SaveFile( outFilePathname, wx.BITMAP_TYPE_PNG ) : # SaveFile() success
return True
else : # wx.Bitmap.SaveFile() has failed.
if ('failure' in enabledMsgs) :
msg = '\nFAILURE: CAN\'T WRITE Temporary wx.Bitmap to .PNG file.\n'
print >> sys.stderr, msg
#end if
# Try a different save tactic.
wxImage = wx.ImageFromBitmap( wxBmap ) # ? Avoid some early wx version limitation ?
if wxImage.SaveFile( outFilePathname, wx.BITMAP_TYPE_PNG ) :
return True
else :
msg = '\nERROR: CAN\'T WRITE Temporary wx.Image .PNG File: [ %s ]\n\n' \
%( outFilePathname )
print >> sys.stderr, msg
sys.exit(1)
#end if
#end if wxBmap.SaveFile()
#end BitmapToPngFile def
#------------------------------------------------------------------------------
def CreatePngFileData( imgFilename, enabledMsgs ) :
"""
Encode a PNG file's lossless-compressed binary image data
into a single, big b64 string.
"""
defName = DefName() # For DEBUG
if not os.path.exists( imgFilename ) :
if ('warning' in enabledMsgs) :
msg = '\nWARNING: Image File Doesn\'t Exist[ %s ].' %( imgFilename )
print msg
return None
#-----
# Predefine an error message in case it's needed.
# It may get used for one of 2 different errors.
msg = '\nFAILURE: Image File is UNREADABLE [ %s ]' %( imgFilename )
try :
wxBmap = wx.Bitmap( imgFilename, wx.BITMAP_TYPE_ANY )
except :
if ('failure' in enabledMsgs) :
print >> sys.stderr, msg
return None
#-----
# Handle bad image file data
if (not wxBmap.Ok()) and ('failure' in enabledMsgs) :
print >> sys.stderr, msg # Same msg string from above.
##print '5'*70 # DEBUG
return None
#-----
# Read the original image file and write it to a new PNG file.
tmpPngFilename = tempfile.mktemp()
success = BitmapToPngFile( wxBmap, None, tmpPngFilename, enabledMsgs )
if not success :
print >> sys.stderr, '\nERROR: CAN\'T WRITE to Temporary PNG File.\n' \
%( THISPYFILENAME, defName )
return None
#-----
# Encode the PNG file's lossless-compressed binary image data into a single, big b64 string.
pngFile = open( tmpPngFilename, 'rb' )
pngImageData = pngFile.read()
pngFile.close()
os.remove( tmpPngFilename )
return pngImageData
#end CreatePngFileData def
#------------------------------------------------------------------------------
def B64EncodeBinaryData( pngImageData ) :
"""
B64 encodes a binary byte string. Returns a list of lines of strings
suitable for directly embedding into a PyImages file.
"""
defName = DefName() # For DEBUG
# Encode the PNG file's lossless-compressed binary image data into a single, big b64 string.
encPngImgData = B64Encode( pngImageData )
# Chop the long b64 character-encoded encPngImgData into manageable
# line lengths for writing to a file.
linesOfEncPngImgData = list() # b64 linesOfEncPngImgData list.
while encPngImgData :
aLineOfEncPngImgData = encPngImgData[ :72 ] # A chunk length of 72 chars
encPngImgData = encPngImgData[ 72: ] # The remainder of data to be encoded.
aLineOfEncPngImgData = ' "%s"' %( aLineOfEncPngImgData )
linesOfEncPngImgData.append( aLineOfEncPngImgData ) # Add to linesOfEncPngImgData list.
#end while encPngImgData
linesOfEncPngImgData = '\n'.join( linesOfEncPngImgData )
return linesOfEncPngImgData
#end B64EncodeBinaryData def
#==============================================================================
if __name__ == '__main__' :
#WhatsInstalled() # List this platform's Puthon and wxPython version info.
"""
try :
#print "\n$$$$$$$$ getattr( sys, 'frozen', '' ) = [ %r ]" %( getattr( sys, 'frozen' ) )
print
except AttributeError :
print "\nAttributeError: 'module' object has no attribute 'frozen'\n"
"""
cmdLineArgs = sys.argv[ 1: ]
i2p = Image2PyFile( cmdLineArgs )
#print '\ni2p.__doc__ :\n', i2p.__doc__
#end if
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.
