9.1. EnVe Extension Module Programming

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:

x = enve.movie(enve.MOVIE_READ|enve.MOVIE_WRITE)

Creates an empty movie object in read or write mode. No actual I/O operations will be started until the open() method is called. The proper usage is to create the movie object, set attributes on it (for example, filename, image size, number of frame in the case of writing) and then open() the file. At that point, the append() and getframe() methods will work. When done accessing image frames, the file should be close()ed and the object can be destroyed.

err = x.addcount(N|image|movie)

Write movies must know in advance how many frames will be added before the file is open()ed. This function is used to add frame counts to the movie. The input parameter can be an integer (number of frames) an image object (adds one frame) or another movie (open() and in READ mode, which adds the number of frames in the movie). In the latter two cases, the target movie may change its dimensions or frame rate to match the added objects. This will happen if the current dimensions or fps are <= 0. The return value is the number of frames, or -1 on error. x.nframes is updated to reflect this as well. If addcount() is only called with an integer number of frames, the caller must also set the dims attribute to set the size of the output movie in pixels.

err = x.append(image|image_tuple|movie[,object=obj][,method=meth][,smooth=sm])

If a WRITE movie is open(), this method is used to physically add an image, image tuple of two images for stereo, or the frames in a movie to the current movie. The input frames will be scaled to match the dimensions of the target. Returns 0 if successful. If the caller specifies the OBJECT and METHOD keywords to an object reference and the name of a method, this function will periodically call object.method(n) where n is the number of the frame currently being worked on. This method should return 1 if the operation is to be aborted or 0 if processing should continue. By default, this method uses nearest neighbor sampling to scale images. If a higher quality scaling is desired, set the SMOOTH keyword to the value enve.CVF_SCALE_SMOOTH to select box filtered scaling.

err = x.close()

This method completes all I/O operations with a given movie. The physical file on disk will be valid after this method is called.

str = x.errstr()

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.

image = x.getframe(framenum)

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

err = x.open()

This method opens the physical movie file. In the case of a WRITE file, it will begin the encoding process.

err = x.resetcount()

This function resets the current nframes count on a WRITE movie to 0. This can be called if the movie is not currently open.

print(x)

Prints basic information about the movie x.

 

These get and set any of the various movie object attributes.

Movie attributes:

__members__

Returns a list of the attributes this object supports. Read only list.

__methods__

Returns a list of the methods this object supports. Read only list.

filename

The filename to use. Read/write string.

stereo

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.

fps

The framerate for movie playback in frames per second. Read/write float.

dims

The dimensions of the movie frames in pixels. Read/write tuple of two ints: (dx, dy)

tiling

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)

format

This attribute specifies the format for the movie. See: enve.codecs() for a list of formats. Read/write string.

framerange

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)


nframes

For a read movie, this is the effective number of frames in the file (int), useable by x.get_frame(framenum)

realframes

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 getframe(X)). It is equal to: frameend-framestart+repeatstart+repeatend. Readonly int.

options

Format specific options in the form: "op1 value op2 value ...". See enve.codecs() for a list of format options and the example script for how to create them. Read/write string.

intensity

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)

repeat

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)

anaglyph

If an output movie has stereo set, this attribute allows that stereo to be in anaglyph form. Valid values include:

enve.MOVIE_ANAGLYPH_NONE - use HW stereo (shutter glasses)

enve.MOVIE_ANAGLYPH_REDBLUE

enve.MOVIE_ANAGLYPH_BLUERED

enve.MOVIE_ANAGLYPH_REDCYAN

enve.MOVIE_ANAGLYPH_CYANRED

Read/write int.

flip

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: enve.CVF_FLIP_XAXIS and/or enve.CVF_FLIP_YAXIS

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

x = enve.image()

Create a new image object. The default image is 100 by 100 in size and a format of enve.CVF_IMG_FMT_RGB .

print(x)

Prints basic information about the image x.

x == y

The object supports the comparison of two images for pixel by pixel equality

The attributes and methods can be listed separately as follows:

x._methods__

x.__members__


Note:  The following members are not used:

frame, origin, and framenumber.

And, there is no method for closing the file.

x.close()

Both the methods and the attributes are listed together below in alphabetical order.

dir(enve.image())


x.bitblt(src,spos,ssize,pos,size,mode,backpixel)

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: src is an enve.image() object to use as the pixel source, spos is the origin of the pixels in the source image (a tuple of two ints), ssize is the rectangle (dx,dy) of the pixels in the source image (a tuple of two ints), pos is the origin location of the pixels in the destination image (a tuple of two ints), size is the rectangle (dx,dy) of the pixels to paint in the destination (a tuple of two ints), mode - The operation mode can be a simple copy (enve.CVF_BITBLT_COPY ), where source pixels replace destination pixels or it can be a masked copy (enve.CVF_BITBLT_ALPHAMASK ) where source pixels only replace destination pixels if they have a non-zero alpha channel, and backpixel is a tuple of 4 integers (Red,Green,Blue,Alpha).

x.blend(src,srcCM,srcAM,dstCM,dstAM,fixedcolor,fixedalpha)

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. fixedcolor is a tuple of four integers ( enve.CVF_IMG_FMT_RGBA ) and fixedalpha is a single integer.

The formula take the following form:

dst'(RGB)=(dst(RGB)*dstCModeWeight)/255+(src(RGB)*srcCModeWeight)/255

dst'(A) =(dst(A) *dstAModeWeight)/255+(src(A) *srcAModeWeight)/255

srcCM selects the function for determining srcCModeWeight

srcAM selects the function for determining srcAModeWeight

dstCM selects the function for determining dstCModeWeight

dstAM selects the function for determining dstAModeWeight

The available weight functions include:

enve.CVF_BLEND_ZERO The value 0

enve.CVF_BLEND_ONE The value 255

enve.CVF_BLEND_SCOLOR The value of the source color

enve.CVF_BLEND_SALPHA The value of the source alpha

enve.CVF_BLEND_DCOLOR The value of the destination color

enve.CVF_BLEND_DALPHA The value of the destination alpha

enve.CVF_BLEND_CCOLOR The value of the "fixed" color

enve.CVF_BLEND_CALPHA The value of the "fixed" alpha

enve.CVF_BLEND_MSCOLOR 255 - CVF_BLEND_SCOLOR

enve.CVF_BLEND_MSALPHA 255 - CVF_BLEND_SALPHA

enve.CVF_BLEND_MDCOLOR 255 - CVF_BLEND_DCOLOR

enve.CVF_BLEND_MDALPHA 255 - CVF_BLEND_DALPHA

enve.CVF_BLEND_MCCOLOR 255 - CVF_BLEND_CCOLOR

enve.CVF_BLEND_MCALPHA 255 - CVF_BLEND_CALPHA

x.chromakey(incolor,tolerance,alpha)

This method scans the input image and compares the color of each pixel to the input pixel color (incolor). If every channel is within tolerance of the target pixel, the alpha channel for that pixel is replaced by the input alpha value. incolor is a tuple of 3 integers (R,G,B) range [0,255] each. The tolerance is a tuple of 3 integers that are the tolerance in R,G,B range [0,255] each.

x.colormath(rw,gw,bw,aw)

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. rw,gw,bw and aw are each tuples of 5 floats and each represent the coefficients of the linear transform for a given output component.

The math implemented is as follows:

R' = R*rw[0]+G*rw[1]+B*rw[2]+A*rw[3]+rw[4]

G' = R*gw[0]+G*gw[1]+B*gw[2]+A*gw[3]+gw[4]

B' = R*bw[0]+G*bw[1]+B*bw[2]+A*bw[3]+bw[4]

A' = R*aw[0]+G*aw[1]+B*aw[2]+A*aw[3]+aw[4]

image = x.diff(input [,absolute=1])

This method computes a new image that is the pixel by pixel (component by component) difference between image x and image input. By default, the subtraction is performed as a signed operation which is clamped to [0,255] on output. If the absolute keyword is set, the output is the absolute value of the difference clamped to the range [0,255].

x.dims = tuple(int x,int y)

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 x and y values using nearest neighbor sampling. Read/write tuple of ints (dx,dy).

str = x.errstr()

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.

x.flip(int)

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: enve.CVF_FLIP_XAXIS and enve.CVF_FLIP_YAXIS, selects the operation.

x.format = enve.CVF_IMG_FMT_RGB

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 enve.codecs() .

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:

enve.CVF_IMG_FMT_A - alpha only

enve.CVF_IMG_FMT_L - luminance (grayscale) only

enve.CVF_IMG_FMT_LA - luminance and alpha

enve.CVF_IMG_FMT_RGB - red, green, blue, three channel image

enve.CVF_IMG_FMT_RGBA - red, green, blue, alpha, four channel image

Read/write int.

x.fromstring(s, dx, dy, format)

This method is the inverse of tostring(). It constructs the contents of the image x from the pixel data in the raw binary string s. It is assumed that the string source was something like that output by the enve.image.tostring() method. The dx, dy and format arguments specify the size and pixel format the image x should take. This method can be used with packages such as matplotlib or numpy which provide mechanisms for generating such raw strings.

pv = x.getpixel(xo,yo)

This method will return as a list, the current color at pixel xo,yo in the image. See setpixel() for a description of the pv.

np_ndarray = x.getpixels()

This method returns an numpy ndarray with dimensions of (xdim * ydim * depth) and depth is 3 for rgb, 4 for RGBA. So np_ndarray[0,0] might be [0,0,0] for RGB, and each entry is of type numpy.uint8 . You can put this numpy array back into setpixels to create a new image.

err = x.load(filename)

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 enve.codecs() for supported file formats.

x.macclip()

This is a legacy method for the Apple Mac that is no longer used.

x.ppm()

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

err = x.resize(xsize,ysize[,smooth=sm])

This method resizes the current image to the size specified by xsize, ysize. This is essentially the same as changing the 'dim' attribute on the image object. By default, this operation is performed using nearest neighbor sampling. The caller may select higher quality box filtered sampling by setting the smooth keyword equal to the value enve.CVF_SCALE_SMOOTH.

err = x.save(filename[,options=options_string])

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 enve.movie options attribute. The method returns 0 on success, or a negative integer on error. See enve.codecs() for supported filename extensions and option strings.

x.setpixel(xo,yo,pixelvalue)

This method will set the color of the pixel at position xo,yo in the image to be the color specified by the list pixelvalue. Pixelvalue is a list of integer values between 0 and 255 (inclusive). There should be at least as many elements in the list as there are image components. For example, if x.format = enve.CVF_IMG_FMT_RGB then there should be three components in pixelvalue (for example, [255, 135, 135]) representing the red, green and blue values of the pixel.

x.setpixels(np_ndarray)

This method takes as input a numpy ndarray and it creates and enve image, x. The np_ndarray is of dimensions of (xdim * ydim * depth) and depth is 3 for rgb, 4 for RGBA. So np_ndarray[0,0] might be [0,0,0] for RGB, and each entry is of type numpy.uint8 . You must define x as an enve image and define the dimensions of x prior to inputting the numpy array into it as follows:

# suppose you have an nd_ndarray of dimensions 736x769, with [R,G,B] values

x = enve.image()

x.dims = (736,769)

x.setpixels(np_ndarray)

dict = x.stats()

This method computes basic statistics on the image object. It computes for all pixels and for all channels (a 10x10 enve.CVF_IMG_FMT_RGB image is considered to have 300 pixels). It returns a dictionary with the keys:

count - the number of pixels in the image

mean - the mean pixel value

sum - the sum of all the pixel values

sumofsquares - the sum of the squares of all of the pixels

variance - the variance of the pixels

minimum - the minimum pixel value

maximum - the maximum pixel value

image = x.subrect((int originx, int originy),(int dx,int dy))

image = x.subrect()

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.

x.swizzle(swiz,mask)

This method allows the value of any channel of the image to come from any other channel of the image. The array swiz selects the input channel for each output channel. For example, a swiz of (0,1,2,3) will result in no image change. A swiz of (2,1,0,0) will swap the red and blue channels and place the input red channel in the output alpha channel as well. The mask array allows individual output channels to be enabled or disabled for writing. The value in the mask array must be non-zero for the output channel to be writable. swiz and mask are both tuples of four integers. With some formats, not all values are used.

s = x.tostring()

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 enve.CVF_IMG_FMT_RGB format, the resulting string would be 30000 bytes in length.


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.

framenumber

Returns an index number that can be used to store a sequence number for this frame. Presently, this is unused. Read/write int.

frame

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).

x.pickdata = numpy_array

pickdata is numpy unsigned char array of dimensions (dx, dy, 4) representing the contents of the pick buffer containing an RGBA image with 8 bits per pixel and 4 samples per pixel as a numpy array. The contents of the array are described in more detail in the Deep Image description for the pick buffer. This is a read/write attribute.

x.variabledata = numpy_array

variabledata is numpy 32bit float array of dimensions (dx, dy). The contents of the array are the actual variable value computed by EnSight for that point on the part. For more details, this is described in the Deep Image description for the variable buffer. This is a read/write attribute.

x.pixeldata = numpy_array

pixeldata is numpy unsigned char array of dimensions (dx, dy, num_channels). The array represents the color portion of the image object. The number of channels will match the x.format value. This is a read/write attribute.

x.metadata = JSON metadata string

metadata is an attribute that contains a JSON string describing the relationship between the pixeldata, variabledata and pickdata arrays. For more information, see Deep Pixel.

x.enhanced = 0|1

This is a metadata flag indicating existence of metadata in this image. If the read only enhanced attribute is non-zero, the metadata, variabledata and pickdata attributes are present.

Additional EnVe Modules

dir(enve) shows the following modules

The first two are the main objects.

image, and movie, and these have been discussed in their own sections. In addition the following minor objects will be discussed below.

arch, extend, home, indexof, istemplate, uuid, version and codecs. These will be discussed directly below.

test=enve.arch()

This function returns the architecture on which enve is running. For example, enve.arch() returns win64, apple_10.5, or linux_2.6_64.

test=enve.extend(string name,int timestep,int imin,int imax)

This function resets the imin and imax of a named movie.

test=enve.home()

This function returns the $CEI location of the EnSight install.

test=enve.indexof(string file,string name,int start,int end)

This function scans from start to end and gets the index of the file when file==name.

test=enve.istemplate(string file)

This function uses the file string to set a template.

test=enve.uuid(1)

This function generates a universal, unique identifier based on the platform, timestamp and a random number. An example might be as follows: ff20e203-dc86-11e4-9d54-6be85efe571e.

enve.UUID_MAKE_MC - ?

enve.UUID_MAKE_V1 - ?

enve.UUID_MAKE_V3 - ?

enve.UUID_MAKE_V4 - ?

enve.UUID_MAKE_V5 - ?

test=enve.version()

This function generates a list that includes the name and copyright, three digit and then two digit version of EnVe. For example: ['EnVe Movie Editor, Copyright 2017-2018 ANSYS, Inc.', '4.1.0', 4.1] .

list=enve.codecs()

EnSight and EnVe use a consistent set of internal codecs for import and export to ensure compatibility across all platforms. This may mean that EnVe is unable to import a movie or image created in a third-party application. This function queries the installed UDILs and returns a list of supported file formats and associated options. It returns a list structure in the following form:

[
    ["name","desc",[".ext",...],stereo, multi,
            [["optname",opttype,<optvalue>,<optdefault>"optdesc"],...]],
    ...
]

"name" is the name of the UDIL, this is used as the movie.format attribute.

"desc" is an ASCII description of the UDIL in more detail.

" .ext" is a list of the filename extensions used by this format.

stereo is an integer that is non-zero if the file supports HW stereo movies.

multi is an integer that is non-zero if the format is an animation file that places all frames in a single file.

The final list is a list of custom options that can be set for the format.

"optname " is the name of an option.

"opttype " is the type of choice: a boolean, integer, float, or choice from a list.

The types can be as follows:

enve.CVF_UDIL_BOOLEAN

enve.CVF_UDIL_INT

enve.CVF_UDIL_FLOAT

enve.CVF_UDIL_CHOICE .

" optvalue " are different for each type:

" optdefault " are different for each type:

Type             Value                 Default
enve.CVF_UDIL_BOOLEAN         "0|1" int
enve.CVF_UDIL_INT             [int_min,int_max]     int
enve.CVF_UDIL_FLOAT           [flt_min,flt_max]     float
enve.CVF_UDIL_CHOICE          ["opt0","opt1",...]   int (index into list)

" optdesc " is a full text description of this option.

To list all the codecs see the following:

for f in enve.codecs():
    print("{} ({})".format(f[1],f[0]))

For an example,

print(enve.codecs()[8])
['PNG', 'PNG Image', ['.png'], 0, 0, [['Compression', 4, ['None', 'Fast',
'Best', 'Default'], 3, 'Compression method']]]

Example EnSight Python to print out of all of the codecs.

import enve
clist = enve.codecs() 
for cc in clist:
    print(cc) 
    print("\n")
    print("name {}".format(cc[0]))
    print("desc {}".format(cc[1])) 
    print ".ext", cc[2] -> print(".ext {}".format(cc[2])) 
    if cc[3] > 0:
        print("supports stereo") 
    if cc[4] > 0:
        print("all frames in single file") 
    else:
        print("frames in separate files") 
    print("Codec options:")
    opts = ""
    for copt in cc[5]:
        print("optname {}".format(copt[0])) 
        opts += copt[0] + " "
        print(" detailed description {}".format(copt[4])) 
        if copt[1] == enve.CVF_UDIL_BOOLEAN:
            print(" Boolean choice") 
            opts += str(copt[3]) + " "
        elif copt[1] == enve.CVF_UDIL_INT: 
            print(" Integer choice")
            opts += str(copt[3]) + " "
        elif copt[1] == enve.CVF_UDIL_FLOAT: 
            print(" Float choice")
            opts += str(copt[3]) + " "
        elif copt[1] == enve.CVF_UDIL_CHOICE: 
            print(" General choice")
            opts += copt[2][copt[3]] + " " 
        else:
            print(" unknown choice {}".format(copt[1]))
        print(" list of choices {}".format(copt[2])) 
        print(" default choice {}".format(copt[3]))
    if len(opts) > 0:
        print("example mov.options = '{}'".format(opts)) 
    else:
        print("no mov.options available for this format ")
    print("\n\n")

Example output from the above EnSight Python code

['AVI', 'Microsoft AVI Movie', ['.avi'], 0, 1, [['Compression', 4, ['MJPEG', 'RAW', 'MPEG4V2'], 2, 'Compression method'], ['BitRate', 1, [0, 40000], 20000, 'Stream bitrate (kbits/sec)']]]

name AVI
desc Microsoft AVI Movie
.ext ['.avi']
all frames in single file
Codec options:
optname Compression
    detailed description Compression method
    General choice
        list of choices ['MJPEG', 'RAW', 'MPEG4V2']
        default choice 2
    optname BitRate
        detailed description Stream bitrate (kbits/sec)
        Integer choice
            list of choices [0, 40000]
            default choice 20000
    example mov.options = 'Compression MPEG4V2 BitRate 20000 '

["copyright", "ver",ver] = enve.version()

This function returns a copyright notice and the version of the enve API as a text string and a floating point number.