MultiSlice RTP Environment

> MultiSlice Programmer Documentation

[MultiSlice API]

MultiSlice is designed in order to shield programmers from the X/MOTIF code, which can often prove
to be extremely difficult to program in. It is also designed to provide programmers with the ability to
manipulate large 3D data-sets without resorting to falling back on X/MOTIF. In addition, the MultiSlice
API allows the programmer access to raw X/MOTIF if necessary, observing only minimal precautions.
Some of the commonly used variables in MultiSlice are also self-correcting, i.e. a programmer writes
a routine which corrupts one or more variables, they can be self-corrected without the program
crashing. (Note that, however, self-correction is limited and is not an excuse to write buggy code !!)
Self correction is mainly utilized in order to prevent large data-sets from memory leaks, a rather
annoying bug in the  X-Windows system that often causes programs to crash over time due to
corruption of memory areas. Although memory leaks have not been experienced in the current version,
which can handle upto twenty images (512 X 512) without any problems, future extensions which may
support true OpenGL-based 3D images with more images open (current version has been tested
with 40 images with no problems, although the facility was later removed due to a large amount
of swap file accesses), may suffer from memory leaks. You may refer to a technical paper on how
to minimize the effects of memory leaks if you need to by clicking here.

How do I install MultiSlice on my system ?

As a programmer/administrator installing MultiSlice is relatively uncomplicated. Simply download the file slice and run it if you have Irix 5.3 and a MIPS R4400. Alternatively, download the first slice file, un-gzip it (gzip *.gz) and un-tar it (tar xvf filename.tar). After that, simply run a make -u and strip slice. Copy the slice file generated to whichever directory you want the users to work in, and copy the *.raw and *.study files to the same directory. Also copy and customize the two shell scripts (wwwhelpmoi and qpr) to your particular configuration. Thses are simple, uncomplicated scripts and should not cause any problems.

User reports crashes/bugs and other problems
 If users complain of any crashes on start-up, please check your X-Windows configuration. You must have X11R6 or later, as well as Motif 1.2. On most older Sun systems, OpenWindows will not support full X11R6 functionality. You must have Motif and an X11R6 compatible windowing system. If MultiSlice starts and quits immediately reporting that it cannot open file `slicetempyhsTN', it would indicate that the user running it does not have write-access to the current directory. Note that MultiSlice is extremely file-intensive and requires full access (read/write and modify) to the current directory. If MultiSlice quits during a working session with the message `cannot open xyz.raw' check that the file is [a] readable and [b] present in the path indicated and that path is also readable/writable. If the user accidentally leaves MultiSlice running overnight, and complains that MultiSlice quit with the message `Possible system timeout', this will not be a bug. MultiSlice has an automatic timeout after 8.30 hrs of inactivity. This is to prevent CPU cycles being wasted and to prevent a possible system lockout due to a crash in the X kernel (if it ever occurs) or a session left running in the background if the shell it runs under is destroyed (a rather common occurance in most systems). Note that in all these errors all user-processed functions are still saved to disk. Simply load all the slicetempyhsT* files and save the ones needed to be saved under different filenames. Also note that MultiSlice will, by default, save everything even in the event of a fatal crash (unlikely, since it has been tested extensively). In extreme circumstances, only the last file processed could be affected since MultiSlice opens and closes only one file at a time (although, very rapidly).

MultiSlice System performance and timings ?

 MultiSlice compares on a roughly equal basis with the old Slice program in terms of timing and performance. The overhead that the old program generated when reading and writing to and from the screen (XPutPixel/XGetPixel) is offset by the fact that MultiSlice loads a file in the background and creates the pixmap and window system necessary. In comparative performance timings :-
Region Growing (single image)     Old Slice: 2.22s       MultiSlice: 3.05s
Image Growing (single image)      Old Slice: 7.55s       MultiSlice: 6.71s
Note that these timings are +/- 0.2s. System loading was 52 processes (+2 slice & MultiSlice), roughly average for an SGI Indy, images loaded were identical and points chosen on the image were within 10% of each other. Each had one image loaded and was given 15s to settle down (and for the multitasker to execute in MultiSlice). Timings were not made electronically, but with a stopwatch, since the old slice had no multitasking capability or any form of self-timing capability. Timings are roughly equal for both cases. Note that MultiSlice will normally be a lot faster due to it's multiple image processing capability. The time taken for the user to load a file in the old slice and run the process each time will be significantly slower than the time taken to do a 3D image processing function. As a rough estimate for complete timings,
Region growing (ten images)     Old Slice: 1min 54s     MultiSlice: 58.23s
Image growing (ten images)      Old Slice: 2min 86.8s  MultiSlice: 1min 9.34s
Note that these timings include the time taken for the user to load a file in the old slice, and the user to select and load a selection of images in MultiSlice. Since human interaction is included, timings may very from person to person. Alos note that the significant disadvantage of the old slice was that each image had to be loaded one at a time and processing was also one at a time, which is not the case in MultiSlice. Timings, as before, are comparable (excluding the roughly 1 minute for user interaction in the old slice environment).

How does memory get consumed and swap space used as the program runs ?

 Following is the dump of a memory/swapfile allocation as the program processes 10 images and does a 3D region growing algorithm on the images, followed by a load of 10 more images and a de-allocation of one of the images loaded.

Swap space allocated and memory mapped (MultiSlice, 48 Meg. RAM, MIPS R4400, IP22)



Cooley% swap -s

total: 3.08m allocated + 156.07m add'l reserved = 159.15m bytes used, 126.35m bytes available

Cooley% ..completed.



Changed temporary file extensions..to Y.

swap -s

total: 3.08m allocated + 157.12m add'l reserved = 160.20m bytes used, 125.30m bytes available

Cooley% swap -s

total: 3.08m allocated + 157.12m add'l reserved = 160.21m bytes used, 125.30m bytes available

Cooley% swap -s

total: 3.08m allocated + 157.35m add'l reserved = 160.43m bytes used, 125.07m bytes available

Cooley% swap -s

total: 3.08m allocated + 157.35m add'l reserved = 160.43m bytes used, 125.07m bytes available

Cooley% swap -s

total: 3.14m allocated + 162.18m add'l reserved = 165.31m bytes used, 120.19m bytes available

Cooley% swap -s

total: 5.11m allocated + 163.28m add'l reserved = 168.39m bytes used, 117.12m bytes available

Cooley% swap -s

total: 8.63m allocated + 164.23m add'l reserved = 172.87m bytes used, 112.64m bytes available

Cooley% swap -s

total: 7.81m allocated + 167.39m add'l reserved = 175.20m bytes used, 110.30m bytes available

Cooley% swap -s

total: 10.06m allocated + 165.38m add'l reserved = 175.44m bytes used, 110.06m bytes available

Cooley% swap -s

total: 9.96m allocated + 165.73m add'l reserved = 175.69m bytes used, 109.81m bytes available

Cooley% swap -s

total: 9.80m allocated + 165.64m add'l reserved = 175.43m bytes used, 110.07m bytes available

Cooley% swap -s

total: 9.61m allocated + 165.57m add'l reserved = 175.18m bytes used, 110.32m bytes available

Cooley% swap -s

total: 9.16m allocated + 166.03m add'l reserved = 175.19m bytes used, 110.31m bytes available

Cooley% 

Normal program termination ... Run Time : 110 seconds

--------------------------MultiSlice RTP----------------------------

[1]    Done                 slice

Cooley% swap -s

total: 7.62m allocated + 142.24m add'l reserved = 149.86m bytes used, 135.65m bytes available

Cooley% swap -s

total: 7.62m allocated + 142.24m add'l reserved = 149.86m bytes used, 135.65m bytes available
As can be seen, the memory requirements increase rapidly when loading and processing, before reducing slightly when a file is de-allocated, and then dropping sharply when the program quits.

What do I need to program in MultiSlice ?

In order to program in MultiSlice you need to have :-
(i) A Silicon Graphics Indy (MIPS R4400-132MHz) or higher with at least 48 megabytes of RAM
    and 120 megabytes of free disk space. In addition, the swap file should be at least 100 megabytes.
(ii) A decent C compiler (the default one included with the machine should suffice).
(iii) X11R6 and Motif 1.2 or higher.
(iv) Irix version 5.3 or higher.
In addition, you need to have a reasonable knowledge of C. You don't need to know anything about
X/MOTIF, K&R C, C++ or anything else. If you know how to manipulate files (load, save etc.) and
have a basic knowledge of arrays, you can write a reasonably good function in MultiSlice that can
manipulate upto 10 files and do a large number of image handling/manipulation operations in 3D
or 2D, display the results, give the user an option to maximise/minimise the output, all without writing
more than a single line  of X/MOTIF code (the single line is simply to attach your function to the menu
system).

All MultiSlice functions are grouped into four groups, which are a definition of the difficulty level and
knowledge required by the programmer. Any good C programmer can easily write a Group I or II
program without any difficulty. However, groups III and IV require extensive knowledge of the
X/MOTIF system. It is recommended that you start writing a Group I or II function before extending
it to a Group III or IV after you gain familiarity with the system. Note that self-correction is NOT
provided for Group III or IV programs to a large extent. A bug/error in these functions will crash the
system completely, possibly without any form of recovery or protection for the files loaded.

What are Groups ?

Groups are simply a category of functions, similar to a security level. The number of variables imported
and the type indicates the level of a group. Groups are defined as follows :-
 

Group Description of Group
I This group defines the base level. Functions operate in psuedo-3D (i.e. the function can handle upto 10 files, display upto 10 outputs, and process the images without any user input) and require practically no knowledge of X/MOTIF. These can be simply put together by using the checklist described below and require the least programmer knowledge. This is a good level to start out with, in order to build confidence and learn a little about the API itself, without the need for extensive debugging or extensive knowledge of the X-Windows system.
II This group is at a slightly higher level. It allows the function to display a simple check box or other form of user input, with a little knowledge of X/MOTIF and keeps some of the security checks and functionality of Group I in place. In addition, it allows access to the real-time clock, allowing the functions to run in real-time with self-timing mechanisms. It also allows background processing if required, along with screen drawing capability. It does not come with an extensive checklist, so when building functions in this group, proceed with some degree of caution.
III This group does not come with any sort of self-correction. It does not come with any help or a checklist and has very little documentation. It will allow you to work in full 3D, use the OpenGL API to display images if necessary and allows access to most variables. When using this group and sub-functions, beware of memory leaks with large data sets. In addition be aware of the differences in color maps between the standard color map and a full OpenGL color map. This group has not been implemented fully, although a degree of support has been built in. The background display routine allows only 2D images to be represented and has to be extended to support OpenGL. You MUST be able to program in Group IV when attempting the full usage of this group.
IV System Group. This group comes with a degree of documentation, most of which is contained within the program code. All system functions are accessible from this group. You can manipulate any number of files in any way, extend the number of files loaded, change the background routines, alter the user interface and do anything to the program's functionality. There is NO self-correction, any routines which belong to Group IV will crash the program easily. Use all required caution and do extensive and thorough testing for extended periods. There is very little chance of self-recovery. 
As can be seen, the groups do have some correlation between each other. It is recommended
starting most functions at Group I, testing extensively, and then migrating them to higher levels.
Manipulation  of variables determines which group a function belongs to. Most Group I functions
will use a Group IV variable, but only as a read-only  variable for checking. It is only a Group IV
function that will write to a Group IV variable. Writing to even a single Group IV variable will define
the entire function  as a Group IV function. Ensure that you do not write to any variable higher than
the group that your function is in. Critical variables in any group with no chance of recovery are usually
preceded by yhs_ or ys to allow a quick check of criticality.

Variables ?

MultiSlice uses the manipulation of variables to determine the level of a program. There are a lot of
variables in MultiSlice, out of which only a fraction are usually imported into a function (usually not
more than 2 (one of which is an int and the other a char) for a filter, for example). The following
is a complete listing of all the external variables in MultiSlice :-
 

Variable Names Type [F]lag/[D]ata Group Level Reference
fg,bg unsigned long D II foreground & background black and white pixel colors.
time int D II Time (in seconds) since start of program execution.
curfile int D I Current file number 
(self-correcting within limits)
resize
int
F
I
0=Load with resize, 1=load without resize
ystheGC[21]
Array of GC
D
II
Graphics Contexts (the mask) for all files displayed on screen.
ysxorGC[21]
Array of GC
D
II
Graphics Contexts (xor mask) for all files displayed on the screen.
array1 & 2 [512][512]
Arrays of int
D
0
Temporary I/O arrays. array1 - Input array2 - Output. Temporary storage, destroy after usage. No need for any checks.
run_once
int
F
I
1/2 File locks for background loading. Comes with checking/self-correction within limits.
file_loader
int
F
I
2/2 File locks for background loading. Comes with checking/self-correction within limits.
running
int
F
I
Mainly concerned with background processing. Comes with checking within limits.
file_load
*char
D
I
Backup/Temporary storage for background file loader. 
ysmap
Colormap
D
III
8-bit Gray or 256 color color map for files displayed. 
yhs_fileX
(x=1 to 20)
*char
D
IV
Backup filenames of all files loaded.
tempfileold
*char
D
I
1/3 temporary file specifiers (self-checking and extensive refreshing every 10 files loaded)
tempfilenew
*char
D
I
2/3 temporary file specifiers (self-checking and extensive refreshing every 10 files loaded) 
addcharac
*char
D
I
3/3 temporary file specifiers (self-checking and extensive refreshing every 10 files loaded)
one..twenty
int
D
IV
Fixed values for callbacks, mainly used for convenience where 1-20 cannot be used. (e.g. &one instead of &1 which is invalid)
yhs_files_open
int
D
IV
No. of files opened. Although a Group IV, it is extensively used in most Group I's as a read-only variable for checking.
yhs_filename[11]
Array of int
D
IV
No. of files selected and file numbers. One of the few Group IV's with some degree of self-correction, refreshed every time a user selects file selector from the menu. It remains a critical variable, however.
squash[21]
Array of int
F
III
0=normal, 1=thumbnail, 2=normal OpenGL, 3=thumbnail OpenGL, 5=OpenGL with motion, 6=thumbnail OpenGL with motion. Refreshed very often, but remains a critical array of flags.
yhs_filenameX
(X=1 to 20)
*char
D
IV
User selected names of files. Refreshed every time a file selector box is opened. Although one variable (usually yhs_filename1) is often imported into Group I functions, it is used as a read-only. and is a critical set even though a full backup exists.
engage_false_color
int
F
III
0=8-bit Gray , 1=256 color false color mode (psuedocolor representations). Has no effect on any internal routines. MultiSlice's screen independence allows any function to work without caring about falsecolor mode. Usually user-defined, rarely used in anything except very few Group IV functions.
arrayGC[21]
Array of GC
D
IV
Array of actual image Graphics Contexts.
thePixmap_y[21]
Array of Pixmaps
D
IV
Array of image Pixmaps.
XImage_y[21]
Array of XImages
D
IV
Array of image XImages.
file_yhs
*char
D
I
String of new file to load by background routine. Refreshed often, every time a file is loaded.
app
XtAppContext
D
IV
Application Context.
manager[21]
Array of widgets
D
IV
Widgets for file management.
view[21]
Array of widgets
D
IV
Widgets for viewing area management.
manageX
(X=1 to 20)
Parent Widgets
D
IV
Widgets for parent window movement. (Each is a block of RAM, hence an array could not be used without memory leaks.)
args[21]
Array of Arg
D
0
Used for declaring parameters in widget creation for Xt/MOTIF popups. Used extensively, refreshed extremely often.
argcount
Cardinal
D
0
As above. These are refreshed/used/destroyed very often. Temporary variables.
theCursor
Cursor
D
I
A pointing arrow cursor. Used/refreshed and destroyed often.
otherCursor
Cursor
D
I
A please-wait motif style watch cursor. Used/refreshed and destroyed often.
What are checklists ?

Checklists are a fast way of implementing a Group I and most of a Group II function.
Similar to a template in a word processor, simply follow the checklist to implement a
simple functions. For more extensive functions, you will need implement the code by
yourself by building on the checklists.

Checklist - Standard function checklist (1 input file, 1 output file) - Group I

This checklist will foxus on writing a single input and single output function called from the menu of MultiSlice RTP. It will be structured in several parts as follows.

1. Change to your MultiSlice directory.
2. Create a new file called myfunc.c
3. Add the file to the Makefile.
4. Open myfunc.c in a text editor.
5. Create the function, calling it newfunc (say) :-
 void newfunc_callback(Widget w, XtPointer client_data,
                  XmAnyCallbackStruct *call_data)
 {
 }
6. Note that the _callback denotes a function called back from the menu.
7. Proceed by declaring local variables in the { } of newfunc()
e.g.
    Arg al[10];
    int ac;
    int current;
    FILE *p_file;
    int i;
    int a,b;
8. Now initialise the temporary I/O arrays as follows :-
    for (a=0;a<512;a++){for (b=0;b<512;b++) { array1[a][b]=0; array2[a][b]=0; }}
9. Run the normal status check on the system by inserting your code inside the if statement.
    if (yhs_files_open >=1 && yhs_files_open < 20 && yhs_filename[0] >= 1)
    {
    yourcodehere();
    }
10.The lines above simply check that files are loaded & selected properly.
11. Open your input filename as follows :-
   if((p_file = fopen(yhs_filename1,"r")) == NULL)
    {
        fprintf(stderr, "Cannot open: %s\n",yhs_filename1);
        exit(1);
    }
12. Now read it in & close the file.
    for (a=0;a<512;a++){
    for (b=0;b<512;b++)
    { array1[a][b]=getc(p_file); }}
    fclose(p_file);
13. Type your code in place now. Note that all values of the file are in array1, so your code will generate output into array2.
14. Output your code to the relevant file by writing to array2.
       strcpy(tempfileold,tempfilenew); /* copy the new filename to the old file i.e. save
the old file */
       strcat(tempfilenew,addcharac); /* new free temp file */
  if((p_file = fopen(tempfileold,"w")) == NULL)
    {
        fprintf(stderr, "Cannot open: %s - Temporary file for writing.\n",tempfileold);
        exit(1);
    }
    for (a=0;a<512;a++){
    for (b=0;b<512;b++)
    { putc(array2[a][b],p_file); }}
    fclose(p_file);
15. All the values are saved. Now unlock the background file loader.
    run_once=0;
    file_loader=1;
    file_yhs=tempfileold;
16. And end your function at this stage.
    }
    }
17. Now, your function should be working and integrated into MultiSlice. Ensure that your have imported run_once,file_loader,file_yhs, yhs_filename[0] and yhs_files_open as external variables at the start of your file. Also import any libraries used (e.g. math.h) at the start of your file.
18. Your function has now been created, but not yet linked to the menu. Open the file menu.c, and type the following :-
  void create_my_menu(Widget parent)
{
19. The above statement creates a new menu. Declare the widgets for it as follows :-
    Widget my_menu_pane, my_menu_button, my_button;
20. Create the menu pane for the menu ..
    my_menu_pane = XmCreatePulldownMenu(parent, "MyFunc ", NULL, 0);
21. Populate the menu pane ..
    my_button = XmCreatePushButton(my_menu_pane, "My first function",
NULL, 0);
    XtManageChild(my_button);
22. Add the callback..
    XtAddCallback(my_button, XmNactivateCallback,
  (XtCallbackProc) newfunc_callback, (XtPointer) NULL);
23. Tidy up the procedure..
    argcount = 0;
    XtSetArg(args[argcount], XmNsubMenuId, my_menu_pane); argcount++;
    my_menu_button = XmCreateCascadeButton(parent, "MyMenu ", args,
argcount);
    XtManageChild(my_menu_button);
}

24. Note that although several statements of X/MOTIF code are stated above, only one line are relevant to include your function to an existing menu (which is the usual case). Simply type the following line into your code if you do not wish to create a new menu and pane on the menu bar of MultiSlice RTP :-
XtAddCallback( XtManageChild(XmCreatePushButton(existing_menu_pane, "My first function", NULL, 0)), XmNactivateCallback, (XtCallbackProc) newfunc_callback, (XtPointer) NULL);

Substitute existing_menu_pane with the name of the correct pane. there is no need to declare any Widgets and no need to create a seperate menu, unless required. Omit steps 18-23 if using this procedure.

Hence, only a single line of X/MOTIF code is required for implementing functions in MultiSlice RTP.

Checklist - Basic Group II function checklist (1 user input, 2 input, 1 output)

1. Using the Group 1 checklist, implement your function. Add the following in order to create user interaction with a dialog box, as follows.
2. Create the dialog-creation function.
 void create_my_dialog(Widget parent) {
3. Declare variables used.
  XmString message;
  Widget temp_widget = parent;
4. Ensure the parent of the dialog is a shell widget.
  while ( !XtIsShell(temp_widget) ) {
    temp_widget = XtParent(temp_widget);
  }
5. Create the message.
  message = XmStringLtoRCreate(MY_MESSAGE, XmSTRING_DEFAULT_CHARSET);
6. Create the dialog.
  argcount = 0;
  XtSetArg(args[argcount], XmNmessageString, message); argcount++;
  my_dialog = XmCreateQuestionDialog(temp_widget, "What do you want to input",
                                       args, argcount);
7.  Add the actions to the buttons.
  XtAddCallback(my_dialog, XmNokCallback,
                (XtCallbackProc) ok_button_callback, (XtPointer) NULL);
  XtAddCallback(my_dialog, XmNcancelCallback,
                (XtCallbackProc) cancel_button_callback, (XtPointer) NULL);
8. Cleanup the strings.
  XmStringFree(message);
}
9. Create the activation function.
void activate_my_dialog(Widget w, XtPointer client_data,
                          XmAnyCallbackStruct *call_data) {
  selection = MYSELECT;
  action = SELECT;
  refresh_action();
  XtManageChild(my_dialog);
}
10. create the de-activation function
void deactivate_my_dialog(void) {
  /* null - no actions at present dialog is auto unmanaged */
  /* whenever any of its buttons are pressed.              */
}
11. Create the callback functions.
static void ok_button_callback(Widget w, XtPointer client_data,
                                 XmAnyCallbackStruct *call_data) {
my_code_here();
}

static void cancel_button_callback(Widget w, XtPointer client_data,
                                   XmAnyCallbackStruct *call_data) {
  deactivate_exit_dialog();
}
12. That completes the user interaction. Simply add the create_dialog and activate_dialog functions to the menu file as shown previously and run your function.

Checklist - Standard conversion checklist (convert a filter from the old slice to MultiSlice) - Group I
The best way to  demonstrate standard procedure to convert a filter is to simply take an existing filter function and simply demonstrate the mechanism for converting it on a line-by-line basis. In this case we consider a gaussian-type filter with a few enhancements and user input of a single value. The conversion procedure on a line-by-line basis is as follows :-

#define f6 6
#define f7 7

#define SIGMA_MESSAGE "Enter sigma value (0.5-20):"
#define SIGMAVALUE    "Introduce sigma value"

typedef float matrix[IMAGE_WIDTH][IMAGE_HEIGHT];

extern Widget   main_window;
extern Cursor theCursor;

/* Extern variables */
extern char *action;

1. Import extra variables to support your function.

extern int yhs_files_open;
extern int yhs_filename[21];
extern int selection;
extern Widget draw_1,draw_2;
extern GC image_gc_2;
extern Pixmap thePixmap_2;
extern XImage *theXImage_1;
extern XImage *theXImage_2;
extern int file_not_loaded;
extern unsigned long fg, bg;
extern void refresh_action(void);
extern int figure;
extern int array1[512][512];
extern int array2[512][512];
extern int running;
extern char *yhs_filename1;

int filter;
float top;

/* Variables for setting resources */
static Arg args[MAXARGS];
static Cardinal argcount;
static Widget sigma_dialog = (Widget) NULL;
 

/* Procedures to apply the convolution operation */
static void convo_vectorx(matrix m, float *mask, int len,
 float *max, float *min, float resul[][IMAGE_HEIGHT]);

static void convo_vectory(matrix m, float *mask, int len, float *max,
 float *min, float resul[][IMAGE_HEIGHT]);

static void convolution (matrix m, float y[SIZE2][SIZE2],int length,
 float *max, float *min, float resul[][IMAGE_HEIGHT]);

extern void watershed_callback(Widget w, XtPointer client_data,
   XmAnyCallbackStruct *call_data);

/* Procedures to get the masks */
void get_gaussian(float s, float *y, int *len);

void get_derigaussian(float s, float *y, int *len);

void get_2derigaussian(float s, float *y, int *len);
 

/*Gaussian Filter*/
void create_sigma_dialog(Widget parent);
void activate_gaussian_dialog(Widget w, XtPointer client_data,
   XmAnyCallbackStruct *call_data);
void deactivate_sigma_dialog(void);
void ok_sigmabutton_callback(Widget w, XtPointer client_data,
   XmSelectionBoxCallbackStruct *call_data);
void cancel_sigmabutton_callback(Widget w, XtPointer client_data,
   XmSelectionBoxCallbackStruct *call_data);
void gaussian_filter(float sigma);
 

/* Derivative Gaussian Filter */
void activate_dgaussian_dialog(Widget w, XtPointer client_data,
   XmAnyCallbackStruct *call_data);
void dgaussian_filter(float sigma);
 

/* Second derivative of Gaussian filter */
void activate_d2gaussian_dialog(Widget w, XtPointer client_data,
                               XmAnyCallbackStruct *call_data);
void d2gaussian_filter(float sigma);
 
 

/* DEFINITION OF GAUSSIAN FUNCTIONS */
/* Procedure to create de dialog. */
void create_sigma_dialog(Widget parent){

  XmString message;
  Widget temp_widget = parent;

  /* Ensure the parent of the dialog is a shell widget */
  while ( !XtIsShell(temp_widget) ) {
    temp_widget = XtParent(temp_widget);
  }

  message = XmStringLtoRCreate(SIGMA_MESSAGE, XmSTRING_DEFAULT_CHARSET);

  argcount = 0;
  XtSetArg(args[argcount], XmNselectionLabelString, message); argcount++;
  sigma_dialog = XmCreatePromptDialog(temp_widget, "gaussian dialog",
     args, argcount);

  /* Remove the help button from the dialog */
  temp_widget = XmSelectionBoxGetChild(sigma_dialog, XmDIALOG_HELP_BUTTON);
  XtUnmanageChild(temp_widget);

  /* Add the actions to the buttons */
  XtAddCallback(sigma_dialog, XmNokCallback,
  (XtCallbackProc) ok_sigmabutton_callback, (XtPointer) NULL);
  XtAddCallback(sigma_dialog, XmNcancelCallback,
  (XtCallbackProc) cancel_sigmabutton_callback, (XtPointer) NULL);

  XmStringFree(message);

}/*end create_sigma_dialog*/
 

/* Procedure to activate the gaussian dialog. */
void activate_gaussian_dialog(Widget w, XtPointer client_data,
                               XmAnyCallbackStruct *call_data){
  if (file_not_loaded) return;
  selection = GAUSSIAN;
  filter = f1;
  action = SIGMAVALUE;
  refresh_action();
  XtManageChild(sigma_dialog);
}
 

/* Procedure to deactivate gaussian dialog. */
void deactivate_sigma_dialog(void){
   /* null - no actions at present dialog is auto unmanaged
      whenever any of its buttons are pressed.              */
}
 

/* Procedure associated with the ok button. */
void ok_sigmabutton_callback(Widget w, XtPointer client_data,
                               XmSelectionBoxCallbackStruct *call_data){
    float sigma;
  char *value;

    /* Get sigma value from user's selection */
  XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &value);

  sigma = atof(value);

    if ( atoi(value) < 0.5 || atoi(value) > 20 )
      XBell(XtDisplay(w),100);
    else
      switch (filter) {
 case f1: gaussian_filter(sigma); break;
 case f2: dgaussian_filter(sigma); break;
 case f3: d2gaussian_filter(sigma); break;
 case f4: dgaux_gauy_filter(sigma); break;
 case f5: dgauy_gaux_filter(sigma); break;
 case f6: total_gradient_filter(sigma); break;
 case f7: gradient_x_y_filter(sigma); break;
 default: break;
      }

    action=SELECT;
    refresh_action();
}
 

/* Procedure associated with the cancel button. */
void cancel_sigmabutton_callback(Widget w, XtPointer client_data,
                                   XmSelectionBoxCallbackStruct *call_data){

    action=SELECT;
    refresh_action();
    deactivate_sigma_dialog();
}
 

/* Procedure that aply a gaussian matrix filter to the image */
void gaussian_filter(float sigma){
  int i,j,start,length_gaussian,lon;
  float value, rmax,rmin,rng, mask_gaussian[SIZE2][SIZE2];
  float gaussian[SIZE1];
  matrix m,resul;

2. Delete the following lines of code :-
start_delete

  /* Fill in the image with background color */
  for(i=0; i<IMAGE_WIDTH; i++)
 for(j=0; j<IMAGE_HEIGHT; j++)
     XPutPixel(theXImage_2,i,j,bg);

  /* Clear the drawing window so the image is displayed again */
  XClearArea(XtDisplay(draw_1),XtWindow(draw_2),0,0,0,0,True);

  /* Associate the watch cursor with the main window */
  XDefineCursor(XtDisplay(draw_1), XtWindow(main_window), theCursor);

  /* Flush the request buffer and wait for all events */
  /* and errors to be processed by the server.        */
  XSync(XtDisplay(draw_1), False);

end_delete

  /* Storing the matrix we want to process in m */
  for(i=0;i<IMAGE_WIDTH;i++)
    for(j=0;j<IMAGE_HEIGHT;j++)
       m[i][j]= XGetPixel(theXImage_1,i,j);

3. Replace the above line as :-

       m[i][j]= array1[i][j];

  get_gaussian(sigma, gaussian, &length_gaussian);

  fprintf(stderr,"la long es %i \n",length_gaussian);

  /* Only the values higher than 0.01 are desirable */
  start=0;
  value=pow(gaussian[0],2);
  while (value<0.01){
        start += 1;
   value = pow(gaussian[start],2);
  }

  for(i=start;i<=length_gaussian-start;i++)
     for(j=start;j<=length_gaussian-start;j++){
    mask_gaussian[i-start][j-start]= gaussian[i]*gaussian[j];
           fprintf(stderr,"la %i,%i es %f \n",i-start,j-start,
  mask_gaussian[i-start][j-start]);

  }

  length_gaussian = length_gaussian - (2*start);

  fprintf(stderr,"la long es %i \n",length_gaussian);

  convolution(m, mask_gaussian, length_gaussian, &rmax, &rmin, resul);

  rng = (float) (rmax - rmin);

  lon = length_gaussian/2;

  /* Now compute the convolution, scaling. */
  for (i=lon; i<IMAGE_WIDTH-lon; i++)
   for (j=lon; j<IMAGE_HEIGHT-lon; j++)
        XPutPixel(theXImage_2,i,j,
  (unsigned long) (((float)(resul[i][j]-rmin)/rng)*255.0));

4. Replace the above line by :-

        array2[i][j]= (unsigned long) (((float)(resul[i][j]-rmin)/rng)*255.0));

5. Delete the following lines :-

  /* Copy image into pixmap. */
  XPutImage(XtDisplay(draw_2), thePixmap_2,image_gc_2, theXImage_2,
 0, 0, 0, 0, theXImage_2->width, theXImage_2->height);

  /* Disassociate the watch cursor from the main window */
  XUndefineCursor(XtDisplay(draw_1), XtWindow(main_window));

  /* Clear the drawing window so the image is displayed again */
  XClearArea(XtDisplay(draw_2),XtWindow(draw_2),0,0,0,0,True);

6. Add the saving to disk code and loading from disk code as defined in the first checklist.
}

7. Save and exit. The function should operate normally as required. Six steps to simply convert an old Slice function to MultiSlice RTP. Note that these steps can be automated to a certain degree by using a simple search and replace. It would not normally require more than 15 minutes to convert the average filter to MultiSlice, after sufficient practice at cutting and pasting relevant sections of code into the proper positions and deleting the old Slice code.

Checklist - Basic Group II conversion checklist (convert a screen drawer from old slice to MultiSlice)

A screen drawer, or a function which writes to the screen explicitly in the old Slice is often relatively difficult to convert. However, MultiSlice does support screen drawing, although indirectly since it must maintain it's screen-independence. Note that all functions on the old Slice can be converted to MultiSlice with sufficient knowledge and experience. It is simply a case of experience in programming at a slightly higher level. It is always possible to convert a screen drawer or any other function in the old Slice without writing a Group IV function. This will be shown by converting a XOR-buffer based real-time Zooming function to MultiSlice RTP. This type of function is usually the most difficult to convert since it explicitly writes to the screen image 1 with an XOR mask, takes user input from the screen, writes back to the screen image 2 and runs in real-time.

1. TRANSLATE. This is the most common programming error encountered while converting functions. Slice operates on the screen, MultiSlice does NOT operate on the screen. Therefore, slice uses a slightly obscure screen based co-ordinate system that moves the origin (0,0) to the TOP LEFT HAND corner. MultiSlice uses the usual origin at the bottom left hand corner. Reverse all mouse input by using a third variable z as follows :-
z=x;
x=y;
y=z;
This simple code eliminates the most common errors while translating such code.

We can now proceed to the actual code itself :-

/*  Create the zoom level prompt dialog for the zoom button in the tools menu */
void create_zoom_dialog(Widget parent)
{
    XmString message;
    Widget temp_widget = parent;

    /* Ensure the parent of the dialog is a shell widget */
    while ( !XtIsShell(temp_widget) ) {
 temp_widget = XtParent(temp_widget);
    }

    message = XmStringLtoRCreate(ZOOM_MESSAGE, XmSTRING_DEFAULT_CHARSET);

    argcount = 0;
    XtSetArg(args[argcount], XmNselectionLabelString, message); argcount++;
    zoom_dialog = XmCreatePromptDialog(temp_widget, "zoom dialog",
    args, argcount);

    /* Remove the help button from the dialog */
    temp_widget = XmSelectionBoxGetChild(zoom_dialog, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(temp_widget);

    /* Add the actions to the buttons */
    XtAddCallback(zoom_dialog, XmNokCallback,
  (XtCallbackProc) ok_button_callback, (XtPointer) NULL);

    XmStringFree(message);
}
 
 

/*-----------------------------------------------------------------------------*/
/*  a c t i v a t e _ z o o m _ d i a l o g                      */
/*-----------------------------------------------------------------------------*/
void activate_zoom_dialog(Widget w, XtPointer client_data,
                            XmAnyCallbackStruct *call_data)
{
    selection = ZOOM;
    action = CLICK;
    refresh_action();
    XtManageChild(zoom_dialog);
}
 
 

/*-----------------------------------------------------------------------------*/
/*  o k _ b u t t o n _ c a l l b a c k                               */
/*                                                                    */
/*  Callback for the "OK" button      */
/*----------------------------------------------------------------------------*/
static void ok_button_callback(Widget w, XtPointer client_data,
                               XmSelectionBoxCallbackStruct *call_data)
{
    int t;
    char *zoom;
FILE *p_file;
int a,b;

    /* Get threshold value from user's selection */
    XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &zoom);

2. Insert a check to ensure that the file operate on is at it's maximum size and not a thumbnail with this simple if statement :-
if(squash[curfile] != 1)
{
    t = atoi(zoom);

3. Check the user input values to ensure the user does not input a false value.

    if (!(t>0 && t<=50) ) XBell(XtDisplay(w),100);
    else {

4. Insert the usual load file code as defined in the first checklist.

   if((p_file = fopen(yhs_filename1,"r")) == NULL)
    {
        fprintf(stderr, "Cannot open: %s\n",yhs_filename1);
        exit(1);
    }
    for (a=0;a<512;a++){
    for (b=0;b<512;b++)
    { array1[a][b]=getc(p_file); array2[a][b]=0; }}
    fclose(p_file);

 /*Set the scale zooming*/
 zoom_level = t;
 /* Prepare the widgets to be able to receive the corret events */
 prepare_handlers(ZOOM);
 /* Get the correct scale settings */
 old_offset_x = offset_x;
 old_offset_y = offset_y;
 offset_x = 512/zoom_level;
 offset_y = 512/zoom_level;
    }
}
}
 

/*---------------------------------------------------------------------- */
/*  s t a r t  _  z o o m       */
/*---------------------------------------------------------------------- */

void start_zoom(Widget w, XtPointer client_data, XEvent *event)
{
    int i, j, color, x1, y1,z;
int a,b;
FILE *p_file;

5. This is where the translation should be inserted.

z=y;
y=x;
x=z;
    if (event->xbutton.button != Button3) return;
remove_event_handlers(ZOOM);
    /* Fill in the image with zoomed partition */
    for(x1=x; x1<(x+offset_x); x1++)
 for(y1=y; y1<(y+offset_y); y1++) {
     color = array1[x1][y1];
     for(i=0; i<zoom_level; i++)
  for(j=0; j<zoom_level; j++) {
     array2[((x1-x)*zoom_level)+i][((y1-y)*zoom_level)+j]=color;
  };
 }
fprintf(stderr,"\nZooming : x1=%d y1=%d x=%d y=%d offset_x=%d
offset_y=%d\n",x1,y1,x,y,offset_x,offset_y);

6. Delete or comment out the old Slice code.

    /* Flush the request buffer and wait for all events */
    /* and errors to be processed by the server.        */
/*    XSync(XtDisplay(w), False); */

7. Insert the new file saving code as shown in the first checklist.

       strcpy(tempfileold,tempfilenew); /* copy the new filename to the old file i.e. save
the old file */
       strcat(tempfilenew,addcharac); /* new free temp file */
  if((p_file = fopen(tempfileold,"w")) == NULL)
    {
        fprintf(stderr, "Cannot open: %s - Temporary file for writing.\n",tempfileold);
        exit(1);
    }
    for (a=0;a<512;a++){
    for (b=0;b<512;b++)
    { putc(array2[a][b],p_file); }}
    fclose(p_file);

8. Insert the background code as required.

    run_once=0;
    file_loader=1;
    file_yhs=tempfileold;
}
 
 

/*---------------------------------------------------------------------- */
/*  m o v e _  z o o m       */
/*---------------------------------------------------------------------- */

void move_zoom(Widget w, XtPointer data, XEvent *p_event)
{
    x = p_event->xbutton.x;
    y = p_event->xbutton.y;

    /* If rectangle on screen, redraw it again using XOR mask to remove it */
    if (rectangle_on_screen)

9. Note the changes made. view[curfile] should be substituted for Image1. Note the extra XOR mask functionality in MultiSlice to smooth the transition by providing a dynamic XOR mask for every file loaded.

 XDrawRectangle(XtDisplay(view[curfile]),XtWindow(view[curfile]),
ysxorGC[curfile],old_x,old_y,  old_offset_x, old_offset_y);

    /*The rectangle can't be moved outside the display window */
    if ( x>( IMAGE_WIDTH-offset_x) ) x=(IMAGE_WIDTH-offset_x);
    if ( y>(IMAGE_HEIGHT-offset_y) ) y=(IMAGE_HEIGHT-offset_y);

    /* Draw the rectangle in the new position in screen */

10. As before, replace all the old Image1 code with the new view[curfile] and XOR GC mask.

    XDrawRectangle(XtDisplay(view[curfile]), XtWindow(view[curfile]), ysxorGC[curfile],
x, y, offset_x, offset_y);

    /* Save values for the next updating rectangle */
    old_x = x;
    old_y = y;
    old_offset_x = offset_x;
    old_offset_y = offset_y;

    rectangle_on_screen=True;
}
 
 

/*---------------------------------------------------------------------- */
/*  h a n d l e _ z o o m _ e x p o s e     */
/*---------------------------------------------------------------------- */

void handle_zoom_expose (Widget w, XtPointer client_data,
                            XmAnyCallbackStruct *call_data)
{
    /* If an expose event has happen in draw_1 widget, the rectangle has */
    /* been deleted so set correct value to the variable */
    rectangle_on_screen=False;
}

void create_zoom_dialog(Widget parent);
void activate_zoom_dialog(Widget w, XtPointer client_data,
   XmAnyCallbackStruct *call_data);
static void ok_button_callback(Widget w, XtPointer client_data,
                               XmSelectionBoxCallbackStruct *call_data);
void start_zoom(Widget w, XtPointer client_data, XEvent *event);
void move_zoom(Widget w, XtPointer data, XEvent *p_event);

extern void prepare_handlers (int sel);
 
 

/* Function definition */

/*----------------------------------------------------------------------------*/
/*  c r e a t e _ z o o m _ d i a l o g      */
/*          */
/*  Create the zoom level prompt dialog for the zoom button in the tools menu */
/*----------------------------------------------------------------------------*/

void create_zoom_dialog(Widget parent)
{
    XmString message;
    Widget temp_widget = parent;

    /* Ensure the parent of the dialog is a shell widget */
    while ( !XtIsShell(temp_widget) ) {
 temp_widget = XtParent(temp_widget);
    }

    message = XmStringLtoRCreate(ZOOM_MESSAGE, XmSTRING_DEFAULT_CHARSET);

    argcount = 0;
    XtSetArg(args[argcount], XmNselectionLabelString, message); argcount++;
    zoom_dialog = XmCreatePromptDialog(temp_widget, "zoom dialog",
    args, argcount);

    /* Remove the help button from the dialog */
    temp_widget = XmSelectionBoxGetChild(zoom_dialog, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(temp_widget);

    /* Add the actions to the buttons */
    XtAddCallback(zoom_dialog, XmNokCallback,
  (XtCallbackProc) ok_button_callback, (XtPointer) NULL);

    XmStringFree(message);
}
 
 

/*-------------------------------------------------------------------------*/
/*  a c t i v a t e _ z o o m _ d i a l o g                      */
/*------------------------------------------------------------------------*/

void activate_zoom_dialog(Widget w, XtPointer client_data,
                            XmAnyCallbackStruct *call_data)
{
    selection = ZOOM;
    action = CLICK;
    refresh_action();
    XtManageChild(zoom_dialog);
}
 
 

/*------------------------------------------------------------------------*/
/*  o k _ b u t t o n _ c a l l b a c k                               */
/*                                                                    */
/*  Callback for the "OK" button      */
/*-----------------------------------------------------------------------*/

static void ok_button_callback(Widget w, XtPointer client_data,
                               XmSelectionBoxCallbackStruct *call_data)
{
    int t;
    char *zoom;

    /* Get threshold value from user's selection */
    XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &zoom);

    t = atoi(zoom);

    if (!(t>=0 && t<=50) ) XBell(XtDisplay(w),100);
    else {
 zoom_level = t;
 prepare_handlers(ZOOM);

 old_offset_x = offset_x;
 old_offset_y = offset_y;

 offset_x = IMAGE_WIDTH/zoom_level;
 offset_y = IMAGE_HEIGHT/zoom_level;
    }
}
 
 

/*----------------------------------------------------------------------*/
/*  s t a r t  _  z o o m       */
/*----------------------------------------------------------------------*/

void start_zoom(Widget w, XtPointer client_data, XEvent *event)
{
    int i, j, color, x1, y1;

    if (event->xbutton.button != Button3) return;

11. Delete the following code :-
start_delete

    /* Fill in the image with background color */
    for(x1=x; x1<(x+offset_x); x1++)
 for(y1=y; y1<(y+offset_y); y1++) {
     color = XGetPixel(theXImage_1,x1,y1);
     for(i=0; i<zoom_level; i++)
  for(j=0; j<zoom_level; j++) {
      XPutPixel(theXImage_2,
    ((x1-x)*zoom_level)+i,
    ((y1-y)*zoom_level)+j,color);
  };
 };

end_delete

12. Replace XPutPixel(theXImage_2 with array2 as shown in the first conversion checklist.
 
    /* Contorno de la Imagen a negro */
     for(i=0; i<IMAGE_WIDTH; i++)
 for(j=0; j< IMAGE_HEIGHT; j++) {
  XPutPixel(theXImage_2,i,0,0);
  XPutPixel(theXImage_2,i,1,0);
  XPutPixel(theXImage_2,i,511,0);
  XPutPixel(theXImage_2,0,j,0);
  XPutPixel(theXImage_2,1,j,0);
  XPutPixel(theXImage_2,511,j,0);
   };

13. Simply delete the rest.

    /* Flush the request buffer and wait for all events */
    /* and errors to be processed by the server.        */
    XSync(XtDisplay(w), False);

    /* Copy image into pixmap */
    XPutImage(XtDisplay(draw_2), thePixmap_2, image_gc_2, theXImage_2,
  0, 0, 0, 0, theXImage_2->width, theXImage_2->height);
    /* Clear the drawing window so the image is displayed again */
    XClearArea(XtDisplay(draw_1),XtWindow(draw_2),0,0,0,0,True);
}
 
 
14. The function is now completely converted. Test it throughly before releasing it, as with every other function.

Checklist - Simple Group III+ command line function processor checklist (Execute fn from the command-line)

This is a very simple checklist for implementing a Group III+ command line function. Note that although it does not use any Group IV functions, the simple fact of it running in unprotected, critical sections of the program ensure that it's rating is at least a Group III and it should be tested as a Group III or IV function.

1. Edit the file command_slice.c
2. Add the following code to the file :-
        if(strcmp("-myfunc", argv[i]) == 0)
        {
        my_code_here();
        }
3. Note that all file loading operations and background processor operations are available despite the fact the background processor is not yet executing. This is due to the processor execution immediately after the command line processing has been completed.
Include the following to load a file :-
run_once=0;
file_load=1;
4. Test the function throughly with other command line functions. An error in a command line function simply stops MultiSlice functioning correctly, and since it has access to all the variables, it can cause data corruption anywhere in the program.

Hence, in 3 simple steps, a command line function can be implemented.
 

What are the functions available to me (and what groups do they belong to) ?
 
Note that, as before, including a Group IV function in a Group I function automatically converts it to a full Group IV. There is no need to specifically call these functions unless writing a Group IV or III function. Calling it via variables is the usual case. Calling it via variables keeps a Group I function a Group I function as some degree of error-correction/self-checking is used when calling Group IV functions using variables only. There is no real need to use any of these functions by calling them directly. This is provided simply as a reference.
 

 
File 
Fn Call Fn Name Args Reqd. Group Description of function
ctomass.c void activate_ctomass_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate Centre-Of-Mass Callback
edge.c void edge_sobel_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Sobel Callback
edge.c void edge_kirsch_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Kirsch Callback
edge.c void edge_prewitt_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Prewitt Callback
edge.c void edge_frei_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Frei Callback
edge.c void line_frei_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Line Frei Callback
edge.c void edge_marr_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Marr Callback
edge.c void edge_roberts_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Roberts Callback
edge.c void edge_vert_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Edge Vertices Callback
edge.c void create_edge_hv_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Create the Erode Dialog Box
edge.c void activate_edge_hv_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate the Erode Dialog Box
edge.c void deactivate_edge_hv_dialog void I Deactivate the Erode Dialog Box
edge.c static void ok_edge_hvbutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Callback for User pressing OK on Erode Box
edge.c static void cancel_edge_hv_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Callback for User pressing Cancel on Erode Box
edge.c void edge_hv int iterations IV Erode function
edge.c void create_edge_dilate_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Create the Dilate Dialog Box
edge.c void activate_edge_dilate_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate the Dilate Dialog Box
edge.c void deactivate_edge_dilate_dialog void I Deactivate the Dilate dialog
edge.c static void ok_edge_dilatebutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV User presses OK on Dilate Dialog Box
edge.c static void cancel_edge_dilate_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV User presses Cancel on Dilate Dialog Box
edge.c void edge_dilate int loop IV Dilate function
edge.c void edge_unsharp_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Edge Unsharp Callback
edge.c void mean_filter_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Mean Filter Callback
edge.c void create_smooth_t_dialog Widget parent 0 Smooth T dialog Creation
edge.c void activate_smooth_t_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Smooth T Dialog Activation
edge.c void deactivate_smooth_t_dialog void 0 Smooth T Dialog deactivation
edge.c static void ok_smooth_tbutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data 0 OK button pressed - Smooth T dialog
edge.c static void cancel_smooth_t_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data 0 Cancel button pressed - Smooth T dialog
edge.c void smooth_t int t 0 Smooth T Function
edge.c void smooth_mask1_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Smooth Mask 1 Callback
edge.c void smooth_mask2_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Smooth Mask 2 Callback
edge.c void median_filter_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data 0 Median Filter Callback
edge.c void median_vf_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data II Median VF Callback
edge.c void create_hough_dialog Widget parent IV Hough Dialog Creation
edge.c void activate_hough_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Hough Dialog Activation
edge.c void deactivate_hough_dialog void IV Hough Dialog Deactivation
edge.c static void ok_hough_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV OK button Callback - Hough Dialog
edge.c static void cancel_hough_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Cancel button Callback - Hough Dialog
edge.c void hough int t IV Hough Function
edge.c void create_threshold_dialog Widget parent IV Threshold Dialog Creation
edge.c void activate_threshold_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Threshold Dialog Activation
edge.c void deactivate_threshold_dialog void IV Threshold Dialog Deactivation
edge.c static void ok_threshbutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV OK button Callback - Threshold Dialog
edge.c static void cancel_threshbutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Cancel button Callback - Threshold Dialog
edge.c void thresholding int t IV Thresholding Function
edge.c void histogram_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Histogram Function Callback
edge.c void histo_eq_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Histogram Function Computation
editing_tools.c void create_editing_tools_window Widget parent IV Create floating menu
editing_tools.c void activate_editing_tools_window Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate the menu
editing_tools.c void tracking_callback Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data IV Tracking last function callback
editing_tools.c void rectangles_callback Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data IV Rectangle Drawing Callback
editing_tools.c void circles_callback Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data IV Circle Drawing Callback
editing_tools.c void ellipses_callback Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data IV Ellipse Drawing Callback
editing_tools.c void clear_figure_callback Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data IV Clear the figure callback
editing_tools.c void quit_me_callback Widget w, XtPointer client_data, XmDrawingAreaCallbackStruct *call_data IV Quit the floating menu
editing_tools.c void start_tracking Widget w, XtPointer data, XEvent *p_event II Start cursor tracking
editing_tools.c void continue_tracking Widget w, XtPointer data, XEvent *p_event IV Continue cursor tracking
editing_tools.c void end_tracking Widget w, XtPointer data, XEvent *p_event IV End cursor tracking
editing_tools.c void start_rubberband Widget w, XtPointer data, XEvent *p_event IV Start the rubberbanding
editing_tools.c void continue_rubberband Widget w, XtPointer data, XEvent *p_event IV Continue the rubberbanding
editing_tools.c void end_rubberband Widget w, XtPointer data, XEvent *p_event IV Edn the rubberbanding
editing_tools.c void draw_figure Display *d, Window w, GC gc IV Draw the figure with XOR mask
editing_tools.c void show_region NODEPTR aux IV Show the regions
editing_tools.c void get_point_list_of_polygon XPoint *points, int *numpoints IV Get a points list in the polygon
exit.c void create_exit_dialog Widget parent IV Create the exit dialog
exit.c void activate_exit_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate the exit dialog
exit.c void deactivate_exit_dialog void IV Deactivate the exit dialog
exit.c static void exit_button_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Callback for the OK button on the exit dialog
exit.c void cancel_button_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Callback for the Cancel button on the exit dialog
filters.c static void convo_vectorx matrix m, float *mask, int len, float *max, float *min, float resul[][IMAGE_HEIGHT] IV Procedures to apply the convolution operation
filters.c static void convo_vectory matrix m, float *mask, int len, float *max, float *min, float resul[][IMAGE_HEIGHT] IV Procedures to apply the convolution operation
filters.c static void convolution matrix m, float y[SIZE2][SIZE2],int length, float *max, float *min, float resul[][IMAGE_HEIGHT] IV Procedures to apply the convolution operation
filters.c void get_gaussian float s, float *y, int *len IV Procedures to get the masks
filters.c void get_derigaussian float s, float *y, int *len IV Procedures to get the masks
filters.c void get_2derigaussian float s, float *y, int *len IV Procedures to get the masks
filters.c void create_sigma_dialog Widget parent IV Sigma Dialog Creation
filters.c void activate_gaussian_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Gaussian Dialog Activation
filters.c void deactivate_sigma_dialog void IV Sigma Dialog Deactivation
filters.c static void ok_sigmabutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV OK button Callback - Sigma Dialog
filters.c static void cancel_sigmabutton_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Cancel button Callback - Sigma Dialog
filters.c void gaussian_filter float sigma IV Gaussian Filter
filters.c void activate_dgaussian_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate Derivative Gaussian Filter Dialog
filters.c void dgaussian_filter float sigma IV Derivative Gaussian Filter
filters.c void activate_d2gaussian_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate second derivative Gaussian Filter Dialog
filters.c void d2gaussian_filter float sigma IV Second Derivative Gaussian Filter
filters.c void activate_dgaux_gauy_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate Derivative of a Gaussian in rows and Gaussian in columns Dialog
filters.c void dgaux_gauy_filter float sigma IV Derivative of a Gaussian in rows and Gaussian in columns Filter
filters.c void activate_dgauy_gaux_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate derivative Gaussian in columns and Gaussian in rows Filter Dialog
filters.c void dgauy_gaux_filter float sigma IV Derivative Gaussian in columns and Gaussian in rows Filter
filters.c void activate_total_gradient_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate Total Gradient= sqrt(pow(dgauxgauy,2)+pow(dgauygaux,2)) Filter Dialog
filters.c void total_gradient_filter float sigma IV Total Gradient= sqrt(pow(dgauxgauy,2)+pow(dgauygaux,2)) Filter
filters.c void activate_gradient_x_y_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate Gradient_x_y = sqrt(pow(gaussian_x,2)+pow(gaussian_y,2) Filter Dialog
filters.c void gradient_x_y_filter float sigma IV Gradient_x_y = sqrt(pow(gaussian_x,2)+pow(gaussian_y,2) Filter
filters.c void differencex_filter void IV Difference x filter, differences between horizontal adjacent points
filters.c void differencey_filter void IV Difference y filter, differences between vertical adjacent points
filters.c void gradient_filter void IV Gradient filter
label.c void create_labels Widget w1, Widget w2, Widget w3, Widget w4, Widget w5 IV Label Creation
label.c void refresh_filename void IV Filename display refresher
label.c void refresh_action void IV Action display refresher
label.c void refresh_coord int x, int y, int v IV Co-ordinate refresher
measure.c void activate_area_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate selected area
measure.c void activate_perimeter_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate selected perimeter
measure.c void activate_circular_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate circular area
menu.c void create_options_menu Widget parent IV Creates the options menu
menu.c void create_main_menu Widget parent IV Creates the main menu
menu.c void create_file_menu Widget parent IV Creates the file menu
menu.c void create_preprocessing_menu Widget parent IV Creates the preprocessing menu
menu.c void create_segmentation_menu Widget parent IV Creates the segmentation menu
menu.c void create_tools_menu Widget parent IV Creates the tools menu
menu.c void create_feature_menu Widget parent IV Creates the feature menu
menu.c void create_about_menu Widget parent IV Creates the about menu
menu.c void create_window_menu Widget parent IV Creates the window menu
menu.c void create_multi_menu Widget parent IV Creates the multi-images menu
menu.c void create_flasher Widget parent IV Creates the animated flashing phoenix icon in the right hand corner
neighbour.c static void get_neighbours PATHPTR *list, TREEPTR root, char c[] IV Get adjoining neighbours
neighbour.c static void analize PATHPTR *list, TREEPTR root, char path[], short where IV Analyse neighbours
neighbour.c static void include_sub_neigh PATHPTR *list,char path[],TREEPTR node, short level,short where IV Include sub-neighbour pixels
neighbour.c static void get_4_neighbours char c[],char v1[],char v2[],char v3[],char v4[] IV Get N,S,E,W neighbours
neighbour.c static void analize_label char *c, short i, short pos IV Analyse labels
neighbour.c void initialize_label char c[], int start IV Initialise Labels
neighbour.c void copy_label char *dest, char *source IV Label copying function
neighbour.c void write_label char *c IV Label writing function
neighbour.c void insert PATHPTR *list, char n[] IV Insertion function
open.c void sbox_set Widget d, XtPointer client_data,XmToggleButtonCallbackStruct *call_data IV Selection box settings
open.c void pbox_cb Widget m, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Inverse selection box settings
open.c void update_time void IV Main Background Processor - Dynamic file loading/widget-creation/timeout/self-correction
open.c void create_open_dialog Widget parent IV Open a file dialog
open.c void create_view_dialog Widget parent IV Open a project dialog
open.c void activate_open_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate open dialog
open.c void activate_view_dialog Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Activate project open dialog
open.c void deactivate_open_dialog void IV Deactivate open dialog
open.c void deactivate_view_dialog void IV Deactivate project open dialog
open.c void fs_ok Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Callback for file selection OK
open.c void fs_cancel Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Callback for file selection CANCEL
open.c void fv_ok Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Callback for project selection OK
open.c void fs_cancel Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data IV Callback for project selection CANCEL
open.c void load_file char *filename, Widget w IV File loader
open.c static void setup_ximage void IV XImage setup routines
open.c void close_me_callback Widget w, XtPointer client_data,XmDrawingAreaCallbackStruct *call_data IV Callback for file closing
open.c void multi_window_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV MultiWindow Operations callback
open.c void reduce_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Image reduction callback
open.c void expand_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Expanding function callback
open.c void cascade_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Cascading functions callback
open.c void tile_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV Tiling functions callback
open.c void operate_callback Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data IV MultiImage Operations callback
open.c void resize_callback void IV Resizing functions
open.c void reduction void IV Reduction functions
open.c void delreload void IV Delete and Reload functions
open.c void deletestring void IV Delete String functions
region.c void create_region_dialog Widget parent IV Create the region dialog
region.c void activate_region_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate the region dialog
region.c void activate_image_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate the image dialog
region.c void deactivate_region_dialog void IV Deactivate the region dialog
region.c static void ok_button_callback Widget w, XtPointer client_data,XmSelectionBoxCallbackStruct *call_data IV Callback for the OK button
region.c static void cancel_button_callback Widget w, XtPointer client_data,XmSelectionBoxCallbackStruct *call_data IV Callback for the cancel button
region.c void start_growing Widget w, XtPointer client_data, XEvent *event IV Start the growing algorithm
region.c static void grow int x, int y, unsigned long threshold IV Grow function
region.c static void add_neighbours NODEPTR *list_pixels, NODEPTR list_region,TPINFO *info, unsigned long mean, unsigned long threshold IV Add the neighbours
region.c void start_image_growing Widget w, XtPointer client_data,XmSelectionBoxCallbackStruct *call_data IV Image growing function starting
region.c static void image_grow Image growing function main IV unsigned long threshold
region.c int region_cut_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Region cutting function
region.c void start_cut Widget w, XtPointer client_data, XEvent *event IV Start cutting
region.c static void cut void 0 Cutting function
region.c static void create NODEPTR *list 0 List creation
region.c static int list_empty NODEPTR list IV List empty checking
region.c static void insert NODEPTR *list, TPINFO *info IV List insertion
region.c static TPINFO delete_first NODEPTR *list IV First item on list deletion
region.c static unsigned int num_elem NODEPTR list IV Number of elements in the list
region.c static int search int x, int y IV Searching list
region.c static void free_list NODEPTR *list IV Freeing list
region.c static unsigned long calculate_mean NODEPTR list IV Calculating mean from list
region.c static int inside_limits int x, int y IV Is it inside limits ?
region.c static int inside_region int x, int y IV Is it inside region ?
region.c static int inside_threshold unsigned long pixel, unsigned long mean,unsigned long threshold IV Is it inside threshold ?
region.c static void view_pixel NODEPTR list, unsigned long mean IV View the pixel
region.c static void sort_array HISTO_ARRAY *A IV Function for sorting an array
save.c void create_save_as_interface Widget parent IV Create the save as dialog box
save.c void exit_save_as_dialog void IV Exit the dialog box
save.c void save_as_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Save the file
save.c static Widget create_file_select_dialog Widget parent IV Select the file
save.c static void activate_file_select_dialog void IV Activate file selector dialog
save.c static void deactivate_file_select_dialog void IV Deactivate file selection
save.c static void fs_ok_callback Widget w, XtPointer client_data, XmFileSelectionBoxCallbackStruct *call_data IV OK - save the file callback
save.c static void fs_cancel_callback Widget w, XtPointer client_data,XmFileSelectionBoxCallbackStruct *call_data IV Cancel - no file saving callback
save.c static void create_overwrite_dialog Widget parent IV Create overwrite file dialog
save.c static void activate_overwrite_dialog void IV Activate overwrite file dialog
save.c static void deactivate_overwrite_dialog void IV Deactivate overwrite dialog
save.c static void overwrite_yes_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Overwrite file dialog
save.c static void overwrite_no_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Do not overwrite file dialog
save.c static void create_save_fail_dialog Widget parent IV Create save failure dialog
save.c static void activate_save_fail_dialog void IV Activate save failure dialog
save.c static void deactivate_save_fail void IV Deactivate save failure dialog
save.c static void save_fail_ok_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV OK button callback - Save fail dialog
save.c static int save_app_workspace char *filename IV Save application workspace
save.c static int does_file_exist char *filename IV Test for file exist
save.c static void do_save void IV Do the saving
save.c static char *set_temp_filename char *new_filename IV Set temporary filename
save.c static char *get_temp_filename void IV Get temporary filename
save.c static char *set_filename char *new_filename IV Set the filename
save.c static char *get_filename void IV Get the filename
main.c void create_main_menu Widget parent IV Create main menu
main.c void create_labels Widget w1, Widget w2, Widget w3, Widget w4, Widget w5 IV Create labels
main.c void handle_expose_1 Widget w, XtPointer client_data,XmDrawingAreaCallbackStruct *call_data IV Handle exposure pic 1
main.c void handle_expose_2 Widget w, XtPointer client_data,XmDrawingAreaCallbackStruct *call_data IV Handle exposure pic 2
main.c void mouse_track_1 Widget w, XtPointer client_data, XEvent *event IV Mouse Tracking pic 1
main.c void mouse_track_2 Widget w, XtPointer client_data, XEvent *event IV Mouse Tracking pic 2
main.c void refresh_action void IV Refresh actions
main.c void refresh_coord int x, int y, int v IV Refreshing mouse coordinates
main.c void sq int b IV Compression handler
main.c void prepare_handlers int sel IV File handler preparation
main.c void remove_event_handlers int sel IV Remove file handlers
main.c void setup_display Widget w IV Setup the display
main.c void print_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Print a file
main.c XtCallbackProc handle_expose_y Widget w, XtPointer client_data,XmDrawingAreaCallbackStruct *call_data IV File handlers for all other files
main.c XtCallbackProc squish Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Compress current file handler
split_merge.c void create_split_dialog Widget parent IV Create the split-merge dialog
split_merge.c void activate_split_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate the dialog
split_merge.c void start_split Widget w, XtPointer client_data,XmSelectionBoxCallbackStruct *call_data IV Start the split-merge
split_merge.c TREEPTR split short deviation, short x, short y, short level IV Start splitting function
split_merge.c static void create_merge_dialog Widget parent IV Create merge dialog
split_merge.c static void activate_merge_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate the merge dialog
split_merge.c static void start_merge Widget w, XtPointer client_data,XmSelectionBoxCallbackStruct *call_data IV Start the merging
split_merge.c static MERGEPTR merge TREEPTR root, short condition IV Merge function
split_merge.c static void analize_tree TREEPTR node, short condition, short reg, int level IV Analyse tree
split_merge.c static void create_merged_region_list MERGEPTR *list IV Merge region list
split_merge.c static void add_new_merged_region MERGEPTR *list IV Add a new merged region
split_merge.c static void insert_leaf_list MERGEPTR *list, TREEPTR leaf IV Insert into list
split_merge.c static void merge_lists MERGEPTR *list1,MERGEPTR *list2 IV Merge lists function
split_merge.c static void display_contour MERGEPTR merged_region_list IV Display contours
split_merge.c static void display_tree TREEPTR node IV Display tree
split_merge.c TREEPTR get_leaf char path[] IV Get a leaf
split_merge.c static Region get_merged_region LEAFPTR actual_region IV Get a merged region
split_merge.c static void free_tree TREEPTR node IV Free the tree memory
split_merge.c static void free_merge MERGEPTR *merged_region_list IV Free the merged regions
split_merge.c static int similar char p[], char q[], short condition IV Similar region comparision
split_merge.c void insert_path PATHPTR *first, PATHPTR *end, char n[] IV Path insertion
split_merge.c static void delete_first PATHPTR *list, char value[] IV Delete first item entry
split_merge.c void view_path_list PATHPTR *path IV View the list
split_merge.c static float get_deviation float mean, float sqr_mean IV Get deviations
version.c void create_version_dialog Widget parent IV Create the version dialog
version.c void activate_version_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data IV Activate the version dialog
version.c void help_moi Widget w, XtPointer client_data, XmAnyCallbackStruct *call_data II Help me function
version.c void deactivate_version_dialog void I Deactivate the version dialog
version.c static void button_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data II OK button callback
watershed.c void watershed_callback Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data II Watershed function callback
watershed.c static void watershed_contour void IV Contour mapping function
watershed.c static void create_p_list NODEPTR *list II Create the p lists
watershed.c static void insert_p_list NODEPTR *list, TPINFO *info IV Insert into p lists
watershed.c static void view_p_list NODEPTR list IV View a p list
watershed.c static void free_p_list NODEPTR list IV Free a p list
watershed.c static void fifo_init TPINFO p, FIFO *pixel_q IV First in first out list initiation
watershed.c static void fifo_add TPINFO p, FIFO *pixel_q IV FIFO add element
watershed.c static TPINFO fifo_first FIFO *pixel_q IV FIFO first element
watershed.c static int fifo_empty FIFO *pixel_q IV FIFO empty testing
watershed.c static int image_pixel int x, int y IV Image pixels retrieve
watershed.c static int labeled_neighbour int x, int y,unsigned long o[IMAGE_WIDTH][IMAGE_HEIGHT] IV Labelled neighbour processing
zoom.c void create_zoom_dialog Widget parent IV Create the zoom dialog
zoom.c void activate_zoom_dialog Widget w, XtPointer client_data,XmAnyCallbackStruct *call_data II Activate the zoom dialog
zoom.c static void ok_button_callback Widget w, XtPointer client_data, XmSelectionBoxCallbackStruct *call_data II OK button callback - Zoom dialog
zoom.c void start_zoom Widget w, XtPointer client_data, XEvent *event II Start Zooming
zoom.c void move_zoom Widget w, XtPointer data, XEvent *p_event II Move the zooming box
 

How can I convert a function written for the old slice to the new environment ?

Very simply. All the old code fits in the new one without any changes at all. It will not execute,
but will compile without any errors. Simply compile it and refer to the basic conversion checklist.
Following that, simply run and debug.

How do I handle Inter-Process-Communications (IPC's) ?

IPC communications via XCUTBUFFER0 are integrally supported within MultiSlice although they have been disabled as there is no known use for them at this stage. Simply uncomment the IPC code in the main file and use it as it has been debugged and tested extensively. The code is simple and is as given below :-
      if(XFetchBytes(p_disp,&i) != NULL){ if(i==21){
      fprintf(stderr,"XCUTBUFF0 written to.\n"); /*Cut Buffer read. */
      XtCloseDisplay(XtDisplay(main_window));exit(-1);}}
      i=21; XStoreBytes(p_disp,text,i); /* Cut buffer write. */
 
How can I change the default icon in MultiSlice ?

Simply save the icon you want in xbm format (X11 Bitmap Metafile) and copy the bit values to
icon.h. Recompile and run. MovieConvert on SGI's should handle the conversion between (say)
a Microsoft Windows .ico file to xbm.

How do I change small things like colors/menus/fonts without writing a Group IV function ?
 
 MultiSlice supports X-Windows screen and device independence. Programmers can change colors, menu text, fonts etc. simply by editing the file Slice and reloading the database with xrdb -load Slice.
The .sgiresources file is given below as shown :-

4Dwm*useIconBox: True
4Dwm*SG_autoSave: False
4Dwm*moveOpaque: True
*multiClickTime: 200
*scheme: Vancouver

The Slice file is given below as shown :-

! Filename Slice
!
! Resource file for MultiSlice RTP located
! in the home directory or in the $APPRESDIR directory

*input label.background:                blueviolet
*input label.foreground:                White
*output label.background:               blueviolet
*output label.foreground:               White
*file label.background:                 blueviolet
*file label.foreground:                 White
*action label.background:               DarkGrey
*action label.foreground:               White
*coord label.background:                DarkGrey
*coord label.foreground:                White

! Resource settings for the main menu
slice*background:                       cadetblue3
slice*borderColor:                      cadetblue1
 

*version dialog_popup.title:            Version Dialog
*version pixmap.background:             IndianRed2
*version title.fontList:               "*times*bold-r*14*"
*version group.fontList:               "*times*bold-r*14*"
*version button.background:             DarkGrey
*version button.foreground:             White
*version button.labelString:            Close
 

How do I test my routine when completed ?
 
 MultiSlice requires Grp I,II,III,IV functions to be tested extensively on implementation. If they cannot be implemented correctly, a sample program should be written to simulate MultiSlice's operation by varying the variables under programmer control. On implementation, the following tests are required of all functions, irrespective of groups :-
1. Normal functioning.
Test the function by running a random function on a file, followed by the function to be tested on the output of the first function.
2. Heavy load functioning.
Test the function under heavy load conditions by loading 20 files, erasing them using the deallocate function, loading another 19 and finally using the function to process a file in the center position (say, 7).
3. Worst case crash testing.
Load 19 files, run your function, simulate an error by putting a small error code into the background processor set to trigger after 15-20 seconds, and run your function again. The small error code can be simulated by inserting the following into the background processor :-
if (time = 90) {error_code();}
Replace error_code with the error to be simulated.
4. Random time testing.
Load a single file into the program. Run your function using the background processor 20 times at random time intervals. The function should run and produce 19 outputs but not execute the 20th time if proper system self-checks have been implemented correctly.
5. User input testing.
If your routine enters user input, simulate an exceptionally large, non-numeric, exceptionally small, negative and zero values as inputs. The routine should be able to reject the invalid input without causing any errors.
6. Interrupt testing.
Change the background processor's time interval from the default of 2000ms to 200ms. Run your function. This will simulate heavy interruption from the background processing mechanism.
7. Memory leak testing.
Your function should have some sort of variable protection mechanism. Simulate random changes to certain variables using the background processor at odd intervals of time.
8. Value testing.
Test your function on a completely white-background file, a black-background and a random-noise background. If the function has a dividing mechanism, test it for a divide by zero. If it has a multiply, test for an infinite multiply output.
9. Screen independence testing.
Test your function by using it in falsecolor mode. If it writes to the screen directly, simulate placing the window in the background, under another window. Simulate false mouse-clicks in invalid areas, attempts to resize the window and fake keypresses.
10. Finally, ask another person to test it. Although this is an optional test, it is best to test it with a second person present at the controls. At the end of these tests, the function should be reasonably well tested. Although it is impossible to completely tyest a function, these tests will ensure a high degree of confidence in correct function execution at run-time.

What is screen independence  and how will it affect me (as a programer) ?
 
Screen independence is a way of isolating what happens on the screen to what actually
is present in the data set. Since the old slice was screen dependent, it was prone to
crashes, garbled data sets and various other effects of using the screen. Changing the
screen mode would effectively change the data set. A program which operated and left
artifacts on the screen could lead to mis-diagnosis at worst or addition of an artifact to
the image. Proceeding with a filter on that same image would lead to unpredictable results.
Since the old slice worked on one image at a time, this effect was minimized to a certain
extent. Working with 10 images at once, would, however, increase the chances of corruption
dramatically. Hence, the data set in MultiSlice is regarded as a read-only object. Functions
are not given permission to change it in any way. They can garble the screen, change the
colors and draw objects over the screen images, but they cannot change the base data set.
As an additional precaution, every image is refreshed from the disk before a function is applied
to it. After a function completes it's task, the image is automatically saved to disk
(each time under a different filename). In addition, if the user does not save the
files and the program terminates normally, the temporary files are wiped clean.
As a programmer, screen independence should not affect you at all. By default,
the environment runs in array mode and no functions use the screen. However, if you have
a very specific function that does use the screen (except for drawing, where full
functionality is provided even in array mode) you will have to run it as a Group IV program
and ensure it does not affect the rest of the program in any way. As of the current date,
there does not appear to be any functions which have to use the screen in any specific
way. XtGetPixel will however, function normally for any Group IV program which has full access
to all system functions. It is NOT recommended to use a screen-dependent function for the
reasons stated above. You may, however, do so if you wish to.
Below is a sample of screen independence at it's best. The system is running in falsecolor
mode. A zoom function is used which does not know anything about the mode used. It does not even
import the falsecolor variable. However, it works on the data set, and, as with all other functions,
it leaves the screen display to a Group IV background processing function.
The result ? A zoom in falsecolor as required with complete screen independence.
Any screen independent function runs in any required screen mode/color without any alterations.
All current MultiSlice functions are completely screen-independent.

FalseColor Mode

Another example is a concurrently running true 3D OpenGL application running in full color
with MultiSlice running in 8-bit gray with twenty files open, minimised.

OpenGL & MultiSlice

 MultiSlice will run perfectly well in conjunction with OpenGL. In addition, several example programs have been executed which demonstrate the implementation of OpenGL in MultiSlice. Although not yet implemented, OpenGL is supported in MultiSlice, both in the API and in the program code.
 
-EOF-