Processing math: 100%

3 Using the IDI Library

 3.1 Control
 3.2 Memories
 3.3 Configuration
 3.4 Graphics
 3.5 Look-up Table
 3.6 Zoom and Pan
 3.7 Interaction
 3.8 Cursor
 3.9 Region of Interest
 3.10 Workstation Interface

3.1 Control

3.1.1 Opening and Closing IDI

All programs using IDI to perform graphics I/O on a device have to begin and end the IDI sections with calls to Open Display and Close Display. If the program is an ADAM task then these two calls have to be replaced by appropriate calls to IDI_ASSOC and IDI_CANCL or IDI_ANNUL (see Appendix B for more details on these functions).

More than one device can be open at a time, each needing separate calls to Open Display and Close Display. The devices are selected by the unique identifier returned from Open Display, and these identifiers should not be tampered with. Device selection is achieved by passing the relevant device identifier to subsequent IDI routines.

By default IDI does not reset the display when the device is opened. This enables applications using IDI to manipulate pictures drawn by other applications. If an application requires the device to be in its default state then an explicit call to Reset Display is required.

As an example consider an application that is drawing a picture from afresh, and therefore wants the device reset at the beginning. If the application is an ADAM task IDI is opened using

        CALL IDI_ASSOC( ’DEVICE’, ’WRITE’, ID, STATUS )

where ’DEVICE’ is the name of a parameter in the interface file through which the name of the device is obtained. The access mode is set to ’WRITE’ which forces a reset of the device, the other possibilities ’READ’ and ’UPDATE’ leave the device as it was found. The third argument is the display identifier which is returned from the routine, and is used in subsequent IDI calls to direct operations to this device. The status argument is an integer which indicates if any problems have occurred.

In a non-ADAM application the same effect is achieved with

        CALL IIDOPN( DNAME, ID, STATUS )
        CALL IIDRST( ID, STATUS )

where DNAME is a string containing the name of the device, corresponding to an entry in the file gns_idinames. The display identifier returned from Open Display is passed to Reset Display to indicate that this is the device to reset.
3.1.2 Buffering

For efficiency IDI can save up its output and send it to the graphics device in batches. There may be occasions, therefore, when the device does not have the complete picture displayed. To force the program to flush the output buffer a call to Update Display is required:

        CALL IIDUPD( ID, STATUS )

Quite often IDI will automatically flush the output buffer, for example when the buffer is full, when the program is reading from the display, or when using the mouse. The output buffer is also flushed when IDI is closed down so that the picture is guaranteed to be complete after a call to Close Display.

3.1.3 Error messages

IDI returns error status values when it cannot complete a requested function satisfactorily. These status values can be converted into error messages by calling Get Error:

        CALL IIDERR( STATUS, MESSAG, MESLEN )

The first argument is the integer status value returned from an IDI routine, and the string containing the error message is returned in the second argument. If the status value is not defined then a blank string is returned from this routine.

IDI does not use the usual Starlink concept of inherited status. The status value passed to each routine is initialised to IDI__OK (= 0) at the beginning of each routine. This puts the onus on the applications programmer to provide sufficient status checks to locate the source of any problem. If an application is using an inherited status scheme it is probably best to pass a local status variable to the IDI routines, and if an error occurs copy this to the inherited status of the calling routine, or deal with the error in some other way.

3.2 Memories

IDI uses memories as its drawing board. The memories can be considered to be rectangular areas of pixels held internally in the display device. The manner in which these memories appear on the screen is also controlled by IDI. An image is displayed on a device by loading the pixel values into a memory. The pixel values are an array of unsigned integers in the range 0 to 2depth1 where depth is the memory depth (bits per pixel). Any values that exceed the maximum are truncated by discarding the most significant bits. The memory can be displayed at different positions or with different zoom factors, and the colour representation of the image can be altered by changing the display path (see below).

Images are loaded into a memory using Write Memory and they can be read back from a memory using Read Memory. Images do not have to fill the whole memory and the selection of a section of memory to write to is achieved using Set Transfer Window. A transfer window is a rectangular sub-section of memory and the process of writing or reading an image employs the transfer window to define which part of the memory is to be used. If required the image loading can begin in the middle of a row. A memory is cleared by filling the memory with a constant value (usually zero) using the routine Clear Memory.

Writing an image into memory with Write Memory does not guarantee that the image will appear on the display. Although this may happen with some devices it should not be relied upon, and a call to Set Memory Visibility should be used to ensure consistent behaviour.

Suppose an application wants to display an image, having NX and NY pixels along each axis, in the bottom left corner of the memory. The application has already checked that the memory is big enough to accept the image, but the size and shape of the image may not match the size and shape of the memory. A transfer window is therefore set up to match the size of the image and located at the bottom left of the memory.

        DIRECN = 0
        XOFF = 0
        YOFF = 0
        CALL IIMSTW( ID, MEMID, DIRECN, NX, NY, DEPTH, XOFF, YOFF, STATUS )

The memory identifier (MEMID) is used to select one memory from those available on the current configuration. A list of available memory identifiers can be obtained from Query Defined Configuration as shown below. The load direction (DIRECN=0) indicates that the image is to be loaded from bottom to top. In this case the size of the transfer window is made to match the size of the image (NX, NY). The X and Y offsets (XOFF, YOFF) indicate where the origin of the transfer window is with respect to the origin of the memory. The depth argument (DEPTH) specifies the expected number of significant bits for each pixel in the input data stream (e.g. data in the range 0 to 255 is stored in eight bits). If this does not exactly match the depth of the memory then data truncation or padding will occur.

The image is injected into the pixel memory using Write Memory.

        XSTART = 0
        YSTART = 0
        NPIX = NX * NY
        CALL IIMWMY( ID, MEMID, PIXDAT, NPIX, DEPTH, PACK,
       :             XSTART, YSTART, STATUS )

The pixel values are stored in the integer input data array (PIXDAT) as a contiguous stream, and the number of pixels to draw is given by NPIX. The data depth (DEPTH) and packing factor (PACK) indicate how individual pixel values are stored in the integer elements of the input array. For instance if the integer word is 32 bits long and the pixel values only have 8 significant bits, then it is possible to store four pixel values in each integer (DEPTH=8, PACK=4). Although this type of packing will save space it will probably not improve plotting times, and so there is no advantage in programs changing the packing of the data themselves. Of course if the data is stored externally in packed form then this feature enables the data to be displayed without having to unpack it first. The start position (XSTART, YSTART) indicates where, with respect to the origin of the transfer window, the first pixel in the data stream is to appear. Subsequent pixels are placed to the right of this one until the edge of the transfer window is reached when a new row of pixels is started. If the size of the transfer window does not match the size of the image then the line breaks will not appear in the correct place and the image will appear skewed.

The final stage of displaying the image is to make the memory visible. This is done with the routine Set Memory Visibility.

        NMEM = 1
        VIS = 1
        CALL IIMSMV( ID, MEMID, NMEM, VIS, STATUS )

This routine takes an array of memory identifiers as its input, so that more than one memory can be made visible at once, but this example only uses the one memory. The visibility (VIS) is a logical value which takes the value TRUE to make the memory visible, and FALSE to make the memory invisible. The IDI specification defines these logical values to be integers having the value zero (FALSE) and non-zero (TRUE).

The display path essentially chooses which intensity transformation table and which look-up table (discussed below) will be used to display the image. The intensity transformation table and look-up table converts the integer values stored in the memory into colours on the screen. If more than one of these tables is available then the bindings of the tables to the memories can be changed using Select Memory Look-up Tables.

The position and zoom factor of the memory on the screen can be altered using the routines Write Memory Scroll and Write Memory Zoom. These routines are non-interactive and the amount of scroll and zoom is set by the input arguments. A zoom factor of 0 means no zoom, a zoom factor of 1 means zoom once (double the size) etc. Negative zooms may be supported on some devices and a zoom factor of -1 means unzoom once (half the size) etc. Scroll offsets are given in pixel units with positive values moving the image to the right and up. Like Set Memory Visibility these two routines take a list of memories as their input so that more than one memory can be operated on with one call, if required. A program can inquire the current scroll and zoom settings with Read Memory Scroll and Zoom. This routine can be used after an interactive operation to inquire what the final values of any scroll and zoom are.

Two memories can be blinked (alternately displayed) using the routine Blink Memories. When this routine is called the blinking begins immediately and continues until the right hand mouse button is pressed. The speed of the blink is initially set by the input argument to the routine, but can be subsequently changed using the left and centre mouse buttons. See the section in the Ikon implementation notes for more details.

3.3 Configuration

The device configuration defines the various capabilities of the device, such as the number of memories, their sizes and their depths, the number of look-up tables etc. A device may have more than one configuration, for example a device with a fixed address space may have one configuration having one memory which fills the available space and another configuration that has several smaller memories allocating the space between them. There are a number of inquiry routines that allow the program to find out various parameters of a given configuration. The inquiries can be used to find out about configurations other than the current one to see if one may be more suitable for the program’s requirement. Query Defined Configuration gives details of the requested configuration.

If there is more than one configuration available on a device then the routine Select Configuration will implement the chosen one.

Query Device Characteristics gives details of the basic set up of the device, such as the size of the display in pixels, the number of configurations available, the number of look-up tables and the number of cursors. More detailed inquiries of the capabilities and current settings for the device can be obtained with Query Capabilities Integer and Query Capabilities Real. Appendix A gives details of the available capabilities. Note that some of the capabilities are arrays of numbers and so the array arguments should be dimensioned large enough to accommodate the returns, otherwise the information returned will be incomplete. A global variable IDI__MAXCP has been supplied which can be used to dimension the array and is as large as any capability on any implemented device. This is defined in the include file IDI_PAR. Examples of using Query Capabilities Integer can be found in the in appendix C.

As an example of searching for a suitable configuration consider an application that requires a minimum size (MEMINX, MEMINY) for an image memory. The first call is to Query Device Characteristics to establish, amongst other things, the number of configurations available which is returned in the second argument.

        CALL IIDQDV( ID, NUMCON, DXSIZE, DYSIZE, DDEPTH, NLUT, NITT,
       :             NCURS, STATUS )

As before the first argument is the display identifier returned from Open Display. The other arguments return the display size and depth, the number of look-up tables, the number of intensity transformation tables and the number of cursors.

The application then examines each configuration in turn using Query Defined Configuration to establish the size of the memories, returned in the seventh and eighth arguments.

  *   Want information on image memories, so memory type = 1
        MEMTYP = 1
  
  *   Examine each configuration in turn, starting from configuration 0
        NCONF = 0
    10  CONTINUE
        IF ( NCONF .LT. NUMCON ) THEN
           CALL IIDQDC( ID, NCONF, MEMTYP, IMAXCP, MODCON, MEMIDS,
       :                MEMSIX, MEMSIY, MEMDEP, ITTDEP, NMEM, STATUS )
  
  *   Examine each memory in turn
           M = 0
    20     CONTINUE
           IF ( M .LT. NMEM ) THEN
              M = M + 1
  
  *   Check the memory size against the required one
              IF ( ( MEMSIX( M ) .GE. MEMINX ) .AND.
       :           ( MEMSIY( M ) .GE. MEMINY ) ) GOTO 30
              GOTO 20
           ENDIF
  
  *   Increment the configuration loop counter
           NCONF = NCONF + 1
           GOTO 10
        ENDIF
  
  *   If this point is reached then have not found a suitable memory
  *   so abort the program
        GOTO 99
  
  *   A suitable memory has been found with configuration number NCONF
    30  CONTINUE

The memory type argument (MEMTYP) is used to indicate which type of memory the routine Query Defined Configuration will return information on. The choices are image memories (1), text memories (2) or graphics memories (4).

As with most IDI identifiers the configuration identifiers (NCONF) start from zero and go up to one less than the number of configurations (NUMCON-1).

The information is returned from Query Defined Configuration in integer arrays having one entry per memory in the configuration. The size of the arrays can be dimensioned using the global variable (IDI__MAXCP) since memory lists form part of the capability inquiries. The actual number of memories in the configuration is given by the output argument (NMEM). Each memory is examined in turn to see if it fulfills the size criterion.

The output list of memory identifiers (MEMIDS) contains the values to be used to identify a particular memory for subsequent IDI routines, in the way that the display identifier selects a particular device. The other arguments returned from Query Defined Configuration are the memory depths, the intensity transformation table depths and the configuration mode (MODCON) which indicates if the device is set up for monochrome (0), pseudo-colour (1) or true-colour (2) display.

The final stage of the example is to remember which memory was chosen and to load the appropriate configuration into the device.

  *   A suitable memory has been found with configuration number NCONF
    30  CONTINUE
  
  *   Obtain the memory identifier of the chosen memory
        MEMID = MEMIDS( M )
  
  *   Select the appropriate configuration
        CALL IIDSEL( ID, NCONF, STATUS )

3.4 Graphics

IDI offers two primitive graphics functions to allow for annotation of an image. The routine Polyline will draw a line connecting a sequence of given points. The routine Plot Text will draw text, in one of up to four sizes, at a given position and at a given angle. Depending on the capabilities of a device either of these routines may overwrite the pixel values of the given memories, and any existing data at these locations will be lost. The appearance of the text (font style and size in pixels) can differ from device to device, because the IDI specification does not define its own fonts and allows implementors to make use of any hardware facilities. The call to Plot Text is as follows:

        CALL IIGTXT( ID, MEMID, STRING, XPOS, YPOS, TPATH, TANGLE,
       :             COLOR, TSIZE, STATUS )

The text to be drawn is passed in the third argument (STRING). The position of the text is given by the next two arguments (XPOS, YPOS) which define the offset of the bottom left corner of the first character with respect to the memory origin. The text path (TPATH) defines if the text is to run horizontally, vertically or back to front, and the orientation of the string (TANGLE) turns the string the given number of degrees clockwise. Some implementations may only offer the default values (0) for both these arguments with the result that the text will only appear horizontally running from left to right. Depending on the type of memory the colour argument (COLOR) is either one of the set of predefined values or is an index into the current look-up table. The text size (TSIZE) is defined imprecisely and takes one of four values, normal (0), large (1), very large (2) or small (3). The values other than the default (0) may not be implemented.

The routine Create Snapshot will return a picture of the display screen in an integer array. It differs from Read Memory in that it does not just return the pixel values from one memory, but takes account of all memories visible on the screen, and at each pixel location returns the value from the memory which is visible at that point. It works on the principle of what you see is what you get, and thus the look-up tables currently displayed are used to transform the pixel values into a value representing the colour. For pseudo-colour devices the displayed colour is transformed onto a single scale using the following fractions of each primary colour 0.30Red+0.59Green+0.11Blue. The call to Create Snapshot is as follows:

        CALL IIDSNP( ID, CMODE, NPIX, XSTART, YSTART, DEPTH, PACK,
       :             IMDAT, STATUS )

The colour mode (CMODE) is zero for a pseudo-colour or monochrome device. The position arguments (XSTART, YSTART) define the start position with respect to the origin of the current transfer window. The given number of pixels (NPIX) are read out sequentially from the current transfer window, with line breaks occurring at the right hand edge of the window. The data depth (DEPTH) and packing factor (PACK) indicate how the pixel values are to be stored in the integer elements of the output array (IMDAT).

3.5 Look-up Table

A pixel value is converted into a spot of colour on the screen in two stages. The pixel value is used as an index into the intensity transformation array. This table has one entry for each possible pixel value, with the pixel values in the range 0 to 2depth1 where depth is the memory depth (bits per pixel). Each entry in this table contains an index into another array, the look-up table, which gives the proportion of red, green and blue used to make the spot of colour. If the number of entries in the look-up table matches the number of entries in the intensity transformation table, then the default intensity transformation table contains a linear mapping, which means that the pixel values point directly into the look-up table. If the tables are of different length, then the default mapping will scale linearly between the two.

The default look-up table is a linear grey scale, but this can be changed by sending a new look-up table with Write Video Look-up Table. To preserve device independence the look-up table entries are stored in a real array with values ranging from 0.0 to 1.0, where the latter indicates the maximum intensity on the device. As an example consider changing one of the screen colours to magenta. The look-up table array is most conveniently defined as a 2-dimensional real array having 3 elements in its first dimension and the number of colour entries in the second.

  *   Dimension the array of colours, in this example length = 1
        REAL VLUT( 3, 1 )
  
  *   Define the number of entries and the red, green and blue intensities
        NENT = 1
        VLUT( 1, NENT ) = 1.0
        VLUT( 2, NENT ) = 0.0
        VLUT( 3, NENT ) = 1.0
  
  *   Load the colour into the look-up table
        CALL IILWLT( ID, LUTNUM, START, NENT, VLUT, STATUS )

The look-up table number (LUTNUM) defines which of the available look-up tables to use. The number of available look-up tables can be inquired using Query Device Characteristics or Query Capabilities Integer. The look-up table is updated starting at the entry defined by the third argument (START), which in this example corresponds to the index of the one colour to change, and continues until the given number of colours (NENT) has been loaded.

Any memory that uses this look-up table will be updated when the new look-up table is sent. The bindings of memories to look-up tables can be changed with Select Memory Look-up Tables.

The look-up tables can be read back using Read Video Look-up Table.

3.6 Zoom and Pan

All the memories on the screen can be zoomed and panned together using Write Display Zoom and Pan. This saves the effort of having to set the zoom and scrolls for all the memories individually using Write Memory Scroll and Write Memory Zoom. These display settings can be read back using Read Display Zoom and Pan. A zoom factor of 0 means no zoom, a zoom factor of 1 means zoom once (double the size) etc. Negative zooms may be supported on some devices and a zoom factor of -1 means unzoom once (half the size) etc. Scroll offsets are given in pixel units with positive values moving the image to the right and up.

3.7 Interaction

The interactions possible with IDI give the user the greatest scope for making use of the image display in an interactive application. The device which controls the interactions is known as the interactor and corresponds to a mouse or trackerball, or some similar object. An interactor such as a mouse or trackerball is considered to have two components; the part which controls the two-dimensional movement is known as the locator, and the buttons are known as triggers.

All interactions are controlled by two basic routines. Enable Interaction sets up one interaction per call. If more than one interaction is required then this routine has to be called again with the appropriate arguments. The routine Execute Interaction and Wait executes all the current interactions and continues until an exit trigger is pressed. An exit trigger is one of the interactor buttons that is defined in Enable Interaction to stop that particular interaction. The exit trigger is therefore a stop button which disables the interaction and returns control to the program. If more than one interaction is defined, for example scrolling and zooming the memory, then it is usual to define the same trigger to be the exit trigger for all interactions.

It is possible to set up more than one interaction to be simultaneously using the same interactor component, for example the locator (mouse) could be used to scroll the memory and rotate the look-up table at the same time, although the effect would be pretty nauseous.

The interactions are defined by two components, the first defines the action to be done, such as move or zoom, and the second defines the object that this action is to be done to, such as cursor or memory. The interaction cross reference table (see Appendix D) shows which actions on which objects are possible for a given device. Clearly some of the possibilities are meaningless, such as rotate display or zoom look-up table, and any attempt to perform such interactions will result in an error.

Examples of setting up interactions are shown in the following section on regions of interest and in the example program (appendix C).

The routine Stop Interactive Input will clear out all current interactions previously set up with Enable Interaction. If more than one interactive session is required in a single application, for example getting a user to change the shape of a region of interest, and then getting the user to move the fixed region of interest around the screen, then Stop Interactive Input should be called between each.

Messages indicating what the user has to do to manage an interaction can be constructed from the output of the routine Query Interactor Description. This will return a string that describes how the given interaction is to be performed, such as ‘move mouse’, or ‘press centre button’. This can be output by the program to give instructions to the user on how to achieve the particular interaction. Examples of the use of this routine can be found in the example program in appendix C.

More complex interactions than those already offered can be programmed using the application specific code mode. Normally the program control would remain inside Execute Interaction and Wait until an exit trigger is fired. In the application specific mode the routine Execute Interaction and Wait returns control to the calling program, where other tasks can be performed. The program then calls the routine Execute Interaction and Wait again, and this loop is repeated until an exit trigger is fired. The routine Get Locator Displacement can be used inside the loop to inquire if the locator has moved, and thus control the programmed interaction. A skeleton example of such an interaction follows.

  *   Set up an application specific interaction to read the locator position
  *   Set up the mouse ( interactor type = 0, interactor id = 0 ) to have
  *   no visible effect ( object type = 0, object id = 0 ) on application
  *   specific code ( interactive operation = 0 ). End the interaction by
  *   pressing the right hand button ( exit trigger number = 2 ).
        INTTY = 0
        INTID = 0
        OBJTY = 0
        OBJID = 0
        INTOP = 0
        EXTRN = 2
        CALL IIIENI( ID, INTTY, INTID, OBJTY, OBJID, INTOP, EXTRN,
       :             STATUS )
  
  *   Loop ( in a non-FORTRAN77 way ) until the exit trigger is fired
        DO WHILE ( TRIGS( EXTRN + 1 ) .EQ. 0 )
  
  *   Enable the interaction
           CALL IIIEIW( ID, TRIGS, STATUS )
  
  *   Inquire the locator displacement
           CALL IIIGLD( ID, INTID, DX, DY, STATUS )
  
  *   Do some application specific functions
           ...
  
        ENDDO

Note in the loop test the exit trigger number is incremented because the trigger numbers start from zero whereas, by default, the FORTRAN array TRIGS has one as its first index. Put another way the exit trigger number of two corresponds to the third entry in the TRIGS array. The displacements returned from Get Locator Displacement give the shift in the locator position (in pixels) since the last call to this routine, and these can then be used in the application specific section.

The routine Execute Interaction and Wait requires one of its arguments to be a logical array whose length matches the number of triggers on the device. The number of triggers can be obtained via the routine Query Capabilities Integer, but standard FORTRAN 77 does not allow dynamic length arrays to be defined. Thus a general purpose application needs to know what is the maximum number of triggers it will have to cope with so it can define the array accordingly. A global parameter IDI__MAXTR has therefore been supplied which can be used to dimension the array, and this is defined in the include file IDI_PAR. The following code segment shows how to define the trigger array in a FORTRAN program

  *  Global Constants:
        INCLUDE ’IDI_PAR’
  *  Local variables:
        INTEGER TRIGS( IDI__MAXTR )

3.8 Cursor

The cursor is usually controlled by the interactor (mouse) but there are several routines to give basic cursor control from a program. Set Cursor Visibility switches the cursor on or off and Write Cursor Position repositions the cursor on the display. The cursor position can be read back using the routine Read Cursor Position.

The routine Initialize Cursor can be used to change the shape of the cursor to one of the predefined shapes. If more than one cursor colour is supported then this can also be changed using Initialize Cursor.

3.9 Region of Interest

A region of interest is a rectangular area on the screen indicated by a rubber-band box. In most respects it is similar in action to a cursor, but instead of indicating a point it defines an area. The routine Initialize Rectangular Region of Interest is required to set up a region of interest, and this returns an identifier which is used by the other routines to access the region. Set Visibility Rectangular Region of Interest switches the box on or off and Write Rectangular Region of Interest repositions the box on the display. The position of the region can be read back using the routine Read Rectangular Region of Interest

A region of interest can also be controlled using the interactor (mouse). The object identifier field of Enable Interaction should contain the relevant ROI identifier returned by Initialize Rectangular Region of Interest. A region can either be moved using an interactive operation = 1, or its shape can be changed using an interactive operation = 7. When moving a region interactively, the size of the area is fixed and the interaction moves the box over the display.

When modifying a region of interest interactively, a rubber-band box is displayed which has one corner anchored and the other corner under the control of the mouse. The active corner is indicated by a small crosshair cursor. By moving the active corner the size and shape of the box is changed. To allow complete control a trigger is set up which switches the active corner to the opposite side. Any region can then be defined by first moving the locator to position one corner as required, switching the active corner, and then moving the locator again to position the opposite corner. This type of operation requires two interactions to be set up. The first defines that the mouse is to move the active corner of the rubber-band box, the second defines a button which will be used to switch the active corner from its current position to the opposite corner of the rubber-band box. The following code segment shows how this works.

  *   Set up the mouse ( interactor type = 0, interactor id = 0 ) to
  *   control the ROI ( object type = 4, object id = ROIID ) by modifying
  *   it ( interactive operation = 7 ). End the interaction by pressing
  *   the right hand button ( exit trigger number = 2 ).
        INTTY = 0
        INTID = 0
        OBJTY = 4
        OBJID = ROIID
        INTOP = 7
        EXTRN = 2
        CALL IIIENI( ID, INTTY, INTID, OBJTY, OBJID, INTOP, EXTRN,
       :             STATUS )
  
  *   Define the left-hand trigger ( interactor type = 5, interactor id = 0 )
  *   to toggle the ROI active corner ( object type = 4, object id = ROIID )
  *   while modifying it ( interactive operation = 7 ). End the interaction
  *   by pressing the right hand button ( exit trigger number = 2 ).
        INTTY = 5
        INTID = 0
        OBJTY = 4
        OBJID = ROIID
        INTOP = 7
        EXTRN = 2
        CALL IIIENI( ID, INTTY, INTID, OBJTY, OBJID, INTOP, EXTRN,
       :             STATUS )
  
  *   Enable the interaction
        CALL IIIEIW( ID, TRIGS, STATUS )
  
  *   Stop the interaction
        CALL IIISTI( ID, STATUS )

3.10 Workstation Interface

When using a workstation as an image display device it is possible to dynamically allocate memory. This is useful if, for instance, the available memory is not large enough to accommodate an image. Consider the earlier example in which the existing configuration was searched for a memory of a minimum size (MEMINX, MEMINY). In that case the program aborted if a suitable memory could not be found. Using the workstation interface a suitably sized memory can be requested. An application should first inquire if the workstation interface is supported using Query Capabilities Integer

  *   Inquire if the workstation interface is supported
        NARR = 1
        CALL IIDQCI( ID, ISDYNC, NARR, YESNO, NVAL, STATUS )
  
  *   Abort if it is not supported
        IF ( YESNO .EQ. 0 ) GOTO 99

The global parameter ISDYNC defines the capability number used to inquire if the dynamic configuration is implemented (see appendix A).

The memory allocation is begun with a call to Enable Configuration which initialises the process. The memory requirements are passed to Allocate Memory and then the process is ended with a call to Stop Configuration which returns a configuration number to be used to access the new memory. The new configuration has to be selected with Select Configuration before the new memory can be used. The following code section shows this in action.

  *   Begin the configuration process
        CALL IIDENC( ID, STATUS )
  
  *   Request an image memory (MEMTYP=1) of the required size
        MEMTYP = 1
        CALL IIDAMY( ID, MEMINX, MEMINY, DDEPTH, MEMTYP, IMEMID, STATUS )
  
  *   Check that the request has been satisfied
        IF ( STATUS .NE. IDI__OK ) GOTO 99
  
  *   End the configuration process
        CALL IIDSTC( ID, ICONF, STATUS )
  
  *   Select this configuration
        CALL IIDSEL( ID, ICONF, STATUS )