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.