1 ////////////////////////////////////////////////////////
2 // Name     : globalFnc.cpp
3 // Purpose  : Global function definitions for EDISON
4 //            command prompt.
5 // Author   : Chris M. Christoudias
6 // Modified by
7 // Created  : 03/20/2002
8 // Copyright: (c) Chris M. Christoudias
9 // Version  : v0.1
10 ////////////////////////////////////////////////////////
11 
12 #include "defs.h"
13 #include "error.h"
14 #include "parser.h"
15 #include "imfilt.h"
16 #include "edison.h"
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 ////////////////////////////////////////////////////
23 //define global flags
24 ////////////////////////////////////////////////////
25 
26 //segmentation flags
27 bool CmCSynergistic        = false;
28 bool CmCGradWinChanged     = false;
29 bool CmCMixtureChanged     = false;
30 bool CmCUseCustomWeightMap = false;
31 
32 //system flags
33 bool CmCImageDefined       = false;
34 bool CmCMapDefined         = false;
35 bool CmCDisplayProgress    = false;
36 
37 //edge detection flags
38 bool CmCRankMapDefined     = false;
39 bool CmCConfMapDefined     = false;
40 
41 ////////////////////////////////////////////////////////
42 //Declare global EDISON wrapper class object
43 ////////////////////////////////////////////////////////
44 
45 EDISON edison;
46 
47 ////////////////////////////////////////////////////////
48 //Display prompt function
49 ////////////////////////////////////////////////////////
50 
CmCPrompt(const char * PromptStr,...)51 void CmCPrompt(const char *PromptStr, ...)
52 {
53   //obtain argument list using ANSI standard...
54   va_list	argList;
55   va_start(argList, PromptStr);
56 
57   //print the output string to stderr using
58   if(CmCDisplayProgress) vfprintf(stdout, PromptStr, argList);
59   va_end(argList);
60 
61   //done.
62   return;
63 }
64 
65 ////////////////////////////////////////////////////////
66 //Identity (Look-up Table Functions) Functions
67 ////////////////////////////////////////////////////////
68 
69 //************************
70 //identify command type
71 //************************
72 
Command(char * cmd)73 int Command(char *cmd)
74 {
75   int i;
76   for(i = 0; i < CMD_NUM; i++)
77     {
78       if(!strcmp(cmd, CMD_LIST[i])) return i;
79     }
80   return UNKNOWN_COMMAND;
81 }
82 
83 //************************
84 //identify command type
85 //************************
86 
CommandType(int cmdId)87 int CommandType(int cmdId)
88 {
89   return CMD_TYPE_LIST[cmdId];
90 }
91 
92 //************************
93 //identify parameter
94 //************************
95 
Parameter(char * param)96 int Parameter(char *param)
97 {
98   int i;
99   for(i = 0; i < PARAM_NUM; i++)
100     {
101       if(!strcmp(param, PARAM_LIST[i])) return i;
102     }
103   return UNKNOWN_PARAMETER;
104 }
105 
106 //************************
107 //identify custom curve list
108 //************************
109 
CustomCurve(char * curve)110 int CustomCurve(char *curve)
111 {
112   int i;
113   for(i = 0; i < CUST_CURVE_NUM; i++)
114     {
115       if(!strcmp(curve, CUST_CURVE_LIST[i])) return i;
116     }
117   return UNKNOWN_CURVE;
118 }
119 
120 //************************
121 //identify input type
122 //************************
123 
InputType(char * inputtype)124 int InputType(char *inputtype)
125 {
126   int i;
127   for(i = 0; i < INPUTTYPE_NUM; i++) {
128     if(!strcmp(inputtype, INPUTTYPE_LIST[i])) return i;
129   }
130   return INPUT_UNKNOWN;
131 }
132 
133 //************************
134 //identify output type
135 //************************
136 
OutputType(char * outputtype)137 int OutputType(char *outputtype)
138 {
139   int i;
140   for(i = 0; i < OUTPUTTYPE_NUM; i++) {
141     if(!strcmp(outputtype, OUTPUTTYPE_LIST[i])) return i;
142   }
143   return OUTPUT_UNKNOWN;
144 }
145 
146 //************************
147 //identify file type
148 //************************
149 
FileType(char * filetype)150 int FileType(char *filetype)
151 {
152   int i;
153   for(i = 0; i < FILETYPE_NUM; i++) {
154     if(!strcmp(filetype, FILETYPE_LIST[i])) return i;
155   }
156   return FILE_UNKNOWN;
157 }
158 
159 ////////////////////////////////////////////////////////
160 //Report Errors
161 ////////////////////////////////////////////////////////
162 
Report(CmCError * error,char * filename,CmCParser * srcParser)163 void Report(CmCError *error, char *filename, CmCParser *srcParser)
164 {
165 
166   //obtain error code
167   int errorCode = error->errorCode_;
168 
169   //report invalid file error
170   if(errorCode == SYN_INVALID_FILE) {
171     fprintf(stderr, "EDISON Fatal Error: Cannot open file '%s'.\n", filename);
172     fprintf(stderr, "Permission denied or file does not exist.\n");
173     return;
174   }
175 
176   //obtain line number and token string of bad token
177   int  lineNumber = error->token_->lineNumber_;
178   char *token     = error->token_->token_;
179 
180   //***************************************
181   //report syntax error
182   //***************************************
183 
184   //check if out of bounds error
185   if(errorCode == SYN_BOUNDS_ERROR) {
186     fprintf(stderr, "Out of bounds error in file '%s'.\n", filename);
187     fprintf(stderr, "Line %d (parameter %s) Error: %s\n", lineNumber, token,
188 	    boundsTable[BOUNDS_TABLE[Parameter(token)]]);
189     return;
190   }
191 
192   //check for unsupported file formats
193   if(errorCode == SYN_UNSUPPORTED_FILETYPE) {
194     fprintf(stderr, "Version incompatability error:\n");
195     fprintf(stderr, "Line %d (argument '%s') Error: %s\n", lineNumber, token, ErrorMsgTable[errorCode-1]);
196     return;
197   }
198 
199   //decrement error code to index the error message
200   //table correctly (starting from 0 instead of 1)
201   errorCode--;
202 
203   if(errorCode < SYN_INVALID_PARAMCMD) {
204     //report syntax error
205     fprintf(stderr, "Syntax error in file '%s':\n", filename);
206     fprintf(stderr, "Line %d (confused by '%s') Error: %s\n", lineNumber, token, ErrorMsgTable[errorCode]);
207   } else if (errorCode < SYN_ASSIGN_INVALID_ARG) {
208     //report assignment error
209     fprintf(stderr, "Assignment error in file '%s':\n", filename);
210     fprintf(stderr, "Line %d (parameter %s) Error: %s\n", lineNumber, token, ErrorMsgTable[errorCode]);
211   }
212 
213   //***************************************
214   //report run-time error
215   //***************************************
216 
217   //check if parameter is missing
218   if(errorCode == (EXE_MISSING_PARAM-1)) {
219     //report missing parameter
220     fprintf(stderr, "Run-time error cause while running script '%s':\n", filename);
221     fprintf(stderr, "Line %d Fatal Error: Parameter '%s' is not specified.\n", lineNumber, token);
222     delete error->token_;
223     return;
224   }
225 
226   if(errorCode >= SYN_ASSIGN_INVALID_ARG) {
227     //report run-time error
228     fprintf(stderr, "Run-time error caused while running script '%s':\n", filename);
229     fprintf(stderr, "Line %d (at '%s') Fatal Error: %s\n", lineNumber, token, ErrorMsgTable[errorCode]);
230   }
231 
232   //done.
233   return;
234 }
235 
236 ////////////////////////////////////////////////////////
237 //Check Syntax
238 ////////////////////////////////////////////////////////
239 
240 //************************
241 //get token set for a specified command type
242 //************************
243 
GetTokenSet(int cmdId,CmCToken ** tokenSet,CmCParser * synParser)244 int GetTokenSet(int cmdId, CmCToken **tokenSet, CmCParser *synParser)
245 {
246   //obtain token count
247   int tokenCount, cmdTypeId = CommandType(cmdId);
248   switch(cmdTypeId)
249     {
250     case CMD_IO       :
251       switch(cmdId)
252 	{
253 	case CMD_SAVE : tokenCount = 10; break;
254 	case CMD_LOAD : tokenCount =  8; break;
255 	default       : tokenCount =  4; break;
256 	}
257       break;
258     case CMD_EXECUTION: tokenCount = 1; break;
259     case CMD_FLAGS    : tokenCount = 2; break;
260     default           : return UNKNOWN_COMMAND;
261     }
262 
263   //populate token set
264   int i;
265   for(i = 0; i < tokenCount; i++)
266     {
267       if(!(tokenSet[i] = synParser->GetToken()))
268 	return SYN_ERROR;
269     }
270 
271   //Appropriate number of tokens read.
272   return NO_ERRORS;
273 }
274 
275 //************************
276 //get token set for a parameter
277 //************************
278 
GetParamTokenSet(CmCToken ** tokenSet,CmCParser * synParser)279 int GetParamTokenSet(CmCToken **tokenSet, CmCParser *synParser)
280 {
281   int i;
282   for(i = 0; i < 3; i++)
283     {
284       if(!(tokenSet[i] = synParser->GetToken()))
285 	return SYN_ERROR;
286     }
287   return NO_ERRORS;
288 }
289 
290 //************************
291 //check for valid file type
292 //************************
293 
validFileType(char * fileType)294 bool validFileType(char *fileType)
295 {
296   int i;
297   for(i = 0; i < FILETYPE_NUM; i++)
298     if(!strcmp(fileType, FILETYPE_LIST[i])) return true;
299   return false;
300 }
301 
302 //************************
303 //check for valid output type
304 //************************
305 
validOutputType(char * outputType)306 bool validOutputType(char *outputType)
307 {
308   int i;
309   for(i = 0; i < OUTPUTTYPE_NUM; i++)
310     if(!strcmp(outputType, OUTPUTTYPE_LIST[i])) return true;
311   return false;
312 }
313 
314 //************************
315 //check for valid intput type
316 //************************
317 
validInputType(char * inputType)318 bool validInputType(char *inputType)
319 {
320   int i;
321   for(i = 0; i < INPUTTYPE_NUM; i++)
322     if(!strcmp(inputType, INPUTTYPE_LIST[i])) return true;
323   return false;
324 }
325 
326 //************************
327 //check for valid flag
328 //************************
329 
validFlag(char * flag)330 bool validFlag(char *flag)
331 {
332   return !(strcmp(flag, "ON") && strcmp(flag, "OFF"));
333 }
334 
335 //************************
336 //check for valid data type and value
337 //************************
338 
checkInteger(char * data)339 int checkInteger(char *data)
340 {
341   char *dptr = data, ch;
342   while(ch = *(dptr++)) if(((ch < 48)||(ch > 57))&&(ch != '-')) return SYN_ASSIGN_INTEGER;
343   return NO_ERRORS;
344 }
345 
checkFloatingPoint(char * data)346 int checkFloatingPoint(char *data)
347 {
348   char *dptr = data, ch;
349   while(ch = *(dptr++)) if(((ch < 48)||(ch > 57))&&(ch != '.')&&(ch != '-')) return SYN_ASSIGN_FLOAT;
350   return NO_ERRORS;
351 }
352 
checkSpeedup(char * data)353 int checkSpeedup(char *data)
354 {
355   if(strcmp(data, "NONE")&&strcmp(data, "MEDIUM")&&strcmp(data, "HIGH"))
356     return SYN_ASSIGN_SPEEDUP;
357   else
358     return NO_ERRORS;
359 }
360 
checkCurveType(int paramId,char * data)361 int checkCurveType(int paramId, char *data)
362 {
363   int i;
364   for(i = 0; i < CURVE_NUM; i++) {
365     if(paramId == PARAM_NMX_TYPE && i == CURVE_CUSTOM) break;
366     if(!strcmp(data, CURVETYPE_LIST[i])) return NO_ERRORS;
367   }
368   if(i == CURVE_CUSTOM) return SYN_ASSIGN_NMX_CUSTOM;
369   return SYN_ASSIGN_CURVE_TYPE;
370 }
371 
checkBounds(int paramId,char * data)372 int checkBounds(int paramId, char *data)
373 {
374   float dataVal = atof(data);
375   if(UBOUND_LIST[paramId] > 0) {
376     if((dataVal <= 0)||(dataVal < LBOUND_LIST[paramId])||(dataVal > UBOUND_LIST[paramId]))
377       return SYN_BOUNDS_ERROR;
378   } else {
379     if((dataVal <= 0)||(dataVal < LBOUND_LIST[paramId]))
380       return SYN_BOUNDS_ERROR;
381   }
382   return NO_ERRORS;
383 }
384 
checkBounds(char * data,float lower,float upper)385 int checkBounds(char *data, float lower, float upper)
386 {
387   float dataVal = atof(data);
388   if((dataVal < lower)||(dataVal > upper)) return SYN_BOUNDS_ERROR;
389   return NO_ERRORS;
390 }
391 
CheckParameter(int paramId,char * data)392 int CheckParameter(int paramId, char *data)
393 {
394   int error;
395   switch(PARAMTYPE_LIST[paramId])
396     {
397     case PARAM_INTEGER:
398       error = checkInteger(data);
399       if(!error) error = checkBounds(paramId, data);
400       break;
401     case PARAM_FLOAT:
402       error = checkFloatingPoint(data);
403       if(!error) error = checkBounds(paramId, data);
404       break;
405     case PARAM_SPEEDUP_TYPE:
406       error = checkSpeedup(data);
407       break;
408     case PARAM_CURVE_TYPE:
409       error = checkCurveType(paramId, data);
410       break;
411     }
412   return error;
413 }
414 
CheckList(CmCParser * synParser,CmCToken ** token)415 int CheckList(CmCParser *synParser, CmCToken **token)
416 {
417   //check for initial left curl bracket
418   (*token) = synParser->GetToken();
419   if((*token)->token_[0] != '{') return SYN_MISSING_LEFT_CURL;
420 
421   //read in each data point
422   do {
423     (*token) = synParser->GetToken();
424     if((*token)->token_[0] != '(') return SYN_MISSING_LEFT_PARENTHESIS;
425     (*token) = synParser->GetToken();
426     if(checkFloatingPoint((*token)->token_)) return SYN_INCOMPLETE_LIST;
427     if(checkBounds((*token)->token_, 0, 1)) return SYN_ARG_BOUNDS_ERROR;
428     (*token) = synParser->GetToken();
429     if((*token)->token_[0] != ',') return SYN_MISSING_COMMA;
430     (*token) = synParser->GetToken();
431     if(checkFloatingPoint((*token)->token_)) return SYN_INCOMPLETE_LIST;
432     if(checkBounds((*token)->token_, 0, 1)) return SYN_ARG_BOUNDS_ERROR;
433     (*token) = synParser->GetToken();
434     if((*token)->token_[0] != ')') return SYN_MISSING_RIGHT_PARENTHESIS;
435     (*token) = synParser->GetToken();
436     if(((*token)->token_[0] != ',') && ((*token)->token_[0] != '}')) return SYN_MISSING_RIGHT_CURL;
437   } while((*token)->token_[0] != '}');
438 
439   //the point list has proper structure!
440   return NO_ERRORS;
441 }
442 
checkSupported(int filetype)443 int checkSupported(int filetype)
444 {
445   int i;
446   for(i = 0; i < SUPPORT_NUM; i++) {
447     if(filetype == SUPPORTED_FILETYPE_LIST[i]) return NO_ERRORS;
448   }
449   return SYN_UNSUPPORTED_FILETYPE;
450 }
451 
452 //************************
453 //check syntax
454 //************************
455 
CheckSyntax(char * filename,CmCParser * synParser)456 CmCError CheckSyntax(char *filename, CmCParser *synParser)
457 {
458 
459   //*****************************************
460   //parse the file
461   //*****************************************
462 
463   int error;
464   synParser->SetDelimiters("=(){},;'");
465   synParser->StoreDelimiters(true);
466   error = synParser->Parse(filename);
467   if(error) return (CmCError((CmCToken *) NULL, SYN_INVALID_FILE));
468 
469   //*****************************************
470   //check syntax
471   //*****************************************
472 
473   int  curveId;
474   int  parameterId;
475   int  commandTypeId, commandId;
476   CmCToken *token, *(tokenSet)[MAX_TOKEN_NUM];
477   while(token = synParser->GetToken())
478     {
479       //identify the command...
480       commandId     = Command(token->token_);
481       commandTypeId = CommandType(commandId);
482 
483       //based on the command, identify the number of tokens
484       //associated with it and obtain those tokens
485       error = GetTokenSet(commandId, tokenSet, synParser);
486 
487       //if the specified number of tokens does not exist
488       //then return an error
489       if(error == SYN_ERROR) return CmCError((CmCToken *) NULL, error);
490 
491       //if the specified tokens exist, then check them for
492       //their validity
493 
494       switch(commandTypeId)
495 	{
496 	case CMD_IO:
497 	  switch(commandId)
498 	    {
499 	    case CMD_SAVE:
500 	      //check structure
501 	      if(strcmp(tokenSet[0]->token_, "(")) return CmCError(tokenSet[0], SYN_MISSING_LEFT_PARENTHESIS);
502 	      if(strcmp(tokenSet[1]->token_, "'")) return CmCError(tokenSet[1],SYN_MISSING_QUOTATION);
503 	      if(strcmp(tokenSet[3]->token_, "'")) return CmCError(tokenSet[3],SYN_MISSING_QUOTATION);
504 	      if(strcmp(tokenSet[4]->token_, ",")) return CmCError(tokenSet[4],SYN_MISSING_COMMA);
505 	      if(strcmp(tokenSet[6]->token_, ",")) return CmCError(tokenSet[6],SYN_MISSING_COMMA);
506 	      if(strcmp(tokenSet[8]->token_, ")")) return CmCError(tokenSet[8],SYN_MISSING_RIGHT_PARENTHESIS);
507 	      if(strcmp(tokenSet[9]->token_, ";")) return CmCError(tokenSet[9],SYN_MISSING_SEMICOLON);
508 
509 	      //check constants
510 	      if(!validFileType(tokenSet[5]->token_))  return CmCError(tokenSet[5],SYN_INVALID_FILETYPE);
511 	      if(!validOutputType(tokenSet[7]->token_))return CmCError(tokenSet[7],SYN_INVALID_OUTPUTTYPE);
512 	      if(checkSupported(FileType(tokenSet[5]->token_)))
513 		 return CmCError(tokenSet[5],SYN_UNSUPPORTED_FILETYPE);
514 	      break;
515 
516 	    case CMD_LOAD:
517 	      //check structure
518 	      if(strcmp(tokenSet[0]->token_, "(")) return CmCError(tokenSet[0],SYN_MISSING_LEFT_PARENTHESIS);
519 	      if(strcmp(tokenSet[1]->token_, "'")) return CmCError(tokenSet[1],SYN_MISSING_QUOTATION);
520 	      if(strcmp(tokenSet[3]->token_, "'")) return CmCError(tokenSet[3],SYN_MISSING_QUOTATION);
521 	      if(strcmp(tokenSet[4]->token_, ",")) return CmCError(tokenSet[4],SYN_MISSING_COMMA);
522 	      if(strcmp(tokenSet[6]->token_, ")")) return CmCError(tokenSet[6],SYN_MISSING_RIGHT_PARENTHESIS);
523 	      if(strcmp(tokenSet[7]->token_, ";")) return CmCError(tokenSet[7],SYN_MISSING_SEMICOLON);
524 
525 	      //check constants
526 	      if(!validInputType(tokenSet[5]->token_)) return CmCError(tokenSet[5],SYN_INVALID_INPUTTYPE);
527 	      break;
528 
529 	    case CMD_USE_RESULT:
530 	      if(strcmp(tokenSet[0]->token_, "(")) return CmCError(tokenSet[0], SYN_MISSING_LEFT_PARENTHESIS);
531 	      if(strcmp(tokenSet[2]->token_, ")")) return CmCError(tokenSet[2], SYN_MISSING_RIGHT_PARENTHESIS);
532 	      if(strcmp(tokenSet[3]->token_, ";")) return CmCError(tokenSet[3], SYN_MISSING_SEMICOLON);
533 	      if((OutputType(tokenSet[1]->token_) != OUTPUT_SEGM_IMAGE) &&
534 		 (OutputType(tokenSet[1]->token_) != OUTPUT_FILT_IMAGE)) {
535 		if(OutputType(tokenSet[1]->token_) != OUTPUT_UNKNOWN) {
536 		  return CmCError(tokenSet[1], SYN_ASSIGN_INVALID_ARG);
537 		} else {
538 		  return CmCError(tokenSet[1], SYN_INVALID_OUTPUTTYPE);
539 		}
540 	      }
541 	      break;
542 	    }
543 	  break;
544 
545 	case CMD_EXECUTION:
546 	  if(tokenSet[0]->token_[0] != ';') return CmCError(tokenSet[0],SYN_MISSING_SEMICOLON);
547 	  break;
548 	case CMD_FLAGS:
549 	  if(!validFlag(tokenSet[0]->token_)) return CmCError(tokenSet[0],SYN_INVALID_FLAG);
550 	  if(tokenSet[1]->token_[0] != ';')   return CmCError(tokenSet[1],SYN_MISSING_SEMICOLON);
551 	  break;
552 	//unknown command
553 	default:
554 	  break;
555 	}
556 
557       //if its not a command, then maybe its a parameter
558       if(commandTypeId == UNKNOWN_COMMAND) {
559 	//get the parameter type
560 	parameterId = Parameter(token->token_);
561 
562 	if(parameterId != UNKNOWN_PARAMETER) {
563 
564 	  //retreive tokens expected given a parameter
565 	  error = GetParamTokenSet(tokenSet, synParser);
566 	  if(error == SYN_ERROR) return CmCError(token, SYN_ERROR);
567 
568 	  //check those tokens for validity
569 	  if(strcmp(tokenSet[0]->token_, "=")) return CmCError(tokenSet[0],SYN_MISSING_EQUALS);
570 	  if(strcmp(tokenSet[2]->token_, ";")) return CmCError(tokenSet[2],SYN_MISSING_SEMICOLON);
571 
572 	  //make sure parameter is of the right type
573 	  error = CheckParameter(parameterId, tokenSet[1]->token_);
574 	  if(error) return CmCError(token, error);
575 
576  	//if its an unknown parameter then maybe its a curve list
577 	} else {
578 	  //get custom curve
579 	  curveId = CustomCurve(token->token_);
580 
581 	  //if its not a custom curve list then flag an error
582 	  if(curveId == UNKNOWN_CURVE) return CmCError(token,SYN_INVALID_PARAMCMD);
583 
584 	  //check for equals
585 	  token = synParser->GetToken();
586 	  if(token->token_[0] != '=') return CmCError(token,SYN_MISSING_EQUALS);
587 
588 	  //if its a curve list, then check that a proper point list
589 	  //is provided
590 	  error = CheckList(synParser, &token);
591 	  if(error) return CmCError(token, error);
592 
593 	  //check for semicolon
594 	  token = synParser->GetToken();
595 	  if(token->token_[0] != ';') return CmCError(token,SYN_MISSING_SEMICOLON);
596 	}
597       }
598 
599       //command/parameter identified and verified for
600       //its validity, next command/parameter
601     }
602 
603   //reset parser
604   synParser->StartOver();
605 
606   //file is syntaxically correct
607   return CmCError((CmCToken *) NULL, NO_ERRORS);
608 
609 }
610 
611 ////////////////////////////////////////////////////////
612 //Run Script
613 ////////////////////////////////////////////////////////
614 
convert(int paramId,char * data)615 void *convert(int paramId, char *data)
616 {
617   switch(PARAMTYPE_LIST[paramId]) {
618   case PARAM_INTEGER: {
619     int *idata = new int;
620     if(!idata) return (void *) NULL;
621     *idata     = atoi(data);
622     return (void *) idata;
623   }
624   break;
625   case PARAM_FLOAT: {
626     float *fdata = new float;
627     if(!fdata) return (void *) NULL;
628     *fdata       = atof(data);
629     return (void *) fdata;
630   }
631   break;
632   case PARAM_SPEEDUP_TYPE: {
633     int *speed = new int;
634     if(!speed) return (void *) NULL;
635     int i;
636     for(i = 0; i < SPEED_NUM; i++)
637       if(!strcmp(data, SPEEDTYPE_LIST[i])) {
638 	*speed = i;
639 	break;
640       }
641     return (void *) speed;
642   }
643   break;
644   default: {
645     int *curve = new int;
646     if(!curve) return (void *) NULL;
647     int i;
648     for(i = 0; i < CURVE_NUM; i++)
649       if(!strcmp(data, CURVETYPE_LIST[i])) {
650 	*curve = i;
651 	break;
652       }
653     return (void *) curve;
654   }
655   break;
656   }
657 }
658 
findMissing(void ** paramTable,int cmd)659 int findMissing(void **paramTable, int cmd)
660 {
661   switch(cmd) {
662   case CMD_SEGMENT:
663     if(!paramTable[PARAM_SPATIAL_BANDWIDTH]) return PARAM_SPATIAL_BANDWIDTH;
664     if(!paramTable[PARAM_RANGE_BANDWIDTH]) return PARAM_RANGE_BANDWIDTH;
665     if(!paramTable[PARAM_MINIMUM_REGION_AREA]) return PARAM_MINIMUM_REGION_AREA;
666     if(!paramTable[PARAM_SPEEDUP]) return PARAM_SPEEDUP;
667     break;
668   case CMD_FILTER:
669     if(!paramTable[PARAM_SPATIAL_BANDWIDTH]) return PARAM_SPATIAL_BANDWIDTH;
670     if(!paramTable[PARAM_RANGE_BANDWIDTH]) return PARAM_RANGE_BANDWIDTH;
671     if(!paramTable[PARAM_SPEEDUP]) return PARAM_SPEEDUP;
672     break;
673   case CMD_FUSE:
674     if(!paramTable[PARAM_RANGE_BANDWIDTH]) return PARAM_RANGE_BANDWIDTH;
675     if(!paramTable[PARAM_MINIMUM_REGION_AREA]) return PARAM_MINIMUM_REGION_AREA;
676     if(!paramTable[PARAM_SPEEDUP]) return PARAM_SPEEDUP;
677     break;
678   case CMD_EDGE_DETECT: {
679     if(!paramTable[PARAM_GRADIENT_WINDOW_RADIUS]) return PARAM_GRADIENT_WINDOW_RADIUS;
680     int paramId;
681     for(paramId = PARAM_MINIMUM_LENGTH; paramId <= PARAM_HYSTERISIS_LOW_TYPE; paramId++) {
682       if(!paramTable[paramId]) return paramId;
683     }
684     break;
685   }
686   default:
687     break;
688   }
689 
690   if(CmCSynergistic) {
691     int paramId;
692     for(paramId = PARAM_GRADIENT_WINDOW_RADIUS; paramId <= PARAM_EDGE_STRENGTH_THRESHOLD; paramId++) {
693       if(!paramTable[paramId]) return paramId;
694     }
695   }
696   return UNKNOWN_PARAMETER;
697 }
698 
SET(int paramId,CmCParser * script,void ** paramTable)699 int SET(int paramId, CmCParser *script, void **paramTable)
700 {
701   //get data
702   script->GetToken(); //skip equals
703   CmCToken *token = script->GetToken(); //get data
704   char *data = token->token_;
705   script->GetToken(); //skip semi-colon
706 
707   //monitor synergistic parameters
708   if(paramId == PARAM_GRADIENT_WINDOW_RADIUS) {
709     int *idata = (int *) convert(paramId, data);
710     if(!idata) return EXE_OUT_OF_MEMORY;
711     int *old   = (int *)(paramTable[paramId]);
712     if((!old) || (*idata != *old)) {
713       if(old) delete old;
714       paramTable[paramId] = (void *) idata;
715       CmCGradWinChanged   = true;
716       return NO_ERRORS;
717     }
718     delete idata;
719     return NO_ERRORS;
720   }
721   if(paramId == PARAM_MIXTURE_PARAMETER) {
722     float *fdata = (float *) convert(paramId, data);
723     if(!fdata) return EXE_OUT_OF_MEMORY;
724     float *old   = (float *)(paramTable[paramId]);
725     if((!old) || (*fdata != *old)) {
726       if(old) delete old;
727       paramTable[paramId] = (void *) fdata;
728       CmCMixtureChanged   = true;
729       return NO_ERRORS;
730     }
731     delete fdata;
732     return NO_ERRORS;
733   }
734 
735   //de-allocate memory used for old data
736   if(paramTable[paramId]) {
737     if(PARAMTYPE_LIST[paramId] == PARAM_FLOAT) {
738       delete (float *) paramTable[paramId];
739     } else {
740       delete (int *) paramTable[paramId];
741     }
742   }
743 
744   //convert data to appropriate data type
745   //and place it onto the parameter table
746   if(!(paramTable[paramId] = convert(paramId, data))) return EXE_OUT_OF_MEMORY;
747 
748   //parameter set successfully!
749   return NO_ERRORS;
750 }
751 
752 const int MAX_SIZE = 1000;
READLIST(int curveId,CmCParser * script,void ** paramTable)753 int READLIST(int curveId, CmCParser *script, void **paramTable)
754 {
755   //traverse the and read the point list into
756   //the temporary buffer (NOTE: a maximum of MAX_SIZE points
757   //may be read into the point list)
758   float tempBuf[2*MAX_SIZE];
759   CmCToken *token;
760   script->GetToken(); //skip "={"
761   script->GetToken();
762   int n = 0;
763   do {
764     if(n >= MAX_SIZE) return EXE_LONG_POINT_LIST;
765     script->GetToken(); //skip '('
766     token = script->GetToken(); //read x-coordinate
767     tempBuf[2*n] = (float) atof(token->token_);
768     script->GetToken(); //skip ','
769     token = script->GetToken(); //read y-coordinate
770     tempBuf[2*n+1] = (float) atof(token->token_);
771     script->GetToken(); //skip '),'
772     token = script->GetToken();
773     n++; //next data point
774   } while(token->token_[0] != '}');
775   script->GetToken(); //skip ';'
776 
777   //create point list
778   float *data = new float[2*n];
779   if(!data) return EXE_OUT_OF_MEMORY;
780   memcpy(data, tempBuf, 2*n*sizeof(float));
781 
782   //place point list into parameter table
783   paramTable[PARAM_NUM + 2*curveId] = (void *) data;
784   int *nPts = new int;
785   if(!nPts) return EXE_OUT_OF_MEMORY;
786   *nPts = n;
787   paramTable[PARAM_NUM + 2*curveId + 1] = (void *) nPts;
788 
789   //point list has been read successfully!
790   return NO_ERRORS;
791 }
792 
EXECUTE(int cmdId,CmCParser * script,void ** paramTable)793 int EXECUTE(int cmdId, CmCParser *script, void **paramTable)
794 {
795   switch(cmdId) {
796 
797     //***************************************************
798     //set global flags
799     //***************************************************
800 
801   case CMD_SYNERGISTIC: {
802     CmCToken *token;
803     token = script->GetToken(); //get flag
804     if(!strcmp(token->token_, "ON")) {
805       CmCSynergistic = true;
806       CmCPrompt("Synergistic Segmentation ENABLED.\n");
807     } else {
808       CmCSynergistic = false;
809       CmCPrompt("Synergistic Segmentation DISABLED.\n");
810     }
811     script->GetToken(); //skip ';'
812     break;
813   }
814 
815   case CMD_DISPLAY_PROGRESS: {
816     CmCToken *token;
817     token = script->GetToken(); //get flag
818     if(!strcmp(token->token_, "ON"))
819       CmCDisplayProgress = true;
820     else
821       CmCDisplayProgress = false;
822     script->GetToken(); //skip ';'
823     CmCPrompt("Display progress ENABLED.\n");
824     break;
825   }
826 
827   case CMD_USE_CUSTOM_WEIGHT_MAP: {
828     CmCToken *token;
829     token = script->GetToken(); //get flag
830     if(!strcmp(token->token_, "ON")) {
831       CmCUseCustomWeightMap = true;
832       CmCPrompt("Custum weight map IN-USE (if defined).\n");
833     } else {
834       CmCUseCustomWeightMap = false;
835       CmCPrompt("Custum weight map IN-ACTIVE.\n");
836     }
837     script->GetToken(); //skip ';'
838     break;
839   }
840 
841     //***************************************************
842     //load a file
843     //***************************************************
844 
845   case CMD_LOAD: {
846     CmCToken *token;
847     script->GetToken(); //skip "('"
848     script->GetToken();
849     token = script->GetToken(); //get filename
850     char *filename = new char[strlen(token->token_)+1];
851     strcpy(filename, token->token_);
852     script->GetToken(); //skip "',"
853     script->GetToken();
854     token = script->GetToken(); //get input type
855     int inputtype = InputType(token->token_);
856     script->GetToken(); //skip ");"
857     script->GetToken();
858 
859     //load file
860     int error = edison.Load(filename, inputtype);
861     if(!error) CmCPrompt("File '%s' has been successfully loaded!\n", filename);
862     delete [] filename;
863 
864     //return any errors
865     if(error) return error;
866 
867     break;
868   }
869 
870     //***************************************************
871     //save a file
872     //***************************************************
873 
874   case CMD_SAVE: {
875     CmCToken *token;
876     script->GetToken(); //skip "('"
877     script->GetToken();
878     token = script->GetToken(); //get filename
879     char *filename = new char [strlen(token->token_) + 1];
880     strcpy(filename, token->token_);
881     script->GetToken(); //skip "',"
882     script->GetToken();
883     token = script->GetToken(); //filetype
884     int filetype = FileType(token->token_);
885     script->GetToken(); //skip ','
886     token = script->GetToken(); //get output type
887     int outputtype = OutputType(token->token_);
888     script->GetToken(); //skip ");"
889     script->GetToken();
890 
891     //save file
892     int error = edison.Save(filename, filetype, outputtype);
893     if(!error) CmCPrompt("File '%s' has been successfully saved!\n", filename);
894     delete [] filename;
895 
896     //return any errors
897     if(error) return error;
898     break;
899   }
900 
901     //***************************************************
902     //route output to input
903     //***************************************************
904 
905   case CMD_USE_RESULT: {
906     CmCToken *token;
907     script->GetToken(); //skip '('
908     token = script->GetToken(); //get output type
909     int outputtype = OutputType(token->token_);
910     script->GetToken(); //skip ");"
911     script->GetToken();
912 
913     //route output to input
914     int error = edison.UseResult(outputtype);
915     if(!error) {
916       if(outputtype == OUTPUT_SEGM_IMAGE) {
917 	CmCPrompt("Segmented image result has been set as input.\n");
918       } else {
919 	CmCPrompt("Filtered image result has been set as input.\n");
920       }
921     }
922     if(error) return error;
923     break;
924   }
925 
926     //***************************************************
927     //edge detect the input image
928     //***************************************************
929 
930   case CMD_EDGE_DETECT: {
931     edison.SetParameters(paramTable);
932     int error = edison.EdgeDetect();
933     if(error) return error;
934     script->GetToken(); //skip ';'
935     break;
936   }
937 
938     //***************************************************
939     //filter the input image
940     //***************************************************
941 
942   case CMD_FILTER: {
943     edison.SetParameters(paramTable);
944     int error = edison.Filter();
945     if(error) return error;
946     script->GetToken(); //skip ';'
947     break;
948   }
949 
950     //***************************************************
951     //fuse the regions of the input image
952     //***************************************************
953 
954   case CMD_FUSE: {
955     edison.SetParameters(paramTable);
956     int error = edison.Fuse();
957     if(error) return error;
958     script->GetToken(); //skip ';'
959     break;
960   }
961     //***************************************************
962     //segment the input image
963     //***************************************************
964 
965   case CMD_SEGMENT: {
966     edison.SetParameters(paramTable);
967     int error = edison.Segment();
968     if(error) return error;
969     script->GetToken(); //skip ';'
970     break;
971   }
972 
973     //***************************************************
974     //does nothing
975     //***************************************************
976 
977   default:
978     break;
979   }
980 
981   //command executed succesfully!
982   return NO_ERRORS;
983 
984 }
985 
986 //de-allocates the parameter table
DEALLOCATE(void ** paramTable)987 void DEALLOCATE(void **paramTable)
988 {
989   int i;
990   for(i = 0; i < PARAM_NUM + 2*CUST_CURVE_NUM; i++) {
991     if(paramTable[i]) {
992       switch(PARAMTYPE_LIST[i]) {
993       case PARAM_FLOAT: {
994 	float *fdata = (float *) paramTable[i];
995 	delete fdata;
996 	paramTable[i] = (void *) NULL;
997 	break;
998       }
999       default: {
1000 	  int *idata = (int *) paramTable[i];
1001 	  delete idata;
1002 	  paramTable[i] = (void *) NULL;
1003 	  break;
1004 	}
1005       }
1006     }
1007   }
1008 }
1009 
Run(CmCParser * script)1010 CmCError Run(CmCParser *script)
1011 {
1012 
1013   //define and initialize parameter table
1014   void *(paramTable)[PARAM_NUM + 2*CUST_CURVE_NUM];
1015   int i;
1016   for(i = 0; i < PARAM_NUM + 2*CUST_CURVE_NUM; i++)
1017     paramTable[i] = (void *) NULL;
1018 
1019   //parse script, setting parameters and
1020   //running commands along the way...
1021   int      tokenId, error;
1022   CmCToken *token;
1023   while(token = script->GetToken()) {
1024     //determine type of token (parameter or command)
1025     tokenId = Command(token->token_);
1026 
1027     //token is a command, so run it
1028     if(tokenId != UNKNOWN_COMMAND) {
1029       error = EXECUTE(tokenId, script, paramTable);
1030       if(error) {
1031 	if(error == EXE_MISSING_PARAM) {
1032 	  CmCToken *ertok = new CmCToken((char *) PARAM_LIST[findMissing(paramTable, Command(token->token_))],
1033 					 token->lineNumber_);
1034 	  return CmCError(ertok, error);
1035 	} else {
1036 	  return CmCError(token, error);
1037 	}
1038       }
1039     }
1040     //token is a parameter, so set its value
1041     else {
1042       tokenId = Parameter(token->token_);
1043       if(tokenId != UNKNOWN_PARAMETER) {
1044 	error = SET(tokenId, script, paramTable);
1045 	if(error) return CmCError(token, error);
1046       //token is custum curve list, so read it
1047       } else {
1048 	tokenId = CustomCurve(token->token_);
1049 	error = READLIST(tokenId, script, paramTable);
1050 	if(error) return CmCError(token, error);
1051       }
1052     }
1053   }
1054 
1055   //done running script...
1056 
1057   //de-allocate parameter table
1058   DEALLOCATE(paramTable);
1059 
1060   //reset script parser
1061   script->StartOver();
1062 
1063   //script has been run succesfully!
1064   return CmCError((CmCToken *) NULL, NO_ERRORS);
1065 
1066 }
1067 
1068 ////////////////////////////////////////////////////////
1069 //I/O Filters
1070 ////////////////////////////////////////////////////////
1071 
1072 //get the fileformat of an image
CmCGetImageFormat(char * filename)1073 int CmCGetImageFormat(char *filename)
1074 {
1075   if(!filename) return EXE_NULL_PTR;
1076   FILE *fp = fopen(filename, "rb");
1077   if(!fp) return EXE_FILE_READ_ERROR;
1078   char buf[3];
1079   if(!fgets(buf, 3, fp)) {
1080     fclose(fp);
1081     return EXE_FILE_READ_ERROR;
1082   }
1083   fclose(fp);
1084   int i;
1085   for(i = 0; i < FILETYPE_NUM-1; i++) {
1086     if(!strncmp(buf, FILETYPE_HEADER_LIST[i], 2)) return i;
1087   }
1088   return FILE_UNKNOWN;
1089 }
1090 
1091 //converts an image into floating point format
CmCConvertToFloat(unsigned char * image,int height,int width,int dim)1092 float *CmCConvertToFloat(unsigned char *image, int height, int width, int dim)
1093 {
1094   float *data = new float[height * width * dim];
1095   if(!data) return (float *) NULL;
1096   int i;
1097   for(i = 0; i < height * width * dim; i++) {
1098     data[i] = (float)(image[i]);
1099   }
1100   return data;
1101 }
1102 
1103 //converts an image from color to grayscale
1104 const double W1 = 0.299;
1105 const double W2 = 0.587;
1106 const double W3 = 0.114;
CmCConvertToGrayscale(unsigned char * image,int height,int width)1107 unsigned char *CmCConvertToGrayscale(unsigned char *image, int height, int width)
1108 {
1109   unsigned char *data = new unsigned char [height * width];
1110   if(!data) return (unsigned char *) NULL;
1111   int i;
1112   double r, g, b;
1113   for(i = 0; i < height * width; i++) {
1114     r = (double)(image[3*i]);
1115     g = (double)(image[3*i+1]);
1116     b = (double)(image[3*i+2]);
1117     data[i] = (unsigned char)(r*W1 + g*W2 + b*W3);
1118   }
1119   return data;
1120 }
1121 
1122 //write image data
CmCWriteImage(char * filename,unsigned char * image,int height,int width,int dim,int filetype)1123 int CmCWriteImage(char *filename, unsigned char *image, int height, int width, int dim, int filetype)
1124 {
1125   int error, i;
1126   unsigned char *data;
1127   switch(filetype) {
1128   case FILE_PPM:
1129     data = image;
1130     if(dim == 1) {
1131       data = new unsigned char [height * width * 3];
1132       if(!data) return EXE_OUT_OF_MEMORY;
1133       for(i = 0; i < height*width; i++) {
1134 	data[3*i] = data[3*i+1] = data[3*i+2] = image[i];
1135       }
1136     }
1137     error = writePPMImage(filename, data, height, width, 255, (char *) NULL);
1138     if(data != image) delete [] data;
1139     break;
1140   case FILE_PGM:
1141     data = image;
1142     if(dim == 3) {
1143       data = CmCConvertToGrayscale(image, height, width);
1144       if(!data) return EXE_OUT_OF_MEMORY;
1145     }
1146     error = writePGMImage(filename, data, height, width, 255, (char *) NULL);
1147     if(data != image) delete [] data;
1148     break;
1149   case FILE_PNM: {
1150     bool color;
1151     if(dim == 3) {
1152       color = true;
1153     } else {
1154       color = false;
1155     }
1156     error = writePNMImage(filename, image, height, width, 255, color, (char *) NULL);
1157     break;
1158   }
1159   case FILE_MATLAB_ASCII: {
1160     float *fdata = CmCConvertToFloat(image, height, width, dim);
1161     if(!fdata) return EXE_OUT_OF_MEMORY;
1162     error = CmCWriteMFile(filename, fdata, height, width, dim);
1163     delete [] fdata;
1164     break;
1165   }
1166   default:
1167      return EXE_UNSUPPORTED_FILE_FORMAT;
1168   }
1169   if(!error)
1170     return NO_ERRORS;
1171   else
1172     return EXE_FILE_WRITE_ERROR;
1173 }
1174 
1175 //write Matlab ASCII file
CmCWriteMFile(char * filename,float * data,int rows,int cols,int n)1176 int CmCWriteMFile(char *filename, float *data, int rows, int cols, int n)
1177 {
1178   if(!filename || !data) return EXE_NULL_PTR;
1179   FILE *fp = fopen(filename, "wb");
1180   if(!fp) return EXE_FILE_WRITE_ERROR;
1181   int i, j, k;
1182   for(i = 0; i < rows; i++) {
1183     for(j = 0; j < cols-1; j++) {
1184       for(k = 0; k < n; k++) {
1185 	fprintf(fp, "%f ", data[n*(rows*i+j)+k]);
1186       }
1187     }
1188     for(k = 0; k < n-1; k++) {
1189       fprintf(fp, "%f ", data[n*(rows*i+cols-1)+k]);
1190     }
1191     fprintf(fp, "%f\n", data[n*(rows*i+cols-1)+n-1]);
1192     }
1193   fclose(fp);
1194   return NO_ERRORS;
1195 }
1196 
1197 //read image data
CmCReadImage(char * filename,unsigned char ** image,int & height,int & width,int & dim)1198 int CmCReadImage(char *filename, unsigned char **image, int& height, int& width, int& dim)
1199 {
1200   if(!filename) return EXE_NULL_PTR;
1201   int filetype = CmCGetImageFormat(filename);
1202   int error = filetype; //possible error in reading file header
1203   switch(filetype) {
1204   case FILE_PPM:
1205     error = readPPMImage(filename, image, height, width, dim);
1206     dim   = 3;
1207     break;
1208   case FILE_PGM:
1209     error = readPGMImage(filename, image, height, width, dim);
1210     dim   = 1;
1211     break;
1212   case FILE_PNM: {
1213     bool color;
1214     error = readPNMImage(filename, image, height, width, dim, color);
1215     if(color) {
1216       dim = 3;
1217     } else {
1218       dim = 1;
1219     }
1220     break;
1221   }
1222   default:
1223     if(filetype == FILE_UNKNOWN) return EXE_UNKNOWN_FILE_FORMAT;
1224   }
1225 
1226   if(!error)
1227     {
1228       //due to LUV conversion must always work in 5D
1229       if(dim == 1) {
1230 	dim = 3;
1231 	unsigned char *rgbImage = new unsigned char [height * width * dim];
1232 	int i;
1233 	for(i = 0; i < height * width; i++) {
1234 	  rgbImage[3*i] = rgbImage[3*i+1] = rgbImage[3*i+2] = (*image)[i];
1235 	}
1236 	delete [] *image;
1237 	*image = rgbImage;
1238       }
1239       return NO_ERRORS;
1240     }
1241   else
1242     return EXE_FILE_READ_ERROR;
1243 }
1244 
1245 //read Matlab ASCII file
CmCReadMFile(char * filename,float ** data,int rows,int cols)1246 int CmCReadMFile(char *filename, float **data, int rows, int cols)
1247 {
1248   if(!filename || !data) return EXE_NULL_PTR;
1249   FILE *fp = fopen(filename, "rb");
1250   if(!fp) return EXE_FILE_READ_ERROR;
1251   *data = new float [rows * cols];
1252   if(!data) {
1253     fclose(fp);
1254     return EXE_OUT_OF_MEMORY;
1255   }
1256   int i;
1257   for(i = 0; i < rows*cols; i++) {
1258     if(fscanf(fp, "%f", &((*data)[i])) == EOF) {
1259       delete[] *data;
1260       fclose(fp);
1261       return EXE_FILE_READ_ERROR;
1262     }
1263   }
1264   delete[] *data;
1265   fclose(fp);
1266   return NO_ERRORS;
1267 }
1268 
1269 
1270