Last week, I showed an example of an ENVI 5 batch program; this week, I’ll show an extension, the successor to a user function in ENVI Classic. (Be warned, though, that this turned into a long post.)
Extensions are programs executed in an interactive ENVI session. Extensions allow programmatic control over not only the file access and analysis components of ENVI, but also the UI. Like batch programs, extensions may use routines from both the ENVI and IDL libraries. ENVI+IDL is required to build an extension, but by compiling an extension into an IDL SAVE file, the extension can be executed in an ENVI (runtime version) session. I’ll outline this technique at the end of the post.
In this example, a user is prompted to select a file containing a raster image. The Prewitt edge enhancement operator is applied to each band of the image, with the result written to a new raster file. The first band of the input image is displayed in a new layer in the ENVI 5 UI, with the first band of the output image displayed in the same view as a portal.
Here’s the start of the extension code:
pro envi5_extension_ex
compile_opt idl2
catch, err
if err ne 0 then begin
catch, /cancel
if e ne !null then $
e.reporterror, 'Error: ' + !error_state.msg $
else $
message, !error_state.msg, /continue, /noname
message, /reset
return
endif
e = envi(/current)
if e eq !null then $
message, 'This extension requires an interactive ENVI session. Exiting.'
I’ve chosen to write this extension as a procedure (a function or class would also be fine; note there’s an ENVI extension wizard in the IDL Workbench, located under the File menu, that sets up skeleton code for an extension). The CATCH block handles errors thrown in the program. Call the ENVI function to get the reference to the current ENVI session. If ENVI isn’t running, MESSAGE throws an error that’s handled by the CATCH block.
Next, prompt the user for a raster file to load:
in_raster = e.ui.selectinputdata(/raster)
if in_raster eq !null then return
The SelectInputData method of the ENVIUI object presents a file picker dialog, the ENVI 5 analog to ENVI_SELECT in Classic. It returns an ENVIRaster object. Recall that an ENVIRaster is analogous to a FID in Classic, but it also holds metadata. If the user cancels the operation, then exit the extension.
Now prepare for the processed results:
outdir = e.getpreference('output_directory')
outfile = outdir + 'envi5_extension_ex.img'
if file_test(outfile) then begin
basenames = file_basename(outfile, '.img') + ['.img', '.img.enp', '.hdr']
file_delete, outdir + basenames, /allow_nonexistent
endif
out_raster = e.createraster(outfile, inherits_from=in_raster)
In a manner similar to the batch program example from last week, I’ve set up a path to a file in the user’s output directory. The CreateRaster method makes a new ENVIRaster for the output. Because CreateRaster won’t allow an existing file to be overwritten, I’ve included some IDL code to delete the output file and its support files, if they exist. By using the INHERITS_FROM keyword, the CreateRaster method uses metadata from the input raster to populate the metadata for the output raster.
Now perform the processing. Iterate over the input bands, applying the Prewitt edge enhancement operator (with the IDL PREWITT function) to each and writing the result to the output file:
widget_control, /hourglass
for i=0, in_raster.nbands-1 do begin
band = in_raster.getdata(bands=i)
edge = bytscl(prewitt(band))
out_raster.setdata, edge, bands=i
endfor
out_raster.save
The GetData method is the ENVI 5 analog to ENVI_GET_DATA in Classic. The Save method is the analog to ENVI_WRITE_ENVI_FILE.
Finally, visualize the result in the ENVI UI. Using the default view, create new layers for the input and output images and display the first band of each, with the output displayed in a portal:
view = e.getview()
layer1 = view.createlayer(out_raster, bands=0, /clear_display)
layer2 = view.createlayer(in_raster, bands=0)
portal = view.createportal(layer=layer1, size=[150,150])
end
As it currently stands, this extension could be executed in an interactive ENVI session with the Run button in the IDL Workbench, or by calling it from the IDL command prompt:
ENVI> envi5_extension_ex
% Compiled module: ENVI5_EXTENSION_EX.
However, analogous to a user function in Classic, an extension can be set up to automatically load into ENVI on startup and be visible in the Toolbox. To do this, two additional steps are needed.
Continue reading →