EnVe Python ens_utils Module
The ens_utils
module is a collection of
high-level EnSight and EnVe routines available to speed up your programming workflow.
These modules fit between the EnVe application and the
enve
module: they do some of the high-level manipulations
of the EnVe application while they are still useable in your
EnSight Python code. The code in the ens_utils.py
module also
serves to illustrate the usage of the low-level movie and image functions. These
routines can enhance your post-post processing productivity. For example, you might want
to convert a number of files into a movie. You would simply import the
ens_utils
module and find your module from the description
below and use it. Or, look it up in the python source to see how it works if you want to
understand the enve
module in detail in action.
The ens_utils
module is included in the
following directory.
$CEI/site_preferences/extensions/ens_utils.py
and is easily imported as follows:
import ens_utils as eu
Edit the ens_utils.py and find the enve routines and take a look at them as they are discussed below. The detailed, low-level enve functions that are used will be discussed in the movie and image sections below.
A Dictionary of the Codecs: eu.codec_dictionary()
The enve
module has a number of codecs
designed to read and write movies and images. All of the packages installed with
EnSight (EnVe, EnVideo and
EnSight) use these codecs, so that you are guaranteed to be able to read and write your
movies and images on all platforms that we support. So the first thing you might need to
do is to get a listing of the supported codecs and the extensions. The second thing you
might want to do is to get a listing of what options are available for controlling the
output of each of these formats. To use it in your python, do the following:
import ens_utils as eu
#
# Get a dictionary of all codecs
#
cdict = eu.codec_dictionary()
cdict['name']
will have a list of all of the
codec names:
['AVI', 'BMP', 'EVO', 'FLV',
'GIF', 'JPG', 'MPEG', 'MPEG4', 'PNG', ...]
cdict['ext']
will provide a list of all the
appropriate extensions for each of these names:
Note: Some codec names have multiple extensions
[['.avi'], ['.bmp'], ['.evo'],
['.flv'], ['.gif'], ['.jpg', '.jpeg'], ['.mpg', '.mpeg', '.mp4'], ['.mp4'],
['.png'],...]
cdict["name"][0]
is the codec name with the
extensions in cdict["ext"][0]: 'AVI' corresponds to the '.avi'
extension
Take a look at the comments in the ens_utils.py
file for the codec_dictionary()
function as
follows:
################################################################### # # returns an enve codec dictionary # IN # If both inputs are empty (default) then you get a list of ALL # enve codecs # If name OR ext are defined then you get a list of codecs that # match either. # name = codec name, for example, 'MPEG4', 'PNG'. Note since codec names are # all CAPITAL letters the name is converted to all upper # prior to comparison, so it is case insensitive # ext = codec suffix for example, '.mpg', '.png'. Note since all codec # suffixes start with a '.', a missing '.' is added prior to # comparison and all ext are converted to lower so it is # case insensitive. # the_type = 'movie' - returns only movie formats that can store # multiple frames in one file # 'image' - returns only image formats that can store # one frame per file # 'all' - returns both movie and image formats # # OUTPUT # A Dictionary with the following KEYS: # # 'name' - a list of all the codec names available # 'ext' - a list of lists of recognized extensions # corresponding to the name list above # 'desc' - a list of detailed descriptions of the # codecs corresponding to the name list abvoe # 'stereo' - a list of True or False whether the codec # supports stereo # 'single file' - a list of True or False whether the # True means all frames in one file # False means one frame per file # 'options' - a list of lists corresponding to the codec # name list as follows: # [[name,'type',[choices], default, detailed descrip], # [name2, 'type',[choices], default, detailed descrip],... ] # name is the option name # 'type' is 'BOOL', 'INT', 'FLOAT', 'CHOICE' # [choices] is # [0,1] for BOOL # [min,max] for INT or FLOAT (a range of choices) # ['choice1', 'choice2',...'choiceN'] a list of text choices for CHOICE # default is the default choice for this option # detailed description is the complete option description # def codec_dictionary(name="", ext="", the_type='all'):
Mapping Name to File Extension: get_codec_extension and get_codec_name
Sometimes it is useful to parse a filename extension and then ask
enve
if it has a codec for that extension. Or, if you are going to save
an image, the enve
image save decides on what codec to use based on the
filename extension, so you want to be able to name the file appropriately prior to
saving it.
import ens_utils as eu print("\n\nName to Extension") for cdt in cdict['name']: print("{} {}".format(cdt, eu.get_codec_extension(cdt))) print("\n") print("\n\nExtension to Name") for ext in cdict['ext']: for ee in ext: print("{} {}".format(ee, eu.get_codec_name(ee))) print("\n")
Has the following output
Name to Extension AVI ['.avi'] BMP ['.bmp'] EVO ['.evo'] FLV ['.flv'] GIF ['.gif'] JPG ['.jpg', '.jpeg'] MPEG ['.mpg', '.mpeg', '.mp4'] MPEG4 ['.mp4'] PNG ['.png'] PPM ['.ppm', '.pgm', '.pbm', '.pnm'] MOV ['.mov'] SGI ['.rgb', '.bw', '.sgi'] SM ['.sm'] SWF ['.swf'] TIFF ['.tif', '.tiff'] XPM ['.xpm']
Extension to Name .avi AVI .bmp BMP .evo EVO .flv FLV .gif GIF .jpg JPG .jpeg JPG .mpg MPEG .mpeg MPEG .mp4 MPEG .mp4 MPEG .png PNG .ppm PPM .pgm PPM .pbm PPM .pnm PPM .mov MOV .rgb SGI .bw SGI .sgi SGI .sm SM .swf SWF .tif TIFF .tiff TIFF .xpm XPM
Print out Movie Codecs and Image Codecs: eu.codec_dictionary()
import ens_utils as eu print("\n\nImage formats:") print(eu.codec_dictionary("","","image")) print("\n\nMovie formats:") print(eu.codec_dictionary("","","movie"))
Convert a movie from one format to another
eu.convert_movie import ens_utils as eu # and convert the original evo file to all other movie types: # out_mov.evo, out_mov.avi, out_mov.mpg, etc. in_mov = "/path/file.mp4" # full filename with extension out_pref = "/path/new_file" # file prefix out_form="AVI" # one of the allowable formats ret_val = eu.convert_movie(in_mov, out_pref, out_form)
Code Comment Details
# # This will convert a movie # opts is a text string: "optname optchoice optname2 optchoice2" # example for AVI: 'Compression MPEG4V2 BitRate 20000 ' # def convert_movie(infile, outfile_prefix, out_format='EVO', opts=""):
Get Movie Info Metadata: eu.get_movie_info
import ens_utils as eu in_mov = "C:/Users/ensight/Documents/test.evo" in_mov_info = eu.get_movie_info(in_mov) for ky in in_mov_info.keys(): print("# {} {}".format(ky, eu.get_movie_info(in_mov)[ky])
Prints out the following
# nframes 21
# stereo 0
# repeat [0, 0]
# format EVO
# flip 0
# anaglyph 0
# filename C:/Users/ensight/Documents/test.evo
# realframes 21
# dims [737, 768]
# intensity [1.0, 1.0]
# framerange [0, 20]
# fps 30.0
# tiling [1, 1]
# options
Extract out a Movie Frame: eu.extract_frame()
# Extract second to last frame # of a movie and write out as PNG import ens_utils as eu in_mov = "C:/Users/ensight/Documents/test.evo" out_prefix = "C:/Users/ensight/Documents/test2" mi = eu.get_movie_info(in_mov) fn = mi['nframes'] - 1 # second to the last frame eu.extract_frame(in_mov, out_prefix ,fn, "PNG")
Make a List of Images into a Movie: eu.images_to_mov()
# read in a bunch of tif images # and write them into each and every one of the # supported movie formats # # get info on all movie codecs import ens_utils as eu mdict = eu.codec_dictionary("","",'movie') # This searches out_dir for all the tif files file_list = eu.search_tree(out_dir,".tif",1) print(file_list) mv = "EVO" eu.images_to_mov(file_list, out_dir+"mov_tiff", mv)
Concatenate List of Movies & Convert Them to a New Format: eu.concatenate_movies()
import ens_utils as eu infile_list = ["/path/mov.avi","/path/mov.mp4",...] out_file_prefix = "/newpath/new_prefix" eu.concatenate_movies(infile_list, outfile_prefix, out_format="EVO")
Do a Diff of Two Movies Frame by Frame and Write out a New Movie: eu.movie_compare()
import ens_utils as eu mov1 = "/path/mov.avi" mov2 = "/path/mov.mp4" out_diff_prefix = "/path/mov_diff" eu.movie_compare(mov1,mov2,out_diff_prefix,"EVO")
Convert an Image to a Different Format: eu.convert_image()
import ens_utils as eu img = "/path/img.png" out_diff_prefix = "/path/new_image" new_format = "JPG" eu.convert_image(img,out_diff_prefix,new_format)
Get an Image from EnSight Graphics Window & Return enve Image: eu.get_ens_image()
import ens_utils as eu img = eu.get_ens_image()
Get a Dictionary of Info About an enve Image: eu.get_image_info()
import ens_utils as eu idict = eu.get_image_info(img) print(idict['dims'])
Compare Two Images by Doing a Diff on the Pixel by Pixel Diff: eu.image_compare()
import ens_utils as eu img = "/path/img.png" img2 = "/path/img2.png" outfile = "/path/out_diff.png" stat_dict = eu.image_compare(img1,img2,outfile) print(stat_dict)
Save an Image with a Transparent Background: eu.get_ens_image_trans()
import ens_utils as eu outfile = "/path/out_trans_bck.png" env_img = eu.get_ens_image_trans(outfile,annots=’dark’)
Tiling Two Movies or Images: eu.movies_tile_mtm()
This will write out an .mtm file that can be read into EnVideo to show two movies adjacent to each other. The default is to write an .mtm file with movies side by side. The movies must have the same number of frames. Mismatch
import ens_utils as eu infile_list = ["/path/file1.evo","/path/file2.evo"] out_file_prefix = "/path/file_mtm" err = eu.movies_tile_mtm(infile_list,out_file_prefix)
The EnVe Movie Object
This section will discuss the portion of the
enve
module that handles movies. The movie object is
created in READ or WRITE mode. In normal operation, the various movie attributes are set
after creation and then the object is open()
ed to begin the I/O process.
Once the file is open, some attribute values will change to match the actual values in
the files and some attributes will become read only until the file is closed. Movie
objects are associated with a filename. They contain a number of images that can be read
as well as attributes like dimensions, frames per second and stereo.
The movie object is used to open and read from or write to animation files. A simple function for reading a movie in one format and writing it to another format is shown below. It allows changing the options.
import enve # # This will convert a movie # opts is a text string: "optname optchoice optname2 optchoice2" # example for AVI: 'Compression MPEG4V2 BitRate 20000 ' def convert_movie(infile, outfile_prefix, out_format, opts=""): in_mov = enve.movie(enve.MOVIE_READ) out_mov = enve.movie(enve.MOVIE_WRITE) in_mov.filename = infile out_mov.filename = outfile_prefix in_ret = in_mov.open() if in_ret != 0: print("Failure to open input movie") print("'{}'".format(infile) return in_ret else: out_mov.format = out_format if len(opts) > 0: out_mov.options = opts out_mov.addcount(in_mov) out_mov.open() out_mov.append(in_mov) out_mov.close() in_mov.close() # filename1 = r"C:\Users\ensight\Documents\test.evo" filename2 = r"C:\Users\ensight\Documents\test_out" # example options for AVI options = 'Compression MJPEG BitRate 30000 ' convert_movie(filename1,filename2+"AVI_demo","AVI",options) # this will step through all the available formats and convert the # test.evo file to test_out.suffix where suffix is the format suffix # Note if the output format is an image format then only a single image of the # last timestep will be saved. # clist = enve.codecs() for cc in clist: convert_movie(filename1,filename2,cc[0])
Here is an example of loading a series of .png images and writing them out as an .evo movie.
import enve # # Sequentially numbered images can be read directly as # a movie using '#' characters as the numerical field # and an '@' character where the 'l','r' characters go. # # Convert images named: sample00.png, sample01.png, ... # mov = enve.movie(enve.MOVIE_READ) mov.filename = r"d:\Users\rjfrank\Desktop\stereo\sample##.png" err = mov.open() if (err == 0): evo = enve.movie(enve.MOVIE_WRITE) evo.filename = r"d:\Users\rjfrank\Desktop\stereo\sample_output" evo.format = "EVO" evo.stereo = mov.stereo evo.addcount(mov) err = evo.open() if (err == 0): evo.append(mov) else: print("Error: {}".format(evo.errstr())) evo.close() mov.close() else: print("Error: {}".format(mov.errstr())) # # A stereo example: files00l.png, files00r.png, files01l.png, # files01r.png, ... # mov = enve.movie(enve.MOVIE_READ) mov.filename = r"d:\Users\rjfrank\Desktop\stereo\files##@.png" # once you open the move below, you write the header err = mov.open() if (err == 0): evo = enve.movie(enve.MOVIE_WRITE) evo.filename = r"d:\Users\rjfrank\Desktop\stereo\sample_output_stereo" evo.format = "EVO" evo.stereo = mov.stereo evo.addcount(mov) err = evo.open() if (err == 0): evo.append(mov) else: print("Error: {}".format(evo.errstr())) evo.close() mov.close() else: print("Error: {}".format(mov.errstr()))
Here is another example that creates a movie.
import enve # # Generic examples using naturally ordered images. # Note: this approach handles the case where the sizes # of the images might differ as it is not legal to have # frames of different sizes in a movie. movie.append(image) # will rescale each image to match the dimensions of the # output movie. # import glob # Get a list of filenames and sort them alphabetically wildcard = r"d:\Users\rjfrank\Desktop\stereo\sample*.png" filenames = glob.glob(wildcard) filenames.sort() # start the output movie evo = enve.movie(enve.MOVIE_WRITE) evo.filename = r"d:\Users\rjfrank\Desktop\stereo\sample_natural" evo.format = "EVO" # set the size of the frames using the first image # the other images will be scaled to the size of this image img = enve.image() err = img.load(filenames[0]) if (err != 0): print("Unable to set output movie size") evo.dims = tuple(img.dims) # set the number of frames evo.addcount(len(filenames)) # process all images err = evo.open() if (err == 0): for file in filenames: err = img.load(file) if (err != 0): print("Error reading: {}".format(file)) err = evo.append(img) evo.close() else: print("Error: {}".format(evo.errstr()))
Here is an example that creates a stereo movie.
import enve # # Example of image processing on a movie to create # another. In this example, if the source movie is # in stereo, it will swap the right and left images. # mov = enve.movie(enve.MOVIE_READ) mov.filename = r"d:\Users\rjfrank\Desktop\stereo\stereo_example.evo" mov.open() evo = enve.movie(enve.MOVIE_WRITE) # Note: the extension is added automatically. evo.filename = r"d:\Users\rjfrank\Desktop\stereo\stereo_example_rev" evo.format = "EVO" evo.options = "Compression RLE" evo.stereo = mov.stereo # addcount() sets the number of output frames as well # as the frame size err = evo.addcount(mov) if (err < 0): print("Count error: {}".format(evo.errstr())) err = evo.open() if (err < 0): print("Open error: {}".format(evo.errstr())) for i in range(mov.nframes): print("Working on frame: {}".format(i)) # if this is a stereo movie, getframe() will return # a list of enve.image() objects in [right,left] order. pair = mov.getframe(i) # swap the images pair.reverse() # add them to the other movie (make sure to use a tuple) err = evo.append(tuple(pair)) if (err < 0): print("Save error: {}".format(evo.errstr())) evo.close() mov.close()
Now, let's look at each of the enve movie methods and attributes used to create, load, modify and save enve movies. The following methods and attributes can be listed in EnSight Python as follows:
import enve dir(enve.movie)
The EnVe Movie Object
The EnVe movie object provides read and write access to a number of common animation file formats. The various methods are described here:
|
|||
Creates an empty movie object in read or write mode. No actual I/O operations
will be started until the |
|||
|
|||
Write movies must know in advance how many frames will be added before
the file is |
|||
|
|||
If a WRITE movie is |
|||
|
|||
This method completes all I/O operations with a given movie. The physical file on disk will be valid after this method is called. |
|||
|
|||
If any of the methods return an error (-1), a string describing the error will be stored in the movie object. These error strings can be accessed via this method. |
|||
|
|||
This method extracts a frame from a movie and returns a list of image objects. There may be one or two images returned (two in the case of a hardware stereo source). If two images are returned, the first is the left eye image and the second is the right eye image. The framenum is [0,x.nframes-1]. The returned frame is intensity and repeat adjusted as specified by those attributes. This method can only be used on a READ movie. The return is either a list (success) or an int (fail). On error, this returns the integer -1 so, do the following: image = x.getframe(framenum) if type(image) == int: print("Error") return image |
|||
|
|||
This method opens the physical movie file. In the case of a WRITE file, it will begin the encoding process. |
|||
|
|||
This function resets the current nframes count on a WRITE movie to 0. This can be called if the movie is not currently open. |
|||
|
|||
Prints basic information about the movie x. |
|||
|
|||
These get and set any of the various movie object attributes. Movie attributes: |
|||
|
Returns a list of the attributes this object supports. Read only list. |
||
|
Returns a list of the methods this object supports. Read only list. |
||
|
The filename to use. Read/write string. |
||
|
This attribute is non-zero if the movie supports HW stereo (on read) or if the movie has been set to output HW or anaglyph stereo (on write). Read/write int. If stereo is set to non-zero for a WRITE movie then the append function should include tuples of images representing the left and right images. |
||
|
The framerate for movie playback in frames per second. Read/write float. |
||
|
The dimensions of the movie frames in pixels. Read/write tuple of two ints: (dx, dy) |
||
|
If the output movie should be written as an MTM file (see Multi-Tiled Movie (MTM) File Format ) this attribute specifies the number of tiles in the X and Y axis. Read/write tuple of two ints: (dx, dy) |
||
|
This attribute specifies the format for the movie. See:
|
||
|
For a read movie, this attribute allows one to select a subset of the input frames to read. For example, (10,20) will cause the movie to only output frames 10 through 20 inclusive (11 frames). Note: Framerange numbers start at 0 and run through x.realframes-1. Read/write tuple of two ints: (start, end) |
||
|
For a read movie, this is the effective number of frames in the file
(int), useable by |
||
|
The number of actual physical images in the file (the repeated frames are not in the total number of frames). It is the valid range for |
||
|
Format specific options in the form: "op1 value op2 value ...". See
|
||
|
Frames may have their intensity scaled linearly from the first to the last frame. This attribute allows this scaling to be set. The default is (1.0,1.0) or no intensity changes. Read/write tuple of two floats: (start, end) |
||
|
When reading from a file, the first and last frames may be repeated a number of times. This attribute allows the number of additional times those frames appear. For example, (5,3) will cause the first frame to be repeated 5 additional times (6 total) and the last frame 3 times (4 total). As a result, nframes will report 8 more frames in the movie. Note that the intensity interpolation includes these repeated frames. Read/write tuple of two ints: (start, end) |
||
|
If an output movie has stereo set, this attribute allows that stereo to be in anaglyph form. Valid values include:
Read/write int. |
||
|
When reading from a file, flip the frames about the
X or Y axis in memory (the original file is unchanged). If your object in
your movie moves left to right, and flip about the Y axis then it will move
right to left. Pixelated text will be flipped as well. Valid values are
formed by 'OR'ing: Read/write int. |
The EnVe Image Object
The EnVe image object provides read and write access to a number of common image file formats. Methods are included for basic image processing operations. The various methods are described here:
enve.CVF_IMG_FMT_A - alpha only
image
enve.CVF_IMG_FMT_L - luminance
only image (grayscale)
enve.CVF_IMG_FMT_LA -
luminance+alpha image
enve.CVF_IMG_FMT_RGB -
red,green,blue three channel image
enve.CVF_IMG_FMT_RGBA -
red,green,blue,alpha four channel image
EnVe image object processing operations
|
||
Create a
new image object. The default image is 100 by 100 in size and a format of
|
||
|
||
Prints basic information about the image x. |
||
|
||
The object supports the comparison of two images for pixel by pixel equality |
||
The attributes and methods can be listed separately as follows:
Note: The following members are not used:
And, there is no method for closing the file.
Both the methods and the attributes are listed together below in alphabetical order.
|
||
|
||
This method copies a rectangle of pixels from one image to the target. The
two images must have the same pixel format. The rectangles may lie outside
of the source or destination images. For source pixels that lie outside of
the source image, the backpixel value is used. The source pixels will be
scaled as needed (nearest neighbor sampling) to fill the destination
rectangle. The following are variable descriptions: |
||
|
||
This method blends the pixels of two images together according to four
blending mode functions (a color and alpha for each of the source and
destination images). Blending is performed by weighting each component of
the source and destination by a particular function and then summing the
results. The results are then clamped to the range [0,255] and stored in the
destination image. In addition to the images, a fixed color and alpha value
are supplied. These are used by some of the various expression combinations.
The formula take the following form:
The available weight functions include:
|
||
|
||
This method scans the input image and compares the color of each pixel
to the input pixel color ( |
||
|
||
This method performs simple linear algebra on an image. The math is performed
at floating point resolution and the results clamped to the range [0,255]
before being output. The math implemented is as follows:
|
||
|
||
This method computes a new image that is the pixel by pixel (component
by component) difference between image |
||
|
||
This attribute is used to get and set the image dimensions. Returns the
size of the image in the x and y dimensions. If set, it will resize the
image to the new |
||
|
||
If any of the methods return an error (-1), a string describing the error will be stored in the image object. These error strings can be accessed via this method. |
||
|
||
This method will flip an image in memory (original file is unchanged)
about one or more axis. If the image is facing left and you flip it about
the Y axis then the image will be facing right. This corresponds to the
Horizontal flip toggle in the application. The int parameter formed by
'OR'ing together the following: |
||
|
||
This attribute is not the format of the image in terms of the codec (AVI,
TIFF, PNG, etc.). That format is set using the suffix of the filename when
saving the file. The mapping of the suffices to the format is found in This format refers to the information in each pixel. If this is set to a different value, then it will change the image format to the new value (interpreting all pixel values). Valid values:
Read/write int. |
||
|
||
This method is the inverse of |
||
|
||
This method will return as a list, the current color at pixel
|
||
|
||
This method
returns an numpy ndarray with dimensions of (xdim * ydim * depth) and depth
is 3 for rgb, 4 for RGBA. So |
||
|
||
This method reads an image file and sets the current image object to its
contents. If the input file is an animation, the first frame is returned.
The method returns 0 on success or a negative integer on error. See
|
||
|
||
This is a legacy method for the Apple Mac that is no longer used. |
||
|
||
This method returns a string that is the representation of the image as an ASCII PPM file. This can be useful in interfacing to systems like Qt |
||
|
||
This method resizes the current image to the size specified by
|
||
|
||
This method saves the current image to disk in the specified filename. The
filename must have an extension, because the format is selected by the
filename extension. It is an error to give this a filename without an
extension (in contrast to the movie which uses a prefix without an
extension). The target file is overwritten without warning. The options
keyword allows the user to set specific format options (for example, compression)
like the |
||
|
||
This method will set the color of the pixel at position
|
||
|
||
This method takes as input a numpy ndarray and it creates and enve
image,
|
||
|
||
This method computes basic statistics on the image object. It computes
for all pixels and for all channels (a 10x10
|
||
|
||
This method extracts a rectangle of pixels from the image and returns a new image. The first tuple is the offset into the image and the last specifies the dx,dy in pixels. In the second form, the method simply clones the source image. |
||
|
||
This method allows the value of any channel of the image to come from
any other channel of the image. The array |
||
|
||
This method will return the pixel data in the image as a raw binary
Python string. There is one character in the
string for each component of each pixel. For example, if the image were
100x100 and in Note: The image dimensions and pixel format are not encoded in the string and that the string is actually raw binary data. This method can be used with packages such as matplotlib or numpy which provide mechanisms for interpreting such raw strings. |
||
These get and set object attributes are currently unused. |
||
|
Returns an index number that can be used to store a sequence number for this frame. Presently, this is unused. Read/write int. |
|
|
Returns the size of the image frame for which this image might be a subrect of. Presently, this is unused. Read/write tuple of ints (dx,dy). |
|
origin |
Returns the position (relative to the upper left corner) of the current image in the full image frame specified by the frame attribute. Presently, this is unused. Read/write tuple of ints (dx,dy). |
|
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
This is a |