Esempio n. 1
0
void Fatal (const char* Format, ...)
/* Print a message about a fatal error and die */
{
    va_list ap;

    const char* FileName;
    unsigned    LineNum;
    if (CurTok.LI) {
     	FileName = GetInputName (CurTok.LI);
     	LineNum  = GetInputLine (CurTok.LI);
    } else {
     	FileName = GetCurrentFile ();
     	LineNum  = GetCurrentLine ();
    }

    fprintf (stderr, "%s(%u): Fatal: ", FileName, LineNum);

    va_start (ap, Format);
    vfprintf (stderr, Format, ap);
    va_end (ap);
    fprintf (stderr, "\n");

    if (Line) {
        Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
    }
    exit (EXIT_FAILURE);
}
Bool
XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules)
{
InputLine	line;
RemapSpec	remap;
XkbRF_RuleRec	trule,*rule;
XkbRF_GroupRec  tgroup,*group;

    if (!(rules && file))
	return FALSE;
    bzero((char *)&remap,sizeof(RemapSpec));
    bzero((char *)&tgroup,sizeof(XkbRF_GroupRec));
    InitInputLine(&line);
    while (GetInputLine(file,&line,TRUE)) {
	if (CheckLine(&line,&remap,&trule,&tgroup)) {
            if (tgroup.number) {
	        if ((group= XkbRF_AddGroup(rules))!=NULL) {
		    *group= tgroup;
		    bzero((char *)&tgroup,sizeof(XkbRF_GroupRec));
	        }
	    } else {
	        if ((rule= XkbRF_AddRule(rules))!=NULL) {
		    *rule= trule;
		    bzero((char *)&trule,sizeof(XkbRF_RuleRec));
	        }
	    }
	}
	line.num_line= 0;
    }
    FreeInputLine(&line);
    return TRUE;
}
Esempio n. 3
0
void Internal (const char* Format, ...)
/* Print a message about an internal compiler error and die. */
{
    va_list ap;

    const char* FileName;
    unsigned    LineNum;
    if (CurTok.LI) {
     	FileName = GetInputName (CurTok.LI);
     	LineNum  = GetInputLine (CurTok.LI);
    } else {
     	FileName = GetCurrentFile ();
     	LineNum  = GetCurrentLine ();
    }

    fprintf (stderr, "%s(%u): Internal compiler error:\n",
     	     FileName, LineNum);

    va_start (ap, Format);
    vfprintf (stderr, Format, ap);
    va_end (ap);
    fprintf (stderr, "\n");

    if (Line) {
        fprintf (stderr, "\nInput: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
    }

    /* Use abort to create a core dump */
    abort ();
}
Esempio n. 4
0
void LIWarning (const LineInfo* LI, const char* Format, ...)
/* Print a warning message with the line info given explicitly */
{
    va_list ap;
    va_start (ap, Format);
    IntWarning (GetInputName (LI), GetInputLine (LI), Format, ap);
    va_end (ap);
}
Esempio n. 5
0
void Warning (const char* Format, ...)
/* Print warning message. */
{
    va_list ap;
    va_start (ap, Format);
    IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
    va_end (ap);
}
Esempio n. 6
0
void Error (const char* Format, ...)
/* Print an error message */
{
    va_list ap;
    va_start (ap, Format);
    IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
    va_end (ap);
}
Esempio n. 7
0
/*
   Sample extension to demonstrate executing debugger command

 */
HRESULT CALLBACK
cmdsample(PDEBUG_CLIENT4 Client, PCSTR args)
{
    CHAR Input[256];
    INIT_API();

    UNREFERENCED_PARAMETER(args);

    //
    // Output a 10 frame stack
    //
    g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS |   // Flags on what to do with output
                                   DEBUG_OUTCTL_OVERRIDE_MASK |
                                   DEBUG_OUTCTL_NOT_LOGGED,
                                   NULL,
                                   10,           // number of frames to display
                                   DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_COLUMN_NAMES |
                                   DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_ADDRESSES);
    //
    // Engine interface for print
    //
    g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\nDebugger module list\n");

    //
    // list all the modules by executing lm command
    //
    g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
                          DEBUG_OUTCTL_OVERRIDE_MASK |
                          DEBUG_OUTCTL_NOT_LOGGED,
                          "lm", // Command to be executed
                          DEBUG_EXECUTE_DEFAULT );

    //
    // Ask for user input
    //
    g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\n***User Input sample\n\nEnter Command to run : ");
    GetInputLine(NULL, &Input[0], sizeof(Input));
    Input[ARRAYSIZE(Input) - 1] = 0; // Ensure null termination
    g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
                          DEBUG_OUTCTL_OVERRIDE_MASK |
                          DEBUG_OUTCTL_NOT_LOGGED,
                          Input, // Command to be executed
                          DEBUG_EXECUTE_DEFAULT );

    EXIT_API();
    return S_OK;
}
Esempio n. 8
0
int AI1 (SOptions &Options)
	{
	CSocket theSocket;

	//	Help

	if (!Options.bNoLogo)
		{
		printf("AI1 1.0\n");
		printf("Copyright (c) 2011-2015 by Kronosaur Productions. All Rights Reserved.\n");
		printf("\n");
		}

	if (Options.bHelp)
		{
		printf("ai1 [options] [\"command\"]\n");
		printf("\n");
		printf("  /?              Help.\n");
		printf("  /h:{filespec}   Run HexeDocument.\n");
		printf("  /l              Lisp engine top-level.\n");
		printf("  /n              No logo.\n");
		printf("  /r:{filespec}   Run script file.\n");
		printf("  /s:{hostname}   Connect to given server.\n");
		printf("  /t              Time each command.\n");
		printf("  /z              Do not connect to server.\n");
		printf("  /1              V1 authentication.\n");
		printf("  /!              V1 auth to old server.\n");

		if (Options.bNoConnect)
			return 0;

		printf("\n");
		Options.sSingleCommand = CString("help");
		}

	//	Connect (if necessary)

	if (!ConnectToArcology(STR_ARC_CONSOLE, Options, &theSocket))
		return 1;

	//	If we have a HexeDocument, run it.

	if (!Options.sHexeDocument.IsEmpty())
		return ExecuteHexeDocument(Options);

	//	If we have a script file, defer to it.

	else if (!Options.sScriptFile.IsEmpty())
		return ExecuteScript(Options);

	//	PEM file

	else if (Options.bPEMFile)
		return ExecuteDebugPEMFile(Options.sSingleCommand);

	//	If we have a single command, send it

	else if (!Options.sSingleCommand.IsEmpty())
		{
		printf("%s\n", (LPSTR)Options.sSingleCommand);

		CString sOutput = Execute(theSocket, Options, Options.sSingleCommand);
		PrintUTF8(sOutput);
		printf("\n");

		return 0;
		}

	//	Otherwise, do an interactive loop

	else
		{
		while (true)
			{
			CString sInput = GetInputLine(STR_PROMPT);

			if (strEquals(sInput, STR_QUIT))
				break;

			else if (!sInput.IsEmpty())
				{
				CString sOutput = Execute(theSocket, Options, sInput);
				PrintUTF8(sOutput);
				printf("\n");
				}
			}

		return 0;
		}
	}
Esempio n. 9
0
CString ExecuteUpgrade (CSocket &theSocket, const CString &sCmd)
	{
	int i;

	CString sRoot = fileGetPath(fileGetExecutableFilespec());

	//	Make a list of all executable files to upgrade

	TArray<CString> FileList;
	if (!fileGetFileList(sRoot, NULL_STR, CString("*.exe"), FFL_FLAG_RELATIVE_FILESPEC, &FileList))
		return CString("ERROR: Unable to obtain a list of executable files to upgrade.");

	//	Prepare a request upgrade command

	CStringBuffer Output;
	Output.Write("requestUpgrade (", 16);

	for (i = 0; i < FileList.GetCount(); i++)
		{
		CString sFilespec = fileAppend(sRoot, FileList[i]);

		//	Version

		SFileVersionInfo Info;
		if (!fileGetVersionInfo(sFilespec, &Info))
			{
			printf("ERROR: Unable to get file version: %s\n", (LPSTR)sFilespec);
			continue;
			}

		CIPInteger Version(Info.dwProductVersion);
		CString sVersion = Version.AsString();

		//	Checksum

		DWORD dwChecksum = fileChecksumAdler32(sFilespec);
		if (dwChecksum == 0)
			{
			printf("ERROR: Unable to get file checksum: %s\n", (LPSTR)sFilespec);
			continue;
			}

		CString sOutput = strPattern("{filename:\"%s\" version:%s checksum:%d} ", FileList[i], sVersion, dwChecksum);
		Output.Write(sOutput);
		}

	Output.Write(")", 1);

	//	Send the command

	CString sSend = CString::CreateFromHandoff(Output);
	CString sResult;
	CDatum dResult;
	ExecuteArcologyCommand(theSocket, sSend, &sResult, &dResult);
	if (strEquals(sResult, CString("ERROR")))
		return dResult.AsString();

	//	Show all the files to upgrade

	CDatum dUpgradeDesc = dResult.GetElement(0).GetElement(FIELD_UPGRADE_DESC);
	for (i = 0; i < dUpgradeDesc.GetCount(); i++)
		{
		CDatum dFileDesc = dUpgradeDesc.GetElement(i);

		printf("Upgrading %s\n", (LPSTR)dFileDesc.GetElement(FIELD_FILENAME).AsString());
		}

	//	Confirm

	CString sConfirm = GetInputLine(CString("\nAre you sure you want to upgrade the arcology? [y/n] : "));
	if (*sConfirm.GetParsePointer() != 'y' && *sConfirm.GetParsePointer() != 'Y')
		return NULL_STR;

	//	Upload the new files.

	for (i = 0; i < dUpgradeDesc.GetCount(); i++)
		{
		CDatum dFileDesc = dUpgradeDesc.GetElement(i);
		const CString &sFilename = dFileDesc.GetElement(FIELD_FILENAME);
		CString sFilespec = fileAppend(sRoot, sFilename);

		CString sResult = UploadFile(theSocket, CMD_UPLOAD_UPGRADE, sFilename, sFilespec);
		printf("%s\n", (LPSTR)sResult);
		}

	//	Complete the upgrade

	return ExecuteArcologyCommand(theSocket, CMD_COMPLETE_UPGRADE);
	}
bool potential_cloud_shadow_snow_mask
(
 Input_t *input,
 float cloud_prob_threshold,
 float *ptm,
 float *t_templ,
 float *t_temph,
 unsigned char **cloud_mask,
 unsigned char **shadow_mask,
 unsigned char **snow_mask,
 unsigned char **water_mask,
 unsigned char **final_mask
)
{
    char errstr[MAX_STR_LEN];
    int nrows = input->size.l;
    int ncols = input->size.s;
    int ib = 0;
    int row =0; 
    int col = 0;
    int mask_counter = 0;
    int clear_pixel_counter = 0;
    int clear_land_pixel_counter = 0;
    float ndvi, ndsi;
    int16 *f_temp = NULL;
    int16 *f_wtemp = NULL;
    float visi_mean;
    float whiteness = 0;
    float hot;
    float lndptm;
    float l_pt;
    float h_pt;
    int mask;
    float t_wtemp;
    float **wfinal_prob;
    float **final_prob;
    float wtemp_prob;
    int t_bright;
    float brightness_prob;
    int t_buffer;
    float temp_l;
    float temp_prob;
    float vari_prob;
    float max_value;
    float *prob = NULL;
    float clr_mask;
    float wclr_mask;
    int16 *nir = NULL;
    int16 *swir = NULL;
    float backg_b4;
    float backg_b5;
    float shadow_prob;
    int status;

    /* Dynamic memory allocation */
    unsigned char **clear_mask;
    unsigned char **clear_land_mask;

    clear_mask = (unsigned char **)ias_misc_allocate_2d_array(input->size.l, 
                 input->size.s, sizeof(unsigned char)); 
    clear_land_mask = (unsigned char **)ias_misc_allocate_2d_array(
                 input->size.l, input->size.s, sizeof(unsigned char)); 
    if (clear_mask == NULL || clear_land_mask ==NULL)
    {
        sprintf (errstr, "Allocating mask memory");
        ERROR (errstr, "pcloud");
    }
    
    printf("The first pass\n");

    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
        /* Print status on every 100 lines */
        if (!(row%1000)) 
        {
           printf ("Processing line %d\r",row);
           fflush (stdout);
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine(input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                    "band %d", row, ib);
                ERROR (errstr, "pcloud");
            }
        }

	/* For the thermal band */
	/* Read the input thermal band -- data is read into input->therm_buf */
	if (!GetInputThermLine(input, row))
        {
	  sprintf (errstr, "Reading input thermal data for line %d", row);
	  ERROR (errstr, "pcloud");
	}

   for (col = 0; col < ncols; col++)
    {
     if ((input->buf[2][col] +  input->buf[3][col]) != 0)
      ndvi = (input->buf[3][col] -  input->buf[2][col]) / 
       (input->buf[3][col] +  input->buf[2][col]);
     else
      ndvi = 0.01;

     if ((input->buf[1][col] +  input->buf[4][col]) != 0)
      ndsi = (input->buf[1][col] -  input->buf[4][col]) / 
       (input->buf[1][col] +  input->buf[4][col]);
     else
      ndsi = 0.01;

     /* process non-fill pixels only */
     if (input->therm_buf[col] > -9999)
       {
	 mask = 1;
	 mask_counter++;
       }
     else
       mask = 0;

     /* Basic cloud test */
     if ((ndsi < 0.8) && (ndvi < 0.8) && 
         (input->buf[5][col] > 300) && (input->therm_buf[col] < 2700))
         cloud_mask[row][col] = 1;
     else
         cloud_mask[row][col] = 0;

     /* It takes every snow pixels including snow pixel under thin clouds or 
        icy clouds */
     if ((ndsi > 0.15) && (input->therm_buf[col] < 380) && 
         (input->buf[3][col] > 1100) && (input->buf[1][col] > 1000))
         snow_mask[row][col] = 1;
     else
         snow_mask[row][col] = 0;

     /* Zhe's water test (works over thin cloud) */
     if (((ndvi < 0.01) && (input->buf[3][col] < 1100)) || 
         ((ndvi < 0.1) && (ndvi > 0.0) && 
          (input->buf[3][col] < 500)))
         water_mask[row][col] = 1;
     else 
         water_mask[row][col] = 0;
     if (mask == 0)
         water_mask[row][col] = 255;

     /* visible bands flatness (sum(abs)/mean < 0.6 => brigt and dark cloud) */
     visi_mean = (input->buf[0][col] + input->buf[1][col] +
                  input->buf[2][col]) / 3.0;
     whiteness = ((abs(input->buf[0][col] - visi_mean) + 
      abs(input->buf[1][col] - visi_mean) +
                   abs(input->buf[2][col] - visi_mean)))/ visi_mean;

     /* Update cloud_mask,  if one visible band is saturated, whiteness = 0 */
     if (input->buf[0][col] > input->meta.therm_satu_value_ref ||
	 input->buf[1][col] > input->meta.therm_satu_value_ref ||
	 input->buf[2][col] > input->meta.therm_satu_value_ref)
      whiteness = 0;
     if (cloud_mask[row][col] == 1 && whiteness < 0.7)
      cloud_mask[row][col] = 1; 
     else
      cloud_mask[row][col] = 0;

     /* Haze test */
     hot = input->buf[0][col] - 0.5 *input->buf[2][col] - 800;
     if (cloud_mask[row][col] == 1 && (hot > 0.0 || abs(whiteness) < MINSIGMA))
       cloud_mask[row][col] = 1;
     else
       cloud_mask[row][col] = 0;

     /* Ratio 4/5 > 0.75 test */
     if (cloud_mask[row][col] == 1 && (input->buf[3][col] / 
         input->buf[4][col] > 0.75))
       cloud_mask[row][col] = 1;
     else
       cloud_mask[row][col] = 0;
     
     /* Test whether use thermal band or not */
     if (cloud_mask[row][col] == 0 && mask == 1)
       {
	 clear_mask[row][col] = 1;
	 clear_pixel_counter++;

       }
     else
         clear_mask[row][col] = 0;

     if (water_mask[row][col] != 1 && clear_mask[row][col] == 1)
       {
	 clear_land_mask[row][col] = 1;
         clear_land_pixel_counter++;
       }
     else
       clear_land_mask[row][col] = 0;
    }
}

    *ptm = 100. * ((float)clear_pixel_counter / (float)mask_counter);
    lndptm = 100. * ((float)clear_land_pixel_counter / (float)mask_counter);

    if (*ptm <= 0.1)
     majority_filter(cloud_mask, nrows, ncols);
    else
    {
        f_temp = malloc(input->size.l * input->size.s * sizeof(int16));
	f_wtemp = malloc(input->size.l * input->size.s * sizeof(int16));
	if (f_temp == NULL   || f_wtemp == NULL)
	{
	     sprintf (errstr, "Allocating temp memory");
	     ERROR (errstr, "pcloud");
	}
    }
     
     printf("The second pass\n");
     int16 f_temp_max = 0;
     int16 f_temp_min = 0;
     int16 f_wtemp_max = 0;
     int16 f_wtemp_min = 0;
     int index = 0;
     int index2 = 0;
    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
        /* Print status on every 100 lines */
        if (!(row%1000)) 
        {
	     printf ("Processing line %d\r", row);
	     fflush (stdout);
	   }
	 
	 /* For each of the image bands */
	 for (ib = 0; ib < input->nband; ib++)
	   {
	     /* Read each input reflective band -- data is read into
		input->buf[ib] */
	     if (!GetInputLine(input, ib, row))
	       {
		 sprintf (errstr, "Reading input image data for line %d, "
			  "band %d", row, ib);
		 ERROR (errstr, "pcloud");
	       }
	   }

	 /* For the thermal band */
	 /* Read the input thermal band -- data is read into input->therm_buf */
	 if (!GetInputThermLine(input, row))
	   {
	     sprintf (errstr, "Reading input thermal data for line %d", row);
	     ERROR (errstr, "pcloud");
	   }

	 for (col =0; col < ncols; col++)
	   {
	     if (*ptm <= 0.1) /* No thermal test, 
                                meaningless for snow detection */
	     {
		 /* All cloud */
		 if (cloud_mask[row][col] != 1)
		   shadow_mask[row][col] = 1;
                 else
		   shadow_mask[row][col] = 0;
#if 0
                 /* Tempoarary outpouts */
                 if (water_mask[row][col] == 1)
                     final_mask[row][col] = 1;
                 if (shadow_mask[row][col] == 1)
                     final_mask[row][col] = 2;
                 if (cloud_mask[row][col] == 1)
	             final_mask[row][col] = 4;
                 if (input->therm_buf[col] = -9999)
                     final_mask[row][col] = 255;
#endif
	     }
	     else
	     {		 
		 if (lndptm >= 0.1)
		 {
                     /* get clear land temperature */
		     if (clear_land_mask[row][col] == 1 && 
                         input->therm_buf[col] != -9999)
	             {
			 f_temp[index] = input->therm_buf[col];
                         if (f_temp_max < f_temp[index])
                            f_temp_max = f_temp[index];
                         if (f_temp_min > f_temp[index])
                            f_temp_min = f_temp[index];
			 index++;
	             }
	         }
		 else
	         {
		     /*get clear water temperature */
		     if (clear_mask[row][col] == 1 &&  
                         input->therm_buf[col] != -9999)
	             {
			 f_temp[index] = input->therm_buf[col];
                         if (f_temp_max < f_temp[index])
                            f_temp_max = f_temp[index];
                         if (f_temp_min > f_temp[index])
                            f_temp_min = f_temp[index];
			 index++;
	             }
	         }
		 if (water_mask[row][col] == 1 && input->therm_buf[col] <= 300
                     && input->therm_buf[col] != -9999)
	         {
		     f_wtemp[index2] = input->therm_buf[col];
                     if (f_wtemp[index2] > f_wtemp_max)
                        f_wtemp_max = f_wtemp[index2];
                     if (f_wtemp[index2] < f_wtemp_max)
                        f_wtemp_min = f_wtemp[index2];
                     index2++;
	         }
	     }
         }
    }

   printf("Clear sky pixel percentage in this scene = %.2f\n", *ptm);

   if (*ptm <= 0.1)
   {
      *t_templ = -1.0;
      *t_temph = -1.0;
      return 0;
   }
   else
   {
     /* Tempearture for snow test */
     l_pt = 0.175;
     h_pt = 1 - l_pt;

     printf("====%d,%d,%d,%d\n",f_wtemp_max,f_wtemp_min,f_temp_max,f_temp_min);

#if 0
     prctile(f_wtemp, index2 + 1, 100*h_pt, &t_wtemp);
     /* 0.175 percentile background temperature (low) */
     prctile(f_temp, index + 1, 100*l_pt, t_templ);
     /* 0.825 percentile background temperature (high) */
     prctile (f_temp, index + 1, 100*h_pt, t_temph);
#endif
     t_wtemp = h_pt * (float)(f_wtemp_max-f_wtemp_min) + (float)f_wtemp_min;
     *t_templ = l_pt * (float)(f_temp_max-f_temp_min) + (float)f_temp_min;
     *t_temph = h_pt * (float)(f_temp_max-f_temp_min) + (float)f_temp_min; 
     int f_temp_length;
     int f_wtemp_length;

     f_temp_length = f_temp_max - f_temp_min + 1;
     f_wtemp_length = f_wtemp_max - f_wtemp_min + 1;
#if 0
     prctile(f_wtemp, index2 + 1, f_wtemp_length, 100*h_pt, &t_wtemp);
     /* 0.175 percentile background temperature (low) */
     prctile(f_temp, index + 1, f_temp_length, 100*l_pt, t_templ);
     /* 0.825 percentile background temperature (high) */
     prctile (f_temp, index + 1, f_temp_length, 100*h_pt, t_temph);
#endif
     printf("index, index2 = %d,%d\n",index,index2);

     /* Temperature test */
     t_buffer = 4*100;    
     *t_templ -= t_buffer;
     *t_temph += t_buffer;
     temp_l=*t_temph-*t_templ;

     printf("t_wtemp,t_templ,t_temph = %f,%f,%f\n",t_wtemp,*t_templ,*t_temph);

     /* Relase f_temp memory */
     free(f_wtemp);
     free(f_temp);

     wfinal_prob = (float **)ias_misc_allocate_2d_array(input->size.l, 
                 input->size.s, sizeof(float)); 
     final_prob = (float **)ias_misc_allocate_2d_array(input->size.l, 
                 input->size.s, sizeof(float)); 
     if (wfinal_prob == NULL   ||  final_prob == NULL)
     {
	 sprintf (errstr, "Allocating prob memory");
	 ERROR (errstr, "pcloud");
     }

     printf("The third pass\n");
     /* Loop through each line in the image */
     for (row = 0; row < nrows; row++)
     {
        /* Print status on every 100 lines */
        if (!(row%1000)) 
        {
           printf ("Processing line %d\r",row);
           fflush (stdout);
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine(input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                    "band %d", row, ib);
                ERROR (errstr, "pcloud");
            }
        }

	/* For the thermal band */
	/* Read the input thermal band -- data is read into input->therm_buf */
	if (!GetInputThermLine(input, row))
        {
          sprintf (errstr, "Reading input thermal data for line %d", row);
          ERROR (errstr, "pcloud");
	}

	for (col = 0; col <ncols; col++)
	{
	    /* Get cloud prob over water */
	    /* Temperature test over water */
	    wtemp_prob = (t_wtemp - input->therm_buf[col]) / 400.0;
	    
	    /* Brightness test (over water) */
	    t_bright = 1100;
	    brightness_prob = input->buf[4][col] / t_bright;
	    if (brightness_prob > 1)
	      brightness_prob = 1;
	    
	    /*Final prob mask (water), cloud over water probability */
	    wfinal_prob[row][col] =100 * wtemp_prob * brightness_prob;
	    
            temp_prob=(*t_temph-input->therm_buf[col]) / temp_l;
	    /* Temperature can have prob > 1 */
	    if (temp_prob < 0)
	      temp_prob = 0;
	    
            if ((input->buf[2][col] +  input->buf[3][col]) != 0)
                ndvi = (input->buf[3][col] -  input->buf[2][col]) / 
                   (input->buf[3][col] +  input->buf[2][col]);
            else
                ndvi = 0.01;

            if ((input->buf[1][col] +  input->buf[4][col]) != 0)
                ndsi = (input->buf[1][col] -  input->buf[4][col]) / 
                    (input->buf[1][col] +  input->buf[4][col]);
            else
                ndsi = 0.01;
	    
	    /* NDVI and NDSI should not be negative */
	    if (input->buf[2][col] >= input->meta.therm_satu_value_ref 
                && ndsi < 0)
	      ndsi = 0;
	    if (input->buf[3][col] >= input->meta.therm_satu_value_ref 
                && ndvi < 0)
	      ndvi = 0;
	    
	    /*      Vari_prob=1-max(max(abs(NDSI),abs(NDVI)),whiteness); */
	    if (abs(ndsi) > abs(ndvi))
	      max_value = abs(ndsi);
	    else
	      max_value = abs(ndvi);
	    if (whiteness > max_value)
	      max_value = whiteness;
	    vari_prob = 1 - max_value;
	    
	    /*Final prob mask (land) */
	    final_prob[row][col] = 100 * (temp_prob * vari_prob);
        }
     }

     prob = malloc(input->size.l * input->size.s * sizeof(float));
     if(prob == NULL)
     {
          sprintf (errstr, "Allocating prob memory");
	  ERROR (errstr, "pcloud");
     }

     float prob_max = 0.0;
     float prob_min = 0.0;
     int index3 = 0;
     for (row = 0; row < nrows; row++)
     {
	for (col = 0; col <ncols; col++)
	{	    
	    if (clear_land_mask[row][col] == 1);
	    {
		prob[index3] = final_prob[row][col];
                if ((prob[index3] - prob_max) > MINSIGMA)
                    prob_max = prob[index3];
                if ((prob_min - prob[index3]) > MINSIGMA)
                    prob_min = prob[index3];
		index3++;
	    }
        }
    }

    /*Dynamic threshold for land */
    //    prctile2(prob, index3+1, 100*h_pt, &clr_mask);
    printf("index3,prob_max,prob_min =%d, %f, %f\n",index3,prob_max,prob_min);
    clr_mask = h_pt * (prob_max - prob_min) + prob_min;
    printf("clr_mask =%d, %f\n",index3,clr_mask);
#if 0
    prctile2(prob, index3+1, 100*h_pt, &clr_mask);
    printf("clr_mask = %f\n",clr_mask);
#endif
    clr_mask += cloud_prob_threshold;

    printf("clr_mask = %f\n",clr_mask);
	    
    /* Relase memory for prob */
    free(prob);
	    
    /* Fixed threshold for water */
    wclr_mask = 50.0;
	    
    printf("pcloud probability threshold (land) = %.2f\n", clr_mask);
    
    printf("The fourth pass\n");
    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
        /* Print status on every 100 lines */
        if (!(row%1000)) 
        {
           printf ("Processing line %d\r",row);
           fflush (stdout);
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine(input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                    "band %d", row, ib);
                ERROR (errstr, "pcloud");
            }
        }

	/* For the thermal band */
	/* Read the input thermal band -- data is read into input->therm_buf */
	if (!GetInputThermLine(input, row))
        {
	  sprintf (errstr, "Reading input thermal data for line %d", row);
	  ERROR (errstr, "pcloud");
	}

        for (col =0; col < ncols; col++)
        {
           if ((cloud_mask[row][col] == 1 && final_prob[row][col] > clr_mask &&
              water_mask[row][col] == 0) || (cloud_mask[row][col] == 1 && 
              wfinal_prob[row][col] > wclr_mask && water_mask[row][col] == 1) 
              || (final_prob[row][col] > 99 && water_mask[row][col] == 0) ||
              (input->therm_buf[col] < *t_templ - 3500))
                 cloud_mask[row][col] = 1;
        }
    }

    /* Free the memory */
    status = ias_misc_free_2d_array((void **)wfinal_prob);
    status = ias_misc_free_2d_array((void **)final_prob);

    /* Band 4 flood fill */
    nir = malloc(input->size.l * input->size.s * sizeof(int16)); 
    swir = malloc(input->size.l * input->size.s * sizeof(int16)); 
    if (nir == NULL   || swir == NULL)
    {
        sprintf(errstr, "Allocating nir and swir memory");
        ERROR (errstr, "pcloud");
    }
      
    int16 nir_max = 0;
    int16 swir_max = 0;
    index = 0;
    index2 = 0;
    for (row = 0; row < nrows; row++)
    {
      for (col = 0; col < ncols; col++)
      {
        if (clear_land_mask[row][col] == 1)
	{
	  nir[index] = input->buf[3][col];
          if (nir[index] > nir_max)
           nir_max = nir[index];
	  index++;
	}
      
        if (clear_land_mask[row][col] == 1)
	{
	  nir[index2] = input->buf[4][col];
          if (swir[index2] > swir_max)
           swir_max = swir[index2];
	  index2++;
	}
      }
    }

    status = ias_misc_free_2d_array((void **)clear_mask);
    status = ias_misc_free_2d_array((void **)clear_land_mask);

    /* Improve cloud mask by majority filtering */
    majority_filter(cloud_mask, nrows, ncols);

    /* Estimating background (land) Band 4 Ref */
    backg_b4 = l_pt * nir_max;
    backg_b5 = h_pt * swir_max;
    /* Release the memory */
    free(nir);
    free(swir);
	
    /* May need allocate two memory for new band 4 and 5 after imfill 
       (flood filling), also may need read in whole scene of bands 4 and 5
       for flood filling purpose */
    int16 **new_nir;
    int16 **new_swir;   

    new_nir = (int16 **)ias_misc_allocate_2d_array(input->size.l, 
              input->size.s, sizeof(int16)); 
    new_swir = (int16 **)ias_misc_allocate_2d_array(input->size.l, 
              input->size.s, sizeof(int16)); 
    if (wfinal_prob == NULL  || final_prob == NULL)
    {
        sprintf (errstr, "Allocating prob memory");
        ERROR (errstr, "pcloud");
    }

    printf("The fifth pass\n");

    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
       /* Print status on every 100 lines */
        if (!(row%1000)) 
        {
           printf ("Processing line %d\r",row);
           fflush (stdout);
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine(input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                    "band %d", row, ib);
                ERROR (errstr, "pcloud");
            }
        }

	/* For the thermal band */
	/* Read the input thermal band -- data is read into input->therm_buf */
	if (!GetInputThermLine(input, row))
        {
	  sprintf (errstr, "Reading input thermal data for line %d", row);
	  ERROR (errstr, "pcloud");
	}

        for (col = 0; col < ncols; col++)
        {
           if (input->therm_buf[col] == -9999)
           {
               new_nir[row][col] = backg_b4;
	       new_swir[row][col] = backg_b5;
           }
           else
           {
	       new_nir[row][col] = input->buf[3][col];
	       new_swir[row][col] = input->buf[4][col];
           }
        }
    }

    /* TODO: Fill in regional minimum band 4 ref*/
    IplImage* img = cvCreateImage(cvSize(ncols, nrows), IPL_DEPTH_8U, 1);
    if (!img)
    {
        sprintf (errstr, "Reading input image data for line %d, "
                 "band %d", row, ib);
        ERROR (errstr, "pcloud");
    }
    //     cvSet2D(img, ncols, nrows, new_nir);
    for (row = 0; row < nrows; row++)
    {
       for (col = 0; col < ncols; col++)
       {
           img->imageData[row*ncols+col] = new_nir[row][col];
           // cvSet2D(img, col, row, new_nir[row][col]);
       }
    }
    CvPoint seed_point = cvPoint(3,3);
    CvScalar color = CV_RGB(1,0,0);

    cvFloodFill(img, seed_point, color, cvScalarAll(5.0), cvScalarAll(5.0), 
                NULL, 4, NULL );

    // cvGet2D(img, ncols, nrows, new_nir);
    for (row = 0; row < nrows; row++)
    {
       for (col = 0; col < ncols; col++)
       {
           new_nir[row][col] = img->imageData[row*ncols+col];
           // new_nir[row][col] = cvGet2D(img, col, row);          
       }
    }

    /* Release image memory */
    cvReleaseImage(&img);

    /* TODO: Fill in regional minimum band 5 ref*/
    IplImage* img2 = cvCreateImage(cvSize(ncols, nrows), IPL_DEPTH_8U, 1);
    if (!img2)
    {
        sprintf (errstr, "Reading input image data for line %d, "
                 "band %d", row, ib);
        ERROR (errstr, "pcloud");
    }
    //     cvSet2D(img, ncols, nrows, new_swir);
    for (row = 0; row < nrows; row++)
    {
       for (col = 0; col < ncols; col++)
       {
           img2->imageData[row*ncols+col] = new_swir[row][col];
           // cvSet2D(img2, col, row, new_swir[row][col]);
       }
    }

    cvFloodFill(img2, seed_point, color, cvScalarAll(5.0), cvScalarAll(5.0), 
                NULL, 4, NULL );

    //     cvGet2D(img, ncols, nrows, new_swir);
    for (row = 0; row < nrows; row++)
    {
       for (col = 0; col < ncols; col++)
       {
           new_swir[row][col] = img2->imageData[row*ncols+col];
           // new_swir[row][col] = cvGet2D(img2, col, row);          
       }
    }

    /* Release image memory */
    cvReleaseImage(&img2);

    for (row = 0; row < nrows; row++)
    {
      for (col = 0; col < ncols; col++)
      {
        if (new_nir[row][col] < new_swir[row][col])
	  shadow_prob = new_nir[row][col];
        else
	  shadow_prob = new_swir[row][col];
      
        if (shadow_prob > 200)
	  shadow_mask[row][col] = 1;
        else
	  shadow_mask[row][col] = 0;
      }
    }
    status = ias_misc_free_2d_array((void **)new_nir);
    status = ias_misc_free_2d_array((void **)new_swir);
   }

    printf("The sixth pass\n");
    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
       /* Print status on every 100 lines */
        if (!(row%1000)) 
        {
           printf ("Processing line %d\r",row);
           fflush (stdout);
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine(input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                    "band %d", row, ib);
                ERROR (errstr, "pcloud");
            }
        }

	/* For the thermal band */
	/* Read the input thermal band -- data is read into input->therm_buf */
	if (!GetInputThermLine(input, row))
        {
	  sprintf (errstr, "Reading input thermal data for line %d", row);
	  ERROR (errstr, "pcloud");
	}
     for (col = 0; col < ncols; col++)
     {
        /* refine Water mask - Zhe's water mask (no confusion water/cloud) */
        if (water_mask[row][col] == 1 && cloud_mask[row][col] == 0)
          water_mask[row][col] = 1;
        else
	  water_mask[row][col] = 0;

        if (input->therm_buf[col]==-9999)
	{
	  cloud_mask[row][col] = 255;
	  shadow_mask[row][col] = 255;
          //          final_mask[row][col] = 255;
	}
#if 0
      /* Temporary outputs */      
      if (water_mask[row][col] == 1)
	final_mask[row][col] = 1;
      if (snow_mask[row][col] == 1)
        final_mask[row][col] = 3;
      if (shadow_mask[row][col] == 1)
	final_mask[row][col] = 2;
      if (cloud_mask[row][col] == 1)
	final_mask[row][col] = 4;

      if ((water_mask[row][col] != 1) && (snow_mask[row][col] != 1) &&
          (shadow_cal[row][col] != 1) && (cloud_cal[row][col] != 1) &&
          boundary_test[row][col] != 255)
         final_mask[row][col] = 0;
#endif
     }
   }

   printf("t_wtemp,t_templ,t_temph = %f,%f,%f\n",t_wtemp,*t_templ,*t_temph);

    return 0;
}
Esempio n. 11
0
void CS_Output (CodeSeg* S)
/* Output the code segment data to the output file */
{
    unsigned I;
    const LineInfo* LI;

    /* Get the number of entries in this segment */
    unsigned Count = CS_GetEntryCount (S);

    /* If the code segment is empty, bail out here */
    if (Count == 0) {
	return;
    }

    /* Generate register info */
    CS_GenRegInfo (S);

    /* Output the segment directive */
    WriteOutput (".segment\t\"%s\"\n\n", S->SegName);

    /* Output all entries, prepended by the line information if it has changed */
    LI = 0;
    for (I = 0; I < Count; ++I) {
    	/* Get the next entry */
    	const CodeEntry* E = CollConstAt (&S->Entries, I);
    	/* Check if the line info has changed. If so, output the source line
    	 * if the option is enabled and output debug line info if the debug
    	 * option is enabled.
    	 */
    	if (E->LI != LI) {
    	    /* Line info has changed, remember the new line info */
    	    LI = E->LI;

    	    /* Add the source line as a comment. Beware: When line continuation
             * was used, the line may contain newlines.
             */
    	    if (AddSource) {
                const char* L = LI->Line;
                WriteOutput (";\n; ");
                while (*L) {
                    const char* N = strchr (L, '\n');
                    if (N) {
                        /* We have a newline, just write the first part */
                        WriteOutput ("%.*s\n; ", (int) (N - L), L);
                        L = N+1;
                    } else {
                        /* No Newline, write as is */
                        WriteOutput ("%s\n", L);
                        break;
                    }
                }
                WriteOutput (";\n");
    	    }

    	    /* Add line debug info */
	    if (DebugInfo) {
	       	WriteOutput ("\t.dbg\tline, \"%s\", %u\n",
	       	      	     GetInputName (LI), GetInputLine (LI));
	    }
	}
	/* Output the code */
	CE_Output (E);
    }

    /* If debug info is enabled, terminate the last line number information */
    if (DebugInfo) {
       	WriteOutput ("\t.dbg\tline\n");
    }

    /* Free register info */
    CS_FreeRegInfo (S);
}
Esempio n. 12
0
int main (int argc, const char **argv) {
  Param_t *param = NULL;
  Input_t *input = NULL;
  Lut_t *lut = NULL;
  Output_t *output = NULL;
  Output_t *output_th = NULL;
  int iline, isamp,oline, ib, jb, iz, val;
  unsigned char *line_in = NULL;
  unsigned char *line_in_thz = NULL;
  unsigned char *line_out_qa = NULL;
  int16 *line_out = NULL;
  int16 *line_out_th = NULL;
  int16 *line_out_thz = NULL;
  Cal_stats_t cal_stats;
  Cal_stats6_t cal_stats6;
  int nps,nls, nps6, nls6;
  int zoomx, zoomy;
  int i,odometer_flag=0;
  char msgbuf[1024];
  char envi_file[STR_SIZE]; /* name of the output ENVI header file */
  char *cptr=NULL;          /* pointer to the file extension */
  size_t input_psize;
  int qa_band = QA_BAND_NUM;
  int nband_refl = NBAND_REFL_MAX;
  int ifill, num_zero;
  int maxth=0;
  int mss_flag=0;
  Espa_internal_meta_t xml_metadata;  /* XML metadata structure */
  Envi_header_t envi_hdr;   /* output ENVI header information */

  printf ("\nRunning lndcal ...\n");
  for (i=1; i<argc; i++)if ( !strcmp(argv[i],"-o") )odometer_flag=1;

  /* Read the parameters from the input parameter file */
  param = GetParam(argc, argv);
  if (param == (Param_t *)NULL) EXIT_ERROR("getting runtime parameters",
    "main");

  /* Validate the input metadata file */
  if (validate_xml_file (param->input_xml_file_name) != SUCCESS)
  {  /* Error messages already written */
      EXIT_ERROR("Failure validating XML file", "main");
  }

  /* Initialize the metadata structure */
  init_metadata_struct (&xml_metadata);

  /* Parse the metadata file into our internal metadata structure; also
     allocates space as needed for various pointers in the global and band
     metadata */
  if (parse_metadata (param->input_xml_file_name, &xml_metadata) != SUCCESS)
  {  /* Error messages already written */
    EXIT_ERROR("parsing XML file", "main");
  }

  /* Check to see if the gain and bias values were specified */
  if (!existRadGB (&xml_metadata))
    EXIT_ERROR("Gains and biases don't exist in XML file (TOA radiance gain "
      "and bias fields) for each band.  Make sure to utilize the latest LPGS "
      "MTL file for conversion to the ESPA internal raw binary format as the "
      "gains and biases should be in that file.", "main");
  
  /* Open input file */
  input = OpenInput (&xml_metadata);
  if (input == (Input_t *)NULL)
    EXIT_ERROR("setting up input from XML structure", "main");

  /* Get Lookup table */
  lut = GetLut(param, input->nband, input);
  if (lut == (Lut_t *)NULL) EXIT_ERROR("bad lut file", "main");

  nps6=  input->size_th.s;
  nls6=  input->size_th.l;
  nps =  input->size.s;
  nls =  input->size.l;
  zoomx= nint( (float)nps / (float)nps6 );
  zoomy= nint( (float)nls / (float)nls6 );

  for (ib = 0; ib < input->nband; ib++) 
    cal_stats.first[ib] = true;
  cal_stats6.first = true;
  if (input->meta.inst == INST_MSS)mss_flag=1; 

  /* Open the output files.  Raw binary band files will be be opened. */
  output = OpenOutput(&xml_metadata, input, param, lut, false /*not thermal*/,
    mss_flag);
  if (output == NULL) EXIT_ERROR("opening output file", "main");

  /* Allocate memory for the input buffer, enough for all reflectance bands */
  input_psize = sizeof(unsigned char);
  line_in = calloc (input->size.s * nband_refl, input_psize);
   if (line_in == NULL) 
     EXIT_ERROR("allocating input line buffer", "main");

  /* Create and open output thermal band, if one exists */
  if ( input->nband_th > 0 ) {
    output_th = OpenOutput (&xml_metadata, input, param, lut, true /*thermal*/,
      mss_flag);
    if (output_th == NULL)
      EXIT_ERROR("opening output therm file", "main");

    /* Allocate memory for the thermal input and output buffer, only holds
       one band */
    line_out_th = calloc(input->size_th.s, sizeof(int16));
    if (line_out_th == NULL) 
      EXIT_ERROR("allocating thermal output line buffer", "main");

    if (zoomx == 1) {
      line_out_thz = line_out_th;
      line_in_thz = line_in;
    }
    else {
      line_out_thz = calloc (input->size.s, sizeof(int16));
      if (line_out_thz == NULL) 
        EXIT_ERROR("allocating thermal zoom output line buffer", "main");
      line_in_thz = calloc (input->size.s, input_psize);
      if (line_in_thz == NULL) 
        EXIT_ERROR("allocating thermal zoom input line buffer", "main");
    }
  } else {
    printf("*** no output thermal file ***\n"); 
  }

  /* Allocate memory for output lines for both the image and QA data */
  line_out = calloc (input->size.s, sizeof (int16));
  if (line_out == NULL) 
    EXIT_ERROR("allocating output line buffer", "main");

  line_out_qa = calloc (input->size.s, sizeof(unsigned char));
  if (line_out_qa == NULL) 
    EXIT_ERROR("allocating qa output line buffer", "main");
  memset (line_out_qa, 0, input->size.s * sizeof(unsigned char));    

  /* Do for each THERMAL line */
  oline= 0;
  if (input->nband_th > 0) {
    ifill= (int)lut->in_fill;
    for (iline = 0; iline < input->size_th.l; iline++) {
      ib=0;
      if (!GetInputLineTh(input, iline, line_in))
        EXIT_ERROR("reading input data for a line", "main");

      if ( odometer_flag && ( iline==0 || iline ==(nls-1) || iline%100==0  ) ){ 
        if ( zoomy == 1 )
          printf("--- main loop BAND6 Line %d --- \r",iline); 
        else
          printf("--- main loop BAND6 Line in=%d out=%d --- \r",iline,oline); 
        fflush(stdout); 
      }

      memset(line_out_qa, 0, input->size.s*sizeof(unsigned char));    
      if (!Cal6(lut, input, line_in, line_out_th, line_out_qa, &cal_stats6,
        iline))
        EXIT_ERROR("doing calibration for a line", "main");

      if ( zoomx>1 ) {
        zoomIt(line_out_thz, line_out_th, nps/zoomx, zoomx );
        zoomIt8(line_in_thz, line_in, nps/zoomx, zoomx );
      }

      for ( iz=0; iz<zoomy; iz++ ) {
        for (isamp = 0; isamp < input->size.s; isamp++) {
          val= getValue(line_in_thz, isamp);
          if ( val> maxth) maxth=val;
          if ( val==ifill) line_out_qa[isamp] = lut->qa_fill; 
          else if ( val>=SATU_VAL6 ) line_out_qa[isamp] = ( 0x000001 << 6 ); 
        }

        if ( oline<nls ) {
          if (!PutOutputLine(output_th, ib, oline, line_out_thz)) {
            sprintf(msgbuf,"write thermal error ib=%d oline=%d iline=%d",ib,
              oline,iline);
            EXIT_ERROR(msgbuf, "main");
          }

          if (input->meta.inst != INST_MSS) 
            if (!PutOutputLine(output_th, ib+1, oline, line_out_qa)) {
	          sprintf(msgbuf,"write thermal QA error ib=%d oline=%d iline=%d",
                ib+1,oline,iline);
              EXIT_ERROR(msgbuf, "main");
            }
        }
        oline++;
      }
    } /* end loop for each thermal line */
  }
  if (odometer_flag) printf("\n");

  if (input->nband_th > 0)
    if (!CloseOutput(output_th))
      EXIT_ERROR("closing output thermal file", "main");

  /* Do for each REFLECTIVE line */
  ifill= (int)lut->in_fill;
  for (iline = 0; iline < input->size.l; iline++){
    /* Do for each band */

    if ( odometer_flag && ( iline==0 || iline ==(nls-1) || iline%100==0  ) )
     {printf("--- main reflective loop Line %d ---\r",iline); fflush(stdout);}

    memset(line_out_qa, 0, input->size.s*sizeof(unsigned char));
    
    for (ib = 0; ib < input->nband; ib++) {
      if (!GetInputLine(input, ib, iline, &line_in[ib*nps]))
        EXIT_ERROR("reading input data for a line", "main");
    }
    
    for (isamp = 0; isamp < input->size.s; isamp++){
      num_zero=0;
      for (ib = 0; ib < input->nband; ib++) {
        jb= (ib != 5 ) ? ib+1 : ib+2;
        val= getValue((unsigned char *)&line_in[ib*nps], isamp);
	    if ( val==ifill   )num_zero++;
        if ( val==SATU_VAL[ib] ) line_out_qa[isamp]|= ( 0x000001 <<jb ); 
      }
      /* Feng fixed bug by changing "|=" to "=" below (4/17/09) */
      if ( num_zero >  0 )line_out_qa[isamp] = lut->qa_fill; 
    }

    for (ib = 0; ib < input->nband; ib++) {
      if (!Cal(lut, ib, input, &line_in[ib*nps], line_out, line_out_qa,
        &cal_stats,iline))
        EXIT_ERROR("doing calibraton for a line", "main");

      if (!PutOutputLine(output, ib, iline, line_out))
        EXIT_ERROR("reading input data for a line", "main");
    } /* End loop for each band */
        
    if (input->meta.inst != INST_MSS) 
      if (!PutOutputLine(output, qa_band, iline, line_out_qa))
        EXIT_ERROR("writing qa data for a line", "main");
  } /* End loop for each line */

  if ( odometer_flag )printf("\n");

  for (ib = 0; ib < input->nband; ib++) {
    printf(
      " band %d rad min %8.5g max %8.4f  |  ref min  %8.5f max  %8.4f\n", 
      input->meta.iband[ib], cal_stats.rad_min[ib], cal_stats.rad_max[ib],
      cal_stats.ref_min[ib], cal_stats.ref_max[ib]);
  }

  if ( input->nband_th > 0 )
    printf(
      " band %d rad min %8.5g max %8.4f  |  tmp min  %8.5f max  %8.4f\n", 6,
      cal_stats6.rad_min,  cal_stats6.rad_max,
      cal_stats6.temp_min, cal_stats6.temp_max);

  /* Close input and output files */
  if (!CloseInput(input)) EXIT_ERROR("closing input file", "main");
  if (!CloseOutput(output)) EXIT_ERROR("closing input file", "main");

  /* Write the ENVI header for reflectance files */
  for (ib = 0; ib < output->nband; ib++) {
    /* Create the ENVI header file this band */
    if (create_envi_struct (&output->metadata.band[ib], &xml_metadata.global,
      &envi_hdr) != SUCCESS)
        EXIT_ERROR("Creating the ENVI header structure for this file.", "main");

    /* Write the ENVI header */
    strcpy (envi_file, output->metadata.band[ib].file_name);
    cptr = strchr (envi_file, '.');
    strcpy (cptr, ".hdr");
    if (write_envi_hdr (envi_file, &envi_hdr) != SUCCESS)
        EXIT_ERROR("Writing the ENVI header file.", "main");
  }

  /* Write the ENVI header for thermal files */
  for (ib = 0; ib < output_th->nband; ib++) {
    /* Create the ENVI header file this band */
    if (create_envi_struct (&output_th->metadata.band[ib], &xml_metadata.global,
      &envi_hdr) != SUCCESS)
        EXIT_ERROR("Creating the ENVI header structure for this file.", "main");

    /* Write the ENVI header */
    strcpy (envi_file, output_th->metadata.band[ib].file_name);
    cptr = strchr (envi_file, '.');
    strcpy (cptr, ".hdr");
    if (write_envi_hdr (envi_file, &envi_hdr) != SUCCESS)
        EXIT_ERROR("Writing the ENVI header file.", "main");
  }

  /* Append the reflective and thermal bands to the XML file */
  if (append_metadata (output->nband, output->metadata.band,
    param->input_xml_file_name) != SUCCESS)
    EXIT_ERROR("appending reflectance and QA bands", "main");
  if (input->nband_th > 0) {
    if (append_metadata (output_th->nband, output_th->metadata.band,
      param->input_xml_file_name) != SUCCESS)
      EXIT_ERROR("appending thermal and QA bands", "main");
  }

  /* Free the metadata structure */
  free_metadata (&xml_metadata);

  /* Free memory */
  if (!FreeParam(param)) 
    EXIT_ERROR("freeing parameter stucture", "main");

  if (!FreeInput(input)) 
    EXIT_ERROR("freeing input file stucture", "main");

  if (!FreeLut(lut)) 
    EXIT_ERROR("freeing lut file stucture", "main");

  if (!FreeOutput(output)) 
    EXIT_ERROR("freeing output file stucture", "main");

  free(line_out);
  line_out = NULL;
  free(line_in);
  line_in = NULL;
  free(line_out_qa);
  line_out_qa = NULL;
  free(line_out_th);
  line_out_th = NULL;
  if (zoomx != 1) {
    free(line_in_thz);
    free(line_out_thz);
  }
  line_in_thz = NULL;
  line_out_thz = NULL;

  /* All done */
  printf ("lndcal complete.\n");
  return (EXIT_SUCCESS);
}
/******************************************************************************
MODULE:  potential_cloud_shadow_snow_mask

PURPOSE: Identify the cloud pixels, snow pixels, water pixels, clear land 
         pixels, and potential shadow pixels

RETURN: SUCCESS
        FAILURE

HISTORY:
Date        Programmer       Reason
--------    ---------------  -------------------------------------
3/15/2013   Song Guo         Original Development

NOTES: 
1. Thermal buffer is expected to be in degrees Celsius with a factor applied
   of 100.  Many values which compare to the thermal buffer in this code are
   hardcoded and assume degrees celsius * 100.
******************************************************************************/
int potential_cloud_shadow_snow_mask
(
    Input_t * input,            /*I: input structure */
    float cloud_prob_threshold, /*I: cloud probability threshold */
    float *ptm,                 /*O: percent of clear-sky pixels */
    float *t_templ,             /*O: percentile of low background temp */
    float *t_temph,             /*O: percentile of high background temp */
    unsigned char **pixel_mask, /*I/O: pixel mask */
    bool verbose                /*I: value to indicate if intermediate
                                     messages be printed */
)
{
    char errstr[MAX_STR_LEN];   /* error string */
    int nrows = input->size.l;  /* number of rows */
    int ncols = input->size.s;  /* number of columns */
    int ib = 0;                 /* band index */
    int row = 0;                /* row index */
    int col = 0;                /* column index */
    int mask_counter = 0;       /* mask counter */
    int clear_pixel_counter = 0;        /* clear sky pixel counter */
    int clear_land_pixel_counter = 0;   /* clear land pixel counter */
    float ndvi, ndsi;           /* NDVI and NDSI values */
    int16 *f_temp = NULL;       /* clear land temperature */
    int16 *f_wtemp = NULL;      /* clear water temperature */
    float visi_mean;            /* mean of visible bands */
    float whiteness = 0.0;      /* whiteness value */
    float hot;                  /* hot value for hot test */
    float lndptm;               /* clear land pixel percentage */
    float l_pt;                 /* low percentile threshold */
    float h_pt;                 /* high percentile threshold */
    float t_wtemp;              /* high percentile water temperature */
    float **wfinal_prob = NULL; /* final water pixel probabilty value */
    float **final_prob = NULL;  /* final land pixel probability value */
    float wtemp_prob;           /* water temperature probability value */
    int t_bright;               /* brightness test value for water */
    float brightness_prob;      /* brightness probability value */
    int t_buffer;               /* temperature test buffer */
    float temp_l;               /* difference of low/high tempearture
                                   percentiles */
    float temp_prob;            /* temperature probability */
    float vari_prob;            /* probability from NDVI, NDSI, and whiteness */
    float max_value;            /* maximum value */
    float *prob = NULL;         /* probability value */
    float *wprob = NULL;        /* probability value */
    float clr_mask = 0.0;       /* clear sky pixel threshold */
    float wclr_mask = 0.0;      /* water pixel threshold */
    int16 *nir = NULL;          /* near infrared band (band 4) data */
    int16 *swir = NULL;         /* short wavelength infrared (band 5) data */
    float backg_b4;             /* background band 4 value */
    float backg_b5;             /* background band 5 value */
    int16 shadow_prob;          /* shadow probability */
    int status;                 /* return value */
    int satu_bv;                /* sum of saturated bands 1, 2, 3 value */
    unsigned char mask;         /* mask used for 1 pixel */

    /* Dynamic memory allocation */
    unsigned char **clear_mask = NULL;

    clear_mask = (unsigned char **) allocate_2d_array (input->size.l,
                                                       input->size.s,
                                                       sizeof (unsigned char));
    if (clear_mask == NULL)
        RETURN_ERROR ("Allocating mask memory", "pcloud", FAILURE);

    if (verbose)
        printf ("The first pass\n");

    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
        if (verbose)
        {
            /* Print status on every 1000 lines */
            if (!(row % 1000))
            {
                printf ("Processing line %d\r", row);
                fflush (stdout);
            }
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine (input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                         "band %d", row, ib);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }
        }

        /* For the thermal band */
        /* Read the input thermal band -- data is read into input->therm_buf */
        if (!GetInputThermLine (input, row))
        {
            sprintf (errstr, "Reading input thermal data for line %d", row);
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        for (col = 0; col < ncols; col++)
        {
            int ib;
            for (ib = 0; ib < BI_REFL_BAND_COUNT; ib++)
            {
                if (input->buf[ib][col] == input->meta.satu_value_ref[ib])
                    input->buf[ib][col] = input->meta.satu_value_max[ib];
            }
            if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                input->therm_buf[col] = input->meta.therm_satu_value_max;

            /* process non-fill pixels only
               Due to a problem with the input LPGS data, the thermal band
               may have values less than -9999 after scaling so exclude those
               as well */
            if (input->therm_buf[col] <= -9999
                || input->buf[BI_BLUE][col] == -9999
                || input->buf[BI_GREEN][col] == -9999
                || input->buf[BI_RED][col] == -9999
                || input->buf[BI_NIR][col] == -9999
                || input->buf[BI_SWIR_1][col] == -9999
                || input->buf[BI_SWIR_2][col] == -9999)
            {
                mask = 0;
            }
            else
            {
                mask = 1;
                mask_counter++;
            }

            if ((input->buf[BI_RED][col] + input->buf[BI_NIR][col]) != 0
                && mask == 1)
            {
                ndvi = (float) (input->buf[BI_NIR][col]
                                - input->buf[BI_RED][col])
                       / (float) (input->buf[BI_NIR][col]
                                  + input->buf[BI_RED][col]);
            }
            else
                ndvi = 0.01;

            if ((input->buf[BI_GREEN][col] + input->buf[BI_SWIR_1][col]) != 0
                && mask == 1)
            {
                ndsi = (float) (input->buf[BI_GREEN][col]
                                - input->buf[BI_SWIR_1][col])
                       / (float) (input->buf[BI_GREEN][col]
                                  + input->buf[BI_SWIR_1][col]);
            }
            else
                ndsi = 0.01;

            /* Basic cloud test, equation 1 */
            if (((ndsi - 0.8) < MINSIGMA)
                && ((ndvi - 0.8) < MINSIGMA)
                && (input->buf[BI_SWIR_2][col] > 300)
                && (input->therm_buf[col] < 2700))
            {
                pixel_mask[row][col] |= 1 << CLOUD_BIT;
            }
            else
                pixel_mask[row][col] &= ~(1 << CLOUD_BIT);

            /* It takes every snow pixels including snow pixel under thin 
               clouds or icy clouds, equation 20 */
            if (((ndsi - 0.15) > MINSIGMA)
                && (input->therm_buf[col] < 1000)
                && (input->buf[BI_NIR][col] > 1100)
                && (input->buf[BI_GREEN][col] > 1000))
            {
                pixel_mask[row][col] |= 1 << SNOW_BIT;
            }
            else
                pixel_mask[row][col] &= ~(1 << SNOW_BIT);

            /* Zhe's water test (works over thin cloud), equation 5 */
            if (((((ndvi - 0.01) < MINSIGMA)
                  && (input->buf[BI_NIR][col] < 1100))
                 || (((ndvi - 0.1) < MINSIGMA)
                     && (ndvi > MINSIGMA)
                     && (input->buf[BI_NIR][col] < 500)))
                && (mask == 1))
            {
                pixel_mask[row][col] |= 1 << WATER_BIT;
            }
            else
                pixel_mask[row][col] &= ~(1 << WATER_BIT);
            if (mask == 0)
                pixel_mask[row][col] |= 1 << FILL_BIT;

            /* visible bands flatness (sum(abs)/mean < 0.6 => brigt and dark 
               cloud), equation 2 */
            if ((pixel_mask[row][col] & (1 << CLOUD_BIT)) && mask == 1)
            {
                visi_mean = (float) (input->buf[BI_BLUE][col]
                                     + input->buf[BI_GREEN][col]
                                     + input->buf[BI_RED][col]) / 3.0;
                if (visi_mean != 0)
                {
                    whiteness =
                        ((fabs ((float) input->buf[BI_BLUE][col] - visi_mean)
                          + fabs ((float) input->buf[BI_GREEN][col] - visi_mean)
                          + fabs ((float) input->buf[BI_RED][col]
                                  - visi_mean))) / visi_mean;
                }
                else
                {
                    /* Just put a large value to remove them from cloud pixel
                       identification */
                    whiteness = 100.0;
                }
            }

            /* Update cloud_mask,  if one visible band is saturated,
               whiteness = 0, due to data type conversion, pixel value
               difference of 1 is possible */
            if ((input->buf[BI_BLUE][col]
                 >= (input->meta.satu_value_max[BI_BLUE] - 1))
                ||
                (input->buf[BI_GREEN][col]
                 >= (input->meta.satu_value_max[BI_GREEN] - 1))
                ||
                (input->buf[BI_RED][col]
                 >= (input->meta.satu_value_max[BI_RED] - 1)))
            {
                whiteness = 0.0;
                satu_bv = 1;
            }
            else
            {
                satu_bv = 0;
            }

            if ((pixel_mask[row][col] & (1 << CLOUD_BIT)) &&
                (whiteness - 0.7) < MINSIGMA)
                pixel_mask[row][col] |= 1 << CLOUD_BIT;
            else
                pixel_mask[row][col] &= ~(1 << CLOUD_BIT);

            /* Haze test, equation 3 */
            hot =
                (float) input->buf[BI_BLUE][col] -
                0.5 * (float) input->buf[BI_RED][col] - 800.0;
            if ((pixel_mask[row][col] & (1 << CLOUD_BIT))
                && (hot > MINSIGMA || satu_bv == 1))
                pixel_mask[row][col] |= 1 << CLOUD_BIT;
            else
                pixel_mask[row][col] &= ~(1 << CLOUD_BIT);

            /* Ratio 4/5 > 0.75 test, equation 4 */
            if ((pixel_mask[row][col] & (1 << CLOUD_BIT)) &&
                input->buf[BI_SWIR_1][col] != 0)
            {
                if ((float) input->buf[BI_NIR][col] /
                    (float) (input->buf[BI_SWIR_1][col]) - 0.75 > MINSIGMA)
                    pixel_mask[row][col] |= 1 << CLOUD_BIT;
                else
                    pixel_mask[row][col] &= ~(1 << CLOUD_BIT);
            }
            else
                pixel_mask[row][col] &= ~(1 << CLOUD_BIT);

            /* Test whether use thermal band or not */
            if ((!(pixel_mask[row][col] & (1 << CLOUD_BIT))) && mask == 1)
            {
                clear_mask[row][col] |= 1 << CLEAR_BIT;
                clear_pixel_counter++;
            }
            else
                clear_mask[row][col] &= ~(1 << CLEAR_BIT);

            if ((!(pixel_mask[row][col] & (1 << WATER_BIT))) &&
                clear_mask[row][col] & (1 << CLEAR_BIT))
            {
                clear_mask[row][col] |= 1 << CLEAR_LAND_BIT;
                clear_land_pixel_counter++;
                clear_mask[row][col] &= ~(1 << CLEAR_WATER_BIT);
            }
            else if ((pixel_mask[row][col] & (1 << WATER_BIT)) &&
                     clear_mask[row][col] & (1 << CLEAR_BIT))
            {
                clear_mask[row][col] |= 1 << CLEAR_WATER_BIT;
                clear_mask[row][col] &= ~(1 << CLEAR_LAND_BIT);
            }
            else
            {
                clear_mask[row][col] &= ~(1 << CLEAR_WATER_BIT);
                clear_mask[row][col] &= ~(1 << CLEAR_LAND_BIT);
            }
        }
    }
    printf ("\n");

    *ptm = 100. * ((float) clear_pixel_counter / (float) mask_counter);
    lndptm = 100. * ((float) clear_land_pixel_counter / (float) mask_counter);

    if (verbose)
    {
        printf ("clear_pixels, clear_land_pixels, mask_counter = %d,%d,%d\n",
                clear_pixel_counter, clear_land_pixel_counter, mask_counter);
        printf ("*ptm, lndptm=%f,%f\n", *ptm, lndptm);
    }

    if ((*ptm - 0.1) <= MINSIGMA) /* No thermal test is needed, all clouds */
    {
        *t_templ = -1.0;
        *t_temph = -1.0;
        for (row = 0; row < nrows; row++)
        {
            for (col = 0; col < ncols; col++)
            {
                /* All cloud */
                if (!(pixel_mask[row][col] & (1 << CLOUD_BIT)))
                    pixel_mask[row][col] |= 1 << SHADOW_BIT;
                else
                    pixel_mask[row][col] &= ~(1 << SHADOW_BIT);
            }
        }
    }
    else
    {
        f_temp = malloc (input->size.l * input->size.s * sizeof (int16));
        f_wtemp = malloc (input->size.l * input->size.s * sizeof (int16));
        if (f_temp == NULL || f_wtemp == NULL)
        {
            sprintf (errstr, "Allocating temp memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The second pass\n");

        int16 f_temp_max = SHRT_MIN;
        int16 f_temp_min = SHRT_MAX;
        int16 f_wtemp_max = SHRT_MIN;
        int16 f_wtemp_min = SHRT_MAX;
        int index = 0;
        int index2 = 0;
        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For the thermal band, read the input thermal band  */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            for (col = 0; col < ncols; col++)
            {
                if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                    input->therm_buf[col] = input->meta.therm_satu_value_max;

                if ((lndptm - 0.1) >= MINSIGMA)
                {
                    /* get clear land temperature */
                    if (clear_mask[row][col] & (1 << CLEAR_LAND_BIT))
                    {
                        f_temp[index] = input->therm_buf[col];
                        if (f_temp_max < f_temp[index])
                            f_temp_max = f_temp[index];
                        if (f_temp_min > f_temp[index])
                            f_temp_min = f_temp[index];
                        index++;
                    }
                }
                else
                {
                    /* get clear water temperature */
                    if (clear_mask[row][col] & (1 << CLEAR_BIT))
                    {
                        f_temp[index] = input->therm_buf[col];
                        if (f_temp_max < f_temp[index])
                            f_temp_max = f_temp[index];
                        if (f_temp_min > f_temp[index])
                            f_temp_min = f_temp[index];
                        index++;
                    }
                }
                /* Equation 7 */
                if (clear_mask[row][col] & (1 << CLEAR_WATER_BIT))
                {
                    f_wtemp[index2] = input->therm_buf[col];
                    if (f_wtemp[index2] > f_wtemp_max)
                        f_wtemp_max = f_wtemp[index2];
                    if (f_wtemp[index2] < f_wtemp_min)
                        f_wtemp_min = f_wtemp[index2];
                    index2++;
                }
            }
        }
        printf ("\n");

        /* Set maximum and minimum values to zero if no clear land/water 
           pixels */
        if (f_temp_min == SHRT_MAX)
            f_temp_min = 0;
        if (f_temp_max == SHRT_MIN)
            f_temp_max = 0;
        if (f_wtemp_min == SHRT_MAX)
            f_wtemp_min = 0;
        if (f_wtemp_max == SHRT_MIN)
            f_wtemp_max = 0;

        /* Tempearture for snow test */
        l_pt = 0.175;
        h_pt = 1.0 - l_pt;
        /* 0.175 percentile background temperature (low) */
        status = prctile (f_temp, index, f_temp_min, f_temp_max, 100.0 * l_pt,
                          t_templ);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        /* 0.825 percentile background temperature (high) */
        status = prctile (f_temp, index, f_temp_min, f_temp_max, 100.0 * h_pt,
                          t_temph);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = prctile (f_wtemp, index2, f_wtemp_min, f_wtemp_max,
                          100.0 * h_pt, &t_wtemp);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Temperature test */
        t_buffer = 4 * 100;
        *t_templ -= (float) t_buffer;
        *t_temph += (float) t_buffer;
        temp_l = *t_temph - *t_templ;

        /* Relase f_temp memory */
        free (f_wtemp);
        free (f_temp);
        f_wtemp = NULL;
        f_temp = NULL;

        wfinal_prob = (float **) allocate_2d_array (input->size.l,
                                                    input->size.s,
                                                    sizeof (float));
        final_prob =
            (float **) allocate_2d_array (input->size.l, input->size.s,
                                          sizeof (float));
        if (wfinal_prob == NULL || final_prob == NULL)
        {
            sprintf (errstr, "Allocating prob memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The third pass\n");

        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For each of the image bands */
            for (ib = 0; ib < input->nband; ib++)
            {
                /* Read each input reflective band -- data is read into
                   input->buf[ib] */
                if (!GetInputLine (input, ib, row))
                {
                    sprintf (errstr, "Reading input image data for line %d, "
                             "band %d", row, ib);
                    RETURN_ERROR (errstr, "pcloud", FAILURE);
                }
            }

            /* For the thermal band, data is read into input->therm_buf */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            /* Loop through each line in the image */
            for (col = 0; col < ncols; col++)
            {
                for (ib = 0; ib < BI_REFL_BAND_COUNT - 1; ib++)
                {
                    if (input->buf[ib][col] == input->meta.satu_value_ref[ib])
                        input->buf[ib][col] = input->meta.satu_value_max[ib];
                }
                if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                    input->therm_buf[col] = input->meta.therm_satu_value_max;

                if (pixel_mask[row][col] & (1 << WATER_BIT))
                {
                    /* Get cloud prob over water */
                    /* Temperature test over water */
                    wtemp_prob = (t_wtemp - (float) input->therm_buf[col]) /
                        400.0;
                    if (wtemp_prob < MINSIGMA)
                        wtemp_prob = 0.0;

                    /* Brightness test (over water) */
                    t_bright = 1100;
                    brightness_prob = (float) input->buf[BI_SWIR_1][col] /
                        (float) t_bright;
                    if ((brightness_prob - 1.0) > MINSIGMA)
                        brightness_prob = 1.0;
                    if (brightness_prob < MINSIGMA)
                        brightness_prob = 0.0;

                    /*Final prob mask (water), cloud over water probability */
                    wfinal_prob[row][col] =
                        100.0 * wtemp_prob * brightness_prob;
                    final_prob[row][col] = 0.0;
                }
                else
                {
                    temp_prob =
                        (*t_temph - (float) input->therm_buf[col]) / temp_l;
                    /* Temperature can have prob > 1 */
                    if (temp_prob < MINSIGMA)
                        temp_prob = 0.0;

                    /* label the non-fill pixels
                       Due to a problem with the input LPGS data, the thermal
                       band may have values less than -9999 after scaling so
                       exclude those as well */
                    if (input->therm_buf[col] <= -9999
                        || input->buf[BI_BLUE][col] == -9999
                        || input->buf[BI_GREEN][col] == -9999
                        || input->buf[BI_RED][col] == -9999
                        || input->buf[BI_NIR][col] == -9999
                        || input->buf[BI_SWIR_1][col] == -9999
                        || input->buf[BI_SWIR_2][col] == -9999)
                    {
                        mask = 0;
                    }
                    else
                        mask = 1;

                    if ((input->buf[BI_RED][col]
                         + input->buf[BI_NIR][col]) != 0
                        && mask == 1)
                    {
                        ndvi = (float) (input->buf[BI_NIR][col]
                                        - input->buf[BI_RED][col])
                               / (float) (input->buf[BI_NIR][col]
                                          + input->buf[BI_RED][col]);
                    }
                    else
                        ndvi = 0.01;

                    if ((input->buf[BI_GREEN][col]
                         + input->buf[BI_SWIR_1][col]) != 0
                        && mask == 1)
                    {
                        ndsi = (float) (input->buf[BI_GREEN][col]
                                        - input->buf[BI_SWIR_1][col])
                               / (float) (input->buf[BI_GREEN][col]
                                          + input->buf[BI_SWIR_1][col]);
                    }
                    else
                        ndsi = 0.01;

                    /* NDVI and NDSI should not be negative */
                    if (ndsi < MINSIGMA)
                        ndsi = 0.0;
                    if (ndvi < MINSIGMA)
                        ndvi = 0.0;

                    visi_mean = (input->buf[BI_BLUE][col]
                                 + input->buf[BI_GREEN][col]
                                 + input->buf[BI_RED][col]) / 3.0;
                    if (visi_mean != 0)
                    {
                        whiteness =
                            ((fabs ((float) input->buf[BI_BLUE][col]
                                    - visi_mean)
                              + fabs ((float) input->buf[BI_GREEN][col]
                                      - visi_mean)
                              + fabs ((float) input->buf[BI_RED][col]
                                      - visi_mean))) / visi_mean;
                    }
                    else
                        whiteness = 0.0;

                    /* If one visible band is saturated, whiteness = 0 */
                    if ((input->buf[BI_BLUE][col]
                         >= (input->meta.satu_value_max[BI_BLUE] - 1))
                        ||
                        (input->buf[BI_GREEN][col]
                         >= (input->meta.satu_value_max[BI_GREEN] - 1))
                        ||
                        (input->buf[BI_RED][col]
                         >= (input->meta.satu_value_max[BI_RED] - 1)))
                    {
                        whiteness = 0.0;
                    }

                    /* Vari_prob=1-max(max(abs(NDSI),abs(NDVI)),whiteness); */
                    if ((ndsi - ndvi) > MINSIGMA)
                        max_value = ndsi;
                    else
                        max_value = ndvi;
                    if ((whiteness - max_value) > MINSIGMA)
                        max_value = whiteness;
                    vari_prob = 1.0 - max_value;

                    /*Final prob mask (land) */
                    final_prob[row][col] = 100.0 * (temp_prob * vari_prob);
                    wfinal_prob[row][col] = 0.0;
                }
            }
        }
        printf ("\n");

        /* Allocate memory for prob */
        prob = malloc (input->size.l * input->size.s * sizeof (float));
        if (prob == NULL)
        {
            sprintf (errstr, "Allocating prob memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        float prob_max = 0.0;
        float prob_min = 0.0;
        int index3 = 0;
        for (row = 0; row < nrows; row++)
        {
            for (col = 0; col < ncols; col++)
            {
                if (clear_mask[row][col] & (1 << CLEAR_LAND_BIT))
                {
                    prob[index3] = final_prob[row][col];
                    if ((prob[index3] - prob_max) > MINSIGMA)
                        prob_max = prob[index3];
                    if ((prob_min - prob[index3]) > MINSIGMA)
                        prob_min = prob[index3];
                    index3++;
                }
            }
        }

        /* Dynamic threshold for land */
        if (index3 != 0)
        {
            status = prctile2 (prob, index3, prob_min, prob_max, 100.0 * h_pt,
                               &clr_mask);
            if (status != SUCCESS)
            {
                sprintf (errstr, "Error calling prctile2 routine");
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }
        }
        else
        {
            clr_mask = 27.5; /* no clear land pixel, make clr_mask double of
                                cloud_prob_threshold */
        }
        clr_mask += cloud_prob_threshold;

        /* Relase memory for prob */
        free (prob);
        prob = NULL;

        /* Allocate memory for wprob */
        wprob = malloc (input->size.l * input->size.s * sizeof (float));
        if (wprob == NULL)
        {
            sprintf (errstr, "Allocating wprob memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        float wprob_max = 0.0;
        float wprob_min = 0.0;
        int index4 = 0;
        for (row = 0; row < nrows; row++)
        {
            for (col = 0; col < ncols; col++)
            {
                if (clear_mask[row][col] & (1 << CLEAR_WATER_BIT))
                {
                    wprob[index4] = wfinal_prob[row][col];
                    if ((wprob[index4] - wprob_max) > MINSIGMA)
                        wprob_max = wprob[index4];
                    if ((wprob_min - wprob[index4]) > MINSIGMA)
                        wprob_min = wprob[index4];
                    index4++;
                }
            }
        }

        /* Dynamic threshold for water */
        if (index4 != 0)
        {
            status =
                prctile2 (wprob, index4, wprob_min, wprob_max, 100.0 * h_pt,
                          &wclr_mask);
            if (status != SUCCESS)
            {
                sprintf (errstr, "Error calling prctile2 routine");
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }
        }
        else
        {
            wclr_mask = 27.5; /* no clear water pixel, make wclr_mask 27.5 */
        }
        wclr_mask += cloud_prob_threshold;

        /* Relase memory for wprob */
        free (wprob);
        wprob = NULL;

        if (verbose)
        {
            printf ("pcloud probability threshold (land) = %.2f\n", clr_mask);
            printf ("pcloud probability threshold (water) = %.2f\n",
                    wclr_mask);

            printf ("The fourth pass\n");
        }

        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For the thermal band, data is read into input->therm_buf */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            for (col = 0; col < ncols; col++)
            {
                if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                    input->therm_buf[col] = input->meta.therm_satu_value_max;

                if (((pixel_mask[row][col] & (1 << CLOUD_BIT)) &&
                     final_prob[row][col] > clr_mask &&
                     (!(pixel_mask[row][col] & (1 << WATER_BIT)))) ||
                    ((pixel_mask[row][col] & (1 << CLOUD_BIT)) &&
                     wfinal_prob[row][col] > wclr_mask &&
                     (pixel_mask[row][col] & (1 << WATER_BIT)))
                    || (input->therm_buf[col] < *t_templ + t_buffer - 3500))
                    pixel_mask[row][col] |= 1 << CLOUD_BIT;
                else
                    pixel_mask[row][col] &= ~(1 << CLOUD_BIT);
            }
        }
        printf ("\n");

        /* Free the memory */
        status = free_2d_array ((void **) wfinal_prob);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Freeing memory: wfinal_prob\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = free_2d_array ((void **) final_prob);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Freeing memory: final_prob\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Band 4 &5 flood fill */
        nir = calloc (input->size.l * input->size.s, sizeof (int16));
        swir = calloc (input->size.l * input->size.s, sizeof (int16));
        if (nir == NULL || swir == NULL)
        {
            sprintf (errstr, "Allocating nir and swir memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Open the intermediate file for writing */
        FILE *fd1;
        FILE *fd2;
        fd1 = fopen ("b4.bin", "wb");
        if (fd1 == NULL)
        {
            sprintf (errstr, "Opening file: b4.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        fd2 = fopen ("b5.bin", "wb");
        if (fd2 == NULL)
        {
            sprintf (errstr, "Opening file: b5.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The fifth pass\n");

        int16 nir_max = 0;
        int16 nir_min = 0;
        int16 swir_max = 0;
        int16 swir_min = 0;
        int idx = 0;
        int idx2 = 0;
        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For each of the image bands */
            for (ib = 0; ib < input->nband; ib++)
            {
                /* Read each input reflective band -- data is read into
                   input->buf[ib] */
                if (!GetInputLine (input, ib, row))
                {
                    sprintf (errstr, "Reading input image data for line %d, "
                             "band %d", row, ib);
                    RETURN_ERROR (errstr, "pcloud", FAILURE);
                }
            }

            for (col = 0; col < ncols; col++)
            {
                if (input->buf[BI_NIR][col]
                    == input->meta.satu_value_ref[BI_NIR])
                {
                    input->buf[BI_NIR][col] =
                        input->meta.satu_value_max[BI_NIR];
                }
                if (input->buf[BI_SWIR_1][col]
                    == input->meta.satu_value_ref[BI_SWIR_1])
                {
                    input->buf[BI_SWIR_1][col] =
                        input->meta.satu_value_max[BI_SWIR_1];
                }

                if (clear_mask[row][col] & (1 << CLEAR_LAND_BIT))
                {
                    nir[idx] = input->buf[BI_NIR][col];
                    if (nir[idx] > nir_max)
                        nir_max = nir[idx];
                    if (nir[idx] < nir_min)
                        nir_min = nir[idx];
                    idx++;
                }

                if (clear_mask[row][col] & (1 << CLEAR_LAND_BIT))
                {
                    swir[idx2] = input->buf[BI_SWIR_1][col];
                    if (swir[idx2] > swir_max)
                        swir_max = swir[idx2];
                    if (swir[idx2] < swir_min)
                        swir_min = swir[idx2];
                    idx2++;
                }
            }

            /* Write out the intermediate file */
            status = fwrite (&input->buf[BI_NIR][0], sizeof (int16),
                             input->size.s, fd1);
            if (status != input->size.s)
            {
                sprintf (errstr, "Writing file: b4.bin\n");
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }
            status = fwrite (&input->buf[BI_SWIR_1][0], sizeof (int16),
                             input->size.s, fd2);
            if (status != input->size.s)
            {
                sprintf (errstr, "Writing file: b5.bin\n");
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }
        }
        printf ("\n");

        /* Close the intermediate file */
        status = fclose (fd1);
        if (status)
        {
            sprintf (errstr, "Closing file: b4.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = fclose (fd2);
        if (status)
        {
            sprintf (errstr, "Closing file: b5.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Estimating background (land) Band 4 Ref */
        status =
            prctile (nir, idx + 1, nir_min, nir_max, 100.0 * l_pt, &backg_b4);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Calling prctile function\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status =
            prctile (swir, idx2 + 1, swir_min, swir_max, 100.0 * l_pt,
                     &backg_b5);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Calling prctile function\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Release the memory */
        free (nir);
        free (swir);
        nir = NULL;
        swir = NULL;

        /* Write out the intermediate values */
        fd1 = fopen ("b4_b5.txt", "w");
        if (fd1 == NULL)
        {
            sprintf (errstr, "Opening file: b4_b5.txt\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Write out the intermediate file */
        fprintf (fd1, "%f\n", backg_b4);
        fprintf (fd1, "%f\n", backg_b5);
        fprintf (fd1, "%d\n", input->size.l);
        fprintf (fd1, "%d\n", input->size.s);

        /* Close the intermediate file */
        status = fclose (fd1);
        if (status)
        {
            sprintf (errstr, "Closing file: b4_b5.txt\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Call the fill minima routine to do image fill */
        status = system ("run_fillminima.py");
        if (status != SUCCESS)
        {
            sprintf (errstr, "Running run_fillminima.py routine\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Open the intermediate file for reading */
        fd1 = fopen ("filled_b4.bin", "rb");
        if (fd1 == NULL)
        {
            sprintf (errstr, "Opening file: filled_b4.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        fd2 = fopen ("filled_b5.bin", "rb");
        if (fd2 == NULL)
        {
            sprintf (errstr, "Opening file: filled_b5.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* May need allocate two memory for new band 4 and 5 */
        int16 *new_nir;
        int16 *new_swir;

        new_nir = (int16 *) malloc (input->size.s * sizeof (int16));
        new_swir = (int16 *) malloc (input->size.s * sizeof (int16));
        if (new_nir == NULL || new_swir == NULL)
        {
            sprintf (errstr, "Allocating new_nir/new_swir memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The sixth pass\n");

        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For each of the image bands */
            for (ib = 0; ib < input->nband; ib++)
            {
                /* Read each input reflective band -- data is read into
                   input->buf[ib] */
                if (!GetInputLine (input, ib, row))
                {
                    sprintf (errstr, "Reading input image data for line %d, "
                             "band %d", row, ib);
                    RETURN_ERROR (errstr, "pcloud", FAILURE);
                }
            }

            /* For the thermal band, data is read into input->therm_buf */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            /* Read out the intermediate file */
            fread (&new_nir[0], sizeof (int16), input->size.s, fd1);
            fread (&new_swir[0], sizeof (int16), input->size.s, fd2);

            for (col = 0; col < ncols; col++)
            {
                if (input->buf[BI_NIR][col]
                    == input->meta.satu_value_ref[BI_NIR])
                {
                    input->buf[BI_NIR][col] =
                        input->meta.satu_value_max[BI_NIR];
                }
                if (input->buf[BI_SWIR_1][col]
                    == input->meta.satu_value_ref[BI_SWIR_1])
                {
                    input->buf[BI_SWIR_1][col] =
                        input->meta.satu_value_max[BI_SWIR_1];
                }

                /* process non-fill pixels only
                   Due to a problem with the input LPGS data, the thermal
                   band may have values less than -9999 after scaling so
                   exclude those as well */
                if (input->therm_buf[col] <= -9999
                    || input->buf[BI_BLUE][col] == -9999
                    || input->buf[BI_GREEN][col] == -9999
                    || input->buf[BI_RED][col] == -9999
                    || input->buf[BI_NIR][col] == -9999
                    || input->buf[BI_SWIR_1][col] == -9999
                    || input->buf[BI_SWIR_2][col] == -9999)
                {
                    mask = 0;
                }
                else
                    mask = 1;

                if (mask == 1)
                {
                    new_nir[col] -= input->buf[BI_NIR][col];
                    new_swir[col] -= input->buf[BI_SWIR_1][col];

                    if (new_nir[col] < new_swir[col])
                        shadow_prob = new_nir[col];
                    else
                        shadow_prob = new_swir[col];

                    if (shadow_prob > 200)
                        pixel_mask[row][col] |= 1 << SHADOW_BIT;
                    else
                        pixel_mask[row][col] &= ~(1 << SHADOW_BIT);
                }
                else
                {
                    pixel_mask[row][col] |= 1 << FILL_BIT;
                    pixel_mask[row][col] &= ~(1 << CLOUD_BIT);
                    pixel_mask[row][col] &= ~(1 << SHADOW_BIT);
                    pixel_mask[row][col] &= ~(1 << WATER_BIT);
                    pixel_mask[row][col] &= ~(1 << SNOW_BIT);
                }

                /* refine Water mask (no confusion water/cloud) */
                if ((pixel_mask[row][col] & (1 << WATER_BIT)) &&
                    (pixel_mask[row][col] & (1 << CLOUD_BIT)))
                    pixel_mask[row][col] &= ~(1 << WATER_BIT);
            }
        }
        printf ("\n");

        /* Release the memory */
        free (new_nir);
        free (new_swir);
        new_nir = NULL;
        new_swir = NULL;

        /* Close the intermediate file */
        status = fclose (fd1);
        if (status)
        {
            sprintf (errstr, "Closing file: filled_b4.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = fclose (fd2);
        if (status)
        {
            sprintf (errstr, "Closing file: filled_b5.bin\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Remove the intermediate files */
        status = system ("rm b4_b5.txt");
        if (status != SUCCESS)
        {
            sprintf (errstr, "Removing b4_b5.txt file\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = system ("rm b4.bin");
        if (status != SUCCESS)
        {
            sprintf (errstr, "Removing b4.bin file\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = system ("rm b5.bin");
        if (status != SUCCESS)
        {
            sprintf (errstr, "Removing b5.bin file\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = system ("rm filled_b4.bin");
        if (status != SUCCESS)
        {
            sprintf (errstr, "Removing filled_b4.bin file\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = system ("rm filled_b5.bin");
        if (status != SUCCESS)
        {
            sprintf (errstr, "Removing filled_b5.bin file\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
    }

    status = free_2d_array ((void **) clear_mask);
    if (status != SUCCESS)
    {
        sprintf (errstr, "Freeing memory: clear_mask\n");
        RETURN_ERROR (errstr, "pcloud", FAILURE);
    }

    return SUCCESS;
}
Esempio n. 14
0
File: pragma.c Progetto: pmprog/cc65
static void MakeMessage (const char* Message)
{
    fprintf (stderr, "%s(%u): Note: %s\n", GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Message);
}
/*****************************************************************************
MODULE:  potential_cloud_shadow_snow_mask

PURPOSE: Identify the cloud pixels, snow pixels, water pixels, clear land
         pixels, and potential shadow pixels

RETURN: SUCCESS
        FAILURE

HISTORY:
Date        Programmer       Reason
--------    ---------------  -------------------------------------
3/15/2013   Song Guo         Original Development

NOTES:
1. Thermal buffer is expected to be in degrees Celsius with a factor applied
   of 100.  Many values which compare to the thermal buffer in this code are
   hardcoded and assume degrees celsius * 100.
*****************************************************************************/
int potential_cloud_shadow_snow_mask
(
    Input_t * input,            /*I: input structure */
    float cloud_prob_threshold, /*I: cloud probability threshold */
    float *clear_ptm,           /*O: percent of clear-sky pixels */
    float *t_templ,             /*O: percentile of low background temp */
    float *t_temph,             /*O: percentile of high background temp */
    unsigned char *pixel_mask,  /*I/O: pixel mask */
    unsigned char *conf_mask,   /*I/O: confidence mask */
    bool verbose                /*I: value to indicate if intermediate
                                     messages should be printed */
)
{
    char errstr[MAX_STR_LEN];   /* error string */
    int nrows = input->size.l;  /* number of rows */
    int ncols = input->size.s;  /* number of columns */
    int ib = 0;                 /* band index */
    int row = 0;                /* row index */
    int col = 0;                /* column index */
    int image_data_counter = 0;        /* mask counter */
    int clear_pixel_counter = 0;       /* clear sky pixel counter */
    int clear_land_pixel_counter = 0;  /* clear land pixel counter */
    int clear_water_pixel_counter = 0; /* clear water pixel counter */
    float ndvi, ndsi;           /* NDVI and NDSI values */
    int16 *f_temp = NULL;       /* clear land temperature */
    int16 *f_wtemp = NULL;      /* clear water temperature */
    float visi_mean;            /* mean of visible bands */
    float whiteness = 0.0;      /* whiteness value */
    float hot;                  /* hot value for hot test */
    float land_ptm;             /* clear land pixel percentage */
    float water_ptm;            /* clear water pixel percentage */
    unsigned char land_bit;     /* Which clear bit to test all or just land */
    unsigned char water_bit;    /* Which clear bit to test all or just water */
    float l_pt;                 /* low percentile threshold */
    float h_pt;                 /* high percentile threshold */
    float t_wtemp;              /* high percentile water temperature */
    float *wfinal_prob = NULL;  /* final water pixel probabilty value */
    float *final_prob = NULL;   /* final land pixel probability value */
    float wtemp_prob;           /* water temperature probability value */
    int t_bright;               /* brightness test value for water */
    float brightness_prob;      /* brightness probability value */
    int t_buffer;               /* temperature test buffer */
    float temp_l;               /* difference of low/high tempearture
                                   percentiles */
    float temp_prob;            /* temperature probability */
    float vari_prob;            /* probability from NDVI, NDSI, and whiteness */
    float max_value;            /* maximum value */
    float *prob = NULL;         /* probability value */
    float *wprob = NULL;        /* probability value */
    float clr_mask = 0.0;       /* clear sky pixel threshold */
    float wclr_mask = 0.0;      /* water pixel threshold */
    int data_size;              /* Data size for memory allocation */
    int16 *nir = NULL;          /* near infrared band data */
    int16 *swir1 = NULL;        /* short wavelength infrared band data */
    int16 *nir_data = NULL;          /* Data to be filled */
    int16 *swir1_data = NULL;        /* Data to be filled */
    int16 *filled_nir_data = NULL;   /* Filled result */
    int16 *filled_swir1_data = NULL; /* Filled result */
    float nir_boundary;         /* NIR boundary value / background value */
    float swir1_boundary;       /* SWIR1 boundary value / background value */
    int16 shadow_prob;          /* shadow probability */
    int status;                 /* return value */
    int satu_bv;                /* sum of saturated bands 1, 2, 3 value */

    int pixel_index;
    int pixel_count;

    pixel_count = nrows * ncols;

    /* Dynamic memory allocation */
    unsigned char *clear_mask = NULL;

    clear_mask = calloc (pixel_count, sizeof (unsigned char));
    if (clear_mask == NULL)
    {
        RETURN_ERROR ("Allocating mask memory", "pcloud", FAILURE);
    }

    if (verbose)
        printf ("The first pass\n");

    /* Loop through each line in the image */
    for (row = 0; row < nrows; row++)
    {
        if (verbose)
        {
            /* Print status on every 1000 lines */
            if (!(row % 1000))
            {
                printf ("Processing line %d\r", row);
                fflush (stdout);
            }
        }

        /* For each of the image bands */
        for (ib = 0; ib < input->nband; ib++)
        {
            /* Read each input reflective band -- data is read into
               input->buf[ib] */
            if (!GetInputLine (input, ib, row))
            {
                sprintf (errstr, "Reading input image data for line %d, "
                         "band %d", row, ib);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }
        }

        /* For the thermal band */
        /* Read the input thermal band -- data is read into input->therm_buf */
        if (!GetInputThermLine (input, row))
        {
            sprintf (errstr, "Reading input thermal data for line %d", row);
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        for (col = 0; col < ncols; col++)
        {
            pixel_index = row * ncols + col;

            int ib;
            for (ib = 0; ib < BI_REFL_BAND_COUNT; ib++)
            {
                if (input->buf[ib][col] == input->meta.satu_value_ref[ib])
                    input->buf[ib][col] = input->meta.satu_value_max[ib];
            }
            if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                input->therm_buf[col] = input->meta.therm_satu_value_max;

            /* process non-fill pixels only
               Due to a problem with the input LPGS data, the thermal band
               may have values less than FILL_PIXEL after scaling so exclude
               those as well */
            if (input->therm_buf[col] <= FILL_PIXEL
                || input->buf[BI_BLUE][col] == FILL_PIXEL
                || input->buf[BI_GREEN][col] == FILL_PIXEL
                || input->buf[BI_RED][col] == FILL_PIXEL
                || input->buf[BI_NIR][col] == FILL_PIXEL
                || input->buf[BI_SWIR_1][col] == FILL_PIXEL
                || input->buf[BI_SWIR_2][col] == FILL_PIXEL)
            {
                pixel_mask[pixel_index] = CF_FILL_BIT;
                clear_mask[pixel_index] = CF_CLEAR_FILL_BIT;
                continue;
            }
            image_data_counter++;

            if ((input->buf[BI_RED][col] + input->buf[BI_NIR][col]) != 0)
            {
                ndvi = (float) (input->buf[BI_NIR][col]
                                - input->buf[BI_RED][col])
                       / (float) (input->buf[BI_NIR][col]
                                  + input->buf[BI_RED][col]);
            }
            else
                ndvi = 0.01;

            if ((input->buf[BI_GREEN][col] + input->buf[BI_SWIR_1][col]) != 0)
            {
                ndsi = (float) (input->buf[BI_GREEN][col]
                                - input->buf[BI_SWIR_1][col])
                       / (float) (input->buf[BI_GREEN][col]
                                  + input->buf[BI_SWIR_1][col]);
            }
            else
                ndsi = 0.01;

            /* Basic cloud test, equation 1 */
            if (((ndsi - 0.8) < MINSIGMA)
                && ((ndvi - 0.8) < MINSIGMA)
                && (input->buf[BI_SWIR_2][col] > 300)
                && (input->therm_buf[col] < 2700))
            {
                pixel_mask[pixel_index] |= CF_CLOUD_BIT;
            }
            else
                pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;

            /* It takes every snow pixel including snow pixels under thin
               or icy clouds, equation 20 */
            if (((ndsi - 0.15) > MINSIGMA)
                && (input->therm_buf[col] < 1000)
                && (input->buf[BI_NIR][col] > 1100)
                && (input->buf[BI_GREEN][col] > 1000))
            {
                pixel_mask[pixel_index] |= CF_SNOW_BIT;
            }
            else
                pixel_mask[pixel_index] &= ~CF_SNOW_BIT;

            /* Zhe's water test (works over thin cloud), equation 5 */
            if ((((ndvi - 0.01) < MINSIGMA)
                  && (input->buf[BI_NIR][col] < 1100))
                || (((ndvi - 0.1) < MINSIGMA)
                    && (ndvi > MINSIGMA)
                    && (input->buf[BI_NIR][col] < 500)))
            {
                pixel_mask[pixel_index] |= CF_WATER_BIT;
            }
            else
                pixel_mask[pixel_index] &= ~CF_WATER_BIT;

            /* visible bands flatness (sum(abs)/mean < 0.6 => bright and dark
               cloud), equation 2 */
            if (pixel_mask[pixel_index] & CF_CLOUD_BIT)
            {
                visi_mean = (float) (input->buf[BI_BLUE][col]
                                     + input->buf[BI_GREEN][col]
                                     + input->buf[BI_RED][col]) / 3.0;
                if (visi_mean != 0)
                {
                    whiteness =
                        ((fabs ((float) input->buf[BI_BLUE][col] - visi_mean)
                          + fabs ((float) input->buf[BI_GREEN][col] - visi_mean)
                          + fabs ((float) input->buf[BI_RED][col]
                                  - visi_mean))) / visi_mean;
                }
                else
                {
                    /* Just put a large value to remove them from cloud pixel
                       identification */
                    whiteness = 100.0;
                }
            }

            /* Update cloud_mask,  if one visible band is saturated,
               whiteness = 0, due to data type conversion, pixel value
               difference of 1 is possible */
            if ((input->buf[BI_BLUE][col]
                 >= (input->meta.satu_value_max[BI_BLUE] - 1))
                ||
                (input->buf[BI_GREEN][col]
                 >= (input->meta.satu_value_max[BI_GREEN] - 1))
                ||
                (input->buf[BI_RED][col]
                 >= (input->meta.satu_value_max[BI_RED] - 1)))
            {
                whiteness = 0.0;
                satu_bv = 1;
            }
            else
            {
                satu_bv = 0;
            }

            if ((pixel_mask[pixel_index] & CF_CLOUD_BIT) &&
                (whiteness - 0.7) < MINSIGMA)
            {
                pixel_mask[pixel_index] |= CF_CLOUD_BIT;
            }
            else
                pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;

            /* Haze test, equation 3 */
            hot = (float) input->buf[BI_BLUE][col]
                  - 0.5 * (float) input->buf[BI_RED][col]
                  - 800.0;
            if ((pixel_mask[pixel_index] & CF_CLOUD_BIT)
                && (hot > MINSIGMA || satu_bv == 1))
                pixel_mask[pixel_index] |= CF_CLOUD_BIT;
            else
                pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;

            /* Ratio 4/5 > 0.75 test, equation 4 */
            if ((pixel_mask[pixel_index] & CF_CLOUD_BIT) &&
                input->buf[BI_SWIR_1][col] != 0)
            {
                if ((float) input->buf[BI_NIR][col] /
                    (float) input->buf[BI_SWIR_1][col] - 0.75 > MINSIGMA)
                    pixel_mask[pixel_index] |= CF_CLOUD_BIT;
                else
                    pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;
            }
            else
                pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;

            /* Build counters for clear, clear land, and clear water */
            if (pixel_mask[pixel_index] & CF_CLOUD_BIT)
            {
                /* It is cloud so make sure none of the bits are set */
                clear_mask[pixel_index] = CF_CLEAR_NONE;
            }
            else
            {
                clear_mask[pixel_index] = CF_CLEAR_BIT;
                clear_pixel_counter++;

                if (pixel_mask[pixel_index] & CF_WATER_BIT)
                {
                    /* Add the clear water bit */
                    clear_mask[pixel_index] |= CF_CLEAR_WATER_BIT;
                    clear_water_pixel_counter++;
                }
                else
                {
                    /* Add the clear land bit */
                    clear_mask[pixel_index] |= CF_CLEAR_LAND_BIT;
                    clear_land_pixel_counter++;
                }
            }
        }
    }
    printf ("\n");

    *clear_ptm = 100.0 * ((float) clear_pixel_counter
                          / (float) image_data_counter);
    land_ptm = 100.0 * ((float) clear_land_pixel_counter
                        / (float) image_data_counter);
    water_ptm = 100.0 * ((float) clear_water_pixel_counter
                         / (float) image_data_counter);

    if (verbose)
    {
        printf ("(clear_pixels, clear_land_pixels, clear_water_pixels,"
                " image_data_counter) = (%d, %d, %d, %d)\n",
                clear_pixel_counter, clear_land_pixel_counter,
                clear_water_pixel_counter, image_data_counter);
        printf ("(clear_ptm, land_ptm, water_ptm) = (%f, %f, %f)\n",
                *clear_ptm, land_ptm, water_ptm);
    }

    if ((*clear_ptm - 0.1) <= MINSIGMA)
    {
        /* No thermal test is needed, all clouds */
        *t_templ = -1.0;
        *t_temph = -1.0;
        for (pixel_index = 0; pixel_index < pixel_count; pixel_index++)
        {
            /* All cloud */
            if (!(pixel_mask[pixel_index] & CF_CLOUD_BIT))
                pixel_mask[pixel_index] |= CF_SHADOW_BIT;
            else
                pixel_mask[pixel_index] &= ~CF_SHADOW_BIT;
        }
    }
    else
    {
        f_temp = calloc (pixel_count, sizeof (int16));
        f_wtemp = calloc (pixel_count, sizeof (int16));
        if (f_temp == NULL || f_wtemp == NULL)
        {
            sprintf (errstr, "Allocating temp memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The second pass\n");

        /* Determine which bit to test for land */
        if ((land_ptm - 0.1) >= MINSIGMA)
        {
            /* use clear land only */
            land_bit = CF_CLEAR_LAND_BIT;
        }
        else
        {
            /* not enough clear land so use all clear pixels */
            land_bit = CF_CLEAR_BIT;
        }

        /* Determine which bit to test for water */
        if ((water_ptm - 0.1) >= MINSIGMA)
        {
            /* use clear water only */
            water_bit = CF_CLEAR_WATER_BIT;
        }
        else
        {
            /* not enough clear water so use all clear pixels */
            water_bit = CF_CLEAR_BIT;
        }

        int16 f_temp_max = SHRT_MIN;
        int16 f_temp_min = SHRT_MAX;
        int16 f_wtemp_max = SHRT_MIN;
        int16 f_wtemp_min = SHRT_MAX;
        int land_count = 0;
        int water_count = 0;
        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For the thermal band, read the input thermal band  */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            for (col = 0; col < ncols; col++)
            {
                pixel_index = row * ncols + col;

                if (clear_mask[pixel_index] & CF_CLEAR_FILL_BIT)
                    continue;

                if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                    input->therm_buf[col] = input->meta.therm_satu_value_max;

                /* get clear land temperature */
                if (clear_mask[pixel_index] & land_bit)
                {
                    f_temp[land_count] = input->therm_buf[col];
                    if (f_temp_max < f_temp[land_count])
                        f_temp_max = f_temp[land_count];
                    if (f_temp_min > f_temp[land_count])
                        f_temp_min = f_temp[land_count];
                    land_count++;
                }

                /* get clear water temperature */
                if (clear_mask[pixel_index] & water_bit)
                {
                    f_wtemp[water_count] = input->therm_buf[col];
                    if (f_wtemp_max < f_wtemp[water_count])
                        f_wtemp_max = f_wtemp[water_count];
                    if (f_wtemp_min > f_wtemp[water_count])
                        f_wtemp_min = f_wtemp[water_count];
                    water_count++;
                }
            }
        }
        printf ("\n");

        /* Set maximum and minimum values to zero if no clear land/water
           pixels */
        if (f_temp_min == SHRT_MAX)
            f_temp_min = 0;
        if (f_temp_max == SHRT_MIN)
            f_temp_max = 0;
        if (f_wtemp_min == SHRT_MAX)
            f_wtemp_min = 0;
        if (f_wtemp_max == SHRT_MIN)
            f_wtemp_max = 0;

        /* Tempearture for snow test */
        l_pt = 0.175;
        h_pt = 1.0 - l_pt;

        /* 0.175 percentile background temperature (low) */
        status = prctile (f_temp, land_count, f_temp_min, f_temp_max,
                          100.0 * l_pt, t_templ);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* 0.825 percentile background temperature (high) */
        status = prctile (f_temp, land_count, f_temp_min, f_temp_max,
                          100.0 * h_pt, t_temph);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        status = prctile (f_wtemp, water_count, f_wtemp_min, f_wtemp_max,
                          100.0 * h_pt, &t_wtemp);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Temperature test */
        t_buffer = 4 * 100;
        *t_templ -= (float) t_buffer;
        *t_temph += (float) t_buffer;
        temp_l = *t_temph - *t_templ;

        /* Release f_temp memory */
        free (f_wtemp);
        f_wtemp = NULL;
        free (f_temp);
        f_temp = NULL;

        wfinal_prob = calloc (pixel_count, sizeof (float));
        final_prob = calloc (pixel_count, sizeof (float));
        if (wfinal_prob == NULL || final_prob == NULL)
        {
            sprintf (errstr, "Allocating prob memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The third pass\n");

        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For each of the image bands */
            for (ib = 0; ib < input->nband; ib++)
            {
                /* Read each input reflective band -- data is read into
                   input->buf[ib] */
                if (!GetInputLine (input, ib, row))
                {
                    sprintf (errstr, "Reading input image data for line %d, "
                             "band %d", row, ib);
                    RETURN_ERROR (errstr, "pcloud", FAILURE);
                }
            }

            /* For the thermal band, data is read into input->therm_buf */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            /* Loop through each sample in the image */
            for (col = 0; col < ncols; col++)
            {
                pixel_index = row * ncols + col;

                if (pixel_mask[pixel_index] & CF_FILL_BIT)
                    continue;

                for (ib = 0; ib < BI_REFL_BAND_COUNT - 1; ib++)
                {
                    if (input->buf[ib][col] == input->meta.satu_value_ref[ib])
                        input->buf[ib][col] = input->meta.satu_value_max[ib];
                }
                if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                    input->therm_buf[col] = input->meta.therm_satu_value_max;

                if (pixel_mask[pixel_index] & CF_WATER_BIT)
                {
                    /* Get cloud prob over water */
                    /* Temperature test over water */
                    wtemp_prob = (t_wtemp - (float) input->therm_buf[col]) /
                        400.0;
                    if (wtemp_prob < MINSIGMA)
                        wtemp_prob = 0.0;

                    /* Brightness test (over water) */
                    t_bright = 1100;
                    brightness_prob = (float) input->buf[BI_SWIR_1][col] /
                        (float) t_bright;
                    if ((brightness_prob - 1.0) > MINSIGMA)
                        brightness_prob = 1.0;
                    if (brightness_prob < MINSIGMA)
                        brightness_prob = 0.0;

                    /*Final prob mask (water), cloud over water probability */
                    wfinal_prob[pixel_index] =
                        100.0 * wtemp_prob * brightness_prob;
                    final_prob[pixel_index] = 0.0;
                }
                else
                {
                    temp_prob =
                        (*t_temph - (float) input->therm_buf[col]) / temp_l;
                    /* Temperature can have prob > 1 */
                    if (temp_prob < MINSIGMA)
                        temp_prob = 0.0;

                    if ((input->buf[BI_RED][col] + input->buf[BI_NIR][col]) != 0)
                    {
                        ndvi = (float) (input->buf[BI_NIR][col]
                                        - input->buf[BI_RED][col])
                               / (float) (input->buf[BI_NIR][col]
                                          + input->buf[BI_RED][col]);
                    }
                    else
                        ndvi = 0.01;

                    if ((input->buf[BI_GREEN][col]
                         + input->buf[BI_SWIR_1][col]) != 0)
                    {
                        ndsi = (float) (input->buf[BI_GREEN][col]
                                        - input->buf[BI_SWIR_1][col])
                               / (float) (input->buf[BI_GREEN][col]
                                          + input->buf[BI_SWIR_1][col]);
                    }
                    else
                        ndsi = 0.01;

                    /* NDVI and NDSI should not be negative */
                    if (ndsi < MINSIGMA)
                        ndsi = 0.0;
                    if (ndvi < MINSIGMA)
                        ndvi = 0.0;

                    visi_mean = (input->buf[BI_BLUE][col]
                                 + input->buf[BI_GREEN][col]
                                 + input->buf[BI_RED][col]) / 3.0;
                    if (visi_mean != 0)
                    {
                        whiteness =
                            ((fabs ((float) input->buf[BI_BLUE][col]
                                    - visi_mean)
                              + fabs ((float) input->buf[BI_GREEN][col]
                                      - visi_mean)
                              + fabs ((float) input->buf[BI_RED][col]
                                      - visi_mean))) / visi_mean;
                    }
                    else
                        whiteness = 0.0;

                    /* If one visible band is saturated, whiteness = 0 */
                    if ((input->buf[BI_BLUE][col]
                         >= (input->meta.satu_value_max[BI_BLUE] - 1))
                        ||
                        (input->buf[BI_GREEN][col]
                         >= (input->meta.satu_value_max[BI_GREEN] - 1))
                        ||
                        (input->buf[BI_RED][col]
                         >= (input->meta.satu_value_max[BI_RED] - 1)))
                    {
                        whiteness = 0.0;
                    }

                    /* Vari_prob=1-max(max(abs(NDSI),abs(NDVI)),whiteness); */
                    if ((ndsi - ndvi) > MINSIGMA)
                        max_value = ndsi;
                    else
                        max_value = ndvi;
                    if ((whiteness - max_value) > MINSIGMA)
                        max_value = whiteness;
                    vari_prob = 1.0 - max_value;

                    /*Final prob mask (land) */
                    final_prob[pixel_index] = 100.0 * (temp_prob * vari_prob);
                    wfinal_prob[pixel_index] = 0.0;
                }
            }
        }
        printf ("\n");

        /* Allocate memory for prob */
        prob = malloc (pixel_count * sizeof (float));
        if (prob == NULL)
        {
            sprintf (errstr, "Allocating prob memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        float prob_max = 0.0;
        float prob_min = 0.0;
        land_count = 0;
        for (pixel_index = 0; pixel_index < pixel_count; pixel_index++)
        {
            if (clear_mask[pixel_index] & CF_CLEAR_FILL_BIT)
                continue;

            if (clear_mask[pixel_index] & land_bit)
            {
                prob[land_count] = final_prob[pixel_index];

                if ((prob[land_count] - prob_max) > MINSIGMA)
                    prob_max = prob[land_count];

                if ((prob_min - prob[land_count]) > MINSIGMA)
                    prob_min = prob[land_count];

                land_count++;
            }
        }

        /* Dynamic threshold for land */
        status = prctile2 (prob, land_count, prob_min, prob_max,
                           100.0 * h_pt, &clr_mask);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile2 routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        clr_mask += cloud_prob_threshold;

        /* Release memory for prob */
        free (prob);
        prob = NULL;

        /* Allocate memory for wprob */
        wprob = malloc (pixel_count * sizeof (float));
        if (wprob == NULL)
        {
            sprintf (errstr, "Allocating wprob memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        float wprob_max = 0.0;
        float wprob_min = 0.0;
        water_count = 0;
        for (pixel_index = 0; pixel_index < pixel_count; pixel_index++)
        {
            if (clear_mask[pixel_index] & CF_CLEAR_FILL_BIT)
                continue;

            if (clear_mask[pixel_index] & water_bit)
            {
                wprob[water_count] = wfinal_prob[pixel_index];

                if ((wprob[water_count] - wprob_max) > MINSIGMA)
                    wprob_max = wprob[water_count];

                if ((wprob_min - wprob[water_count]) > MINSIGMA)
                    wprob_min = wprob[water_count];

                water_count++;
            }
        }

        /* Dynamic threshold for water */
        status = prctile2 (wprob, water_count, wprob_min, wprob_max,
                           100.0 * h_pt, &wclr_mask);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Error calling prctile2 routine");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        wclr_mask += cloud_prob_threshold;

        /* Release memory for wprob */
        free (wprob);
        wprob = NULL;

        if (verbose)
        {
            printf ("pcloud probability threshold (land) = %.2f\n", clr_mask);
            printf ("pcloud probability threshold (water) = %.2f\n",
                    wclr_mask);

            printf ("The fourth pass\n");
        }

        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For the thermal band, data is read into input->therm_buf */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            for (col = 0; col < ncols; col++)
            {
                pixel_index = row * ncols + col;

                if (pixel_mask[pixel_index] & CF_FILL_BIT)
                    continue;

                if (input->therm_buf[col] == input->meta.therm_satu_value_ref)
                {
                    input->therm_buf[col] = input->meta.therm_satu_value_max;
                }

                if (((pixel_mask[pixel_index] & CF_CLOUD_BIT)
                     &&
                     (final_prob[pixel_index] > clr_mask)
                     &&
                     (!(pixel_mask[pixel_index] & CF_WATER_BIT)))
                    ||
                    ((pixel_mask[pixel_index] & CF_CLOUD_BIT)
                     &&
                     (wfinal_prob[pixel_index] > wclr_mask)
                     &&
                     (pixel_mask[pixel_index] & CF_WATER_BIT))
                    ||
                    (input->therm_buf[col] < *t_templ + t_buffer - 3500))
                {
                    /* This test indicates a high confidence */
                    conf_mask[pixel_index] = CLOUD_CONFIDENCE_HIGH;

                    /* Original code was only this if test and setting the
                       cloud bit or not */
                    pixel_mask[pixel_index] |= CF_CLOUD_BIT;
                }
                else if (((pixel_mask[pixel_index] & CF_CLOUD_BIT)
                          &&
                          (final_prob[pixel_index] > clr_mask-10.0)
                          &&
                          (!(pixel_mask[pixel_index] & CF_WATER_BIT)))
                         ||
                         ((pixel_mask[pixel_index] & CF_CLOUD_BIT)
                          &&
                          (wfinal_prob[pixel_index] > wclr_mask-10.0)
                          &&
                          (pixel_mask[pixel_index] & CF_WATER_BIT)))
                {
                    /* This test indicates a medium confidence */
                    conf_mask[pixel_index] = CLOUD_CONFIDENCE_MED;

                    /* Don't set the cloud bit per the original code */
                    pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;
                }
                else
                {
                    /* All remaining are a low confidence */
                    conf_mask[pixel_index] = CLOUD_CONFIDENCE_LOW;

                    /* Don't set the cloud bit per the original code */
                    pixel_mask[pixel_index] &= ~CF_CLOUD_BIT;
                }
            }
        }
        printf ("\n");

        /* Free the memory */
        free (wfinal_prob);
        wfinal_prob = NULL;
        free (final_prob);
        final_prob = NULL;

        /* Band NIR & SWIR1 flood fill section */
        data_size = input->size.l * input->size.s;
        nir = calloc (data_size, sizeof (int16));
        swir1 = calloc (data_size, sizeof (int16));
        if (nir == NULL || swir1 == NULL)
        {
            sprintf (errstr, "Allocating nir and swir1 memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The fifth pass\n");

        nir_data = calloc (data_size, sizeof (int16));
        swir1_data = calloc (data_size, sizeof (int16));
        filled_nir_data = calloc (data_size, sizeof (int16));
        filled_swir1_data = calloc (data_size, sizeof (int16));
        if (nir_data == NULL || swir1_data == NULL ||
            filled_nir_data == NULL || filled_swir1_data == NULL)
        {
            sprintf (errstr, "Allocating nir and swir1 memory");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        int16 nir_max = 0;
        int16 nir_min = 0;
        int16 swir1_max = 0;
        int16 swir1_min = 0;
        int nir_count = 0;
        int swir1_count = 0;
        /* Loop through each line in the image */
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For each of the image bands */
            for (ib = 0; ib < input->nband; ib++)
            {
                /* Read each input reflective band -- data is read into
                   input->buf[ib] */
                if (!GetInputLine (input, ib, row))
                {
                    sprintf (errstr, "Reading input image data for line %d, "
                             "band %d", row, ib);
                    RETURN_ERROR (errstr, "pcloud", FAILURE);
                }
            }

            for (col = 0; col < ncols; col++)
            {
                pixel_index = row * ncols + col;

                if (clear_mask[pixel_index] & CF_CLEAR_FILL_BIT)
                    continue;

                if (input->buf[BI_NIR][col]
                    == input->meta.satu_value_ref[BI_NIR])
                {
                    input->buf[BI_NIR][col] =
                        input->meta.satu_value_max[BI_NIR];
                }
                if (input->buf[BI_SWIR_1][col]
                    == input->meta.satu_value_ref[BI_SWIR_1])
                {
                    input->buf[BI_SWIR_1][col] =
                        input->meta.satu_value_max[BI_SWIR_1];
                }

                if (clear_mask[pixel_index] & land_bit)
                {
                    nir[nir_count] = input->buf[BI_NIR][col];
                    if (nir[nir_count] > nir_max)
                        nir_max = nir[nir_count];
                    if (nir[nir_count] < nir_min)
                        nir_min = nir[nir_count];
                    nir_count++;

                    swir1[swir1_count] = input->buf[BI_SWIR_1][col];
                    if (swir1[swir1_count] > swir1_max)
                        swir1_max = swir1[swir1_count];
                    if (swir1[swir1_count] < swir1_min)
                        swir1_min = swir1[swir1_count];
                    swir1_count++;
                }
            }

            /* NIR */
            memcpy(&nir_data[row * input->size.s], &input->buf[BI_NIR][0],
                   input->size.s * sizeof (int16));
            /* SWIR1 */
            memcpy(&swir1_data[row * input->size.s], &input->buf[BI_SWIR_1][0],
                   input->size.s * sizeof (int16));
        }
        printf ("\n");

        /* Estimating background (land) Band NIR Ref */
        status = prctile (nir, nir_count, nir_min, nir_max,
                          100.0 * l_pt, &nir_boundary);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Calling prctile function\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }
        status = prctile (swir1, swir1_count, swir1_min, swir1_max,
                          100.0 * l_pt, &swir1_boundary);
        if (status != SUCCESS)
        {
            sprintf (errstr, "Calling prctile function\n");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        /* Release the memory */
        free (nir);
        free (swir1);
        nir = NULL;
        swir1 = NULL;

        /* Call the fill minima routine to do image fill */
/* Perform them in parallel if threading is enabled */
#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
    {
        if (fill_local_minima_in_image("NIR Band", nir_data,
                                       input->size.l, input->size.s,
                                       nir_boundary, filled_nir_data)
            != SUCCESS)
        {
            printf ("Error Running fill_local_minima_in_image on NIR band");
            status = ERROR;
        }
    }

#ifdef _OPENMP
    #pragma omp section
#endif
    {
        if (fill_local_minima_in_image("SWIR1 Band", swir1_data,
                                       input->size.l, input->size.s,
                                       swir1_boundary, filled_swir1_data)
            != SUCCESS)
        {
            printf ("Error Running fill_local_minima_in_image on SWIR1 band");
            status = ERROR;
        }
    }
}

        /* Release the memory */
        free(nir_data);
        free(swir1_data);
        nir_data = NULL;
        swir1_data = NULL;

        if (status == ERROR)
        {
            free(filled_nir_data);
            free(filled_swir1_data);
            sprintf (errstr, "Running fill_local_minima_in_image");
            RETURN_ERROR (errstr, "pcloud", FAILURE);
        }

        if (verbose)
            printf ("The sixth pass\n");

        int16 new_nir;
        int16 new_swir1;
        for (row = 0; row < nrows; row++)
        {
            if (verbose)
            {
                /* Print status on every 1000 lines */
                if (!(row % 1000))
                {
                    printf ("Processing line %d\r", row);
                    fflush (stdout);
                }
            }

            /* For each of the image bands */
            for (ib = 0; ib < input->nband; ib++)
            {
                /* Read each input reflective band -- data is read into
                   input->buf[ib] */
                if (!GetInputLine (input, ib, row))
                {
                    sprintf (errstr, "Reading input image data for line %d, "
                             "band %d", row, ib);
                    RETURN_ERROR (errstr, "pcloud", FAILURE);
                }
            }

            /* For the thermal band, data is read into input->therm_buf */
            if (!GetInputThermLine (input, row))
            {
                sprintf (errstr, "Reading input thermal data for line %d",
                         row);
                RETURN_ERROR (errstr, "pcloud", FAILURE);
            }

            for (col = 0; col < ncols; col++)
            {
                pixel_index = row * ncols + col;

                if (input->buf[BI_NIR][col]
                    == input->meta.satu_value_ref[BI_NIR])
                {
                    input->buf[BI_NIR][col] =
                        input->meta.satu_value_max[BI_NIR];
                }
                if (input->buf[BI_SWIR_1][col]
                    == input->meta.satu_value_ref[BI_SWIR_1])
                {
                    input->buf[BI_SWIR_1][col] =
                        input->meta.satu_value_max[BI_SWIR_1];
                }

                if (pixel_mask[pixel_index] & CF_FILL_BIT)
                {
                    conf_mask[pixel_index] = CF_FILL_PIXEL;
                    continue;
                }

                new_nir = filled_nir_data[pixel_index] -
                          input->buf[BI_NIR][col];
                new_swir1 = filled_swir1_data[pixel_index] -
                            input->buf[BI_SWIR_1][col];

                if (new_nir < new_swir1)
                    shadow_prob = new_nir;
                else
                    shadow_prob = new_swir1;

                if (shadow_prob > 200)
                    pixel_mask[pixel_index] |= CF_SHADOW_BIT;
                else
                    pixel_mask[pixel_index] &= ~CF_SHADOW_BIT;

                /* refine Water mask (no confusion water/cloud) */
                if ((pixel_mask[pixel_index] & CF_WATER_BIT) &&
                    (pixel_mask[pixel_index] & CF_CLOUD_BIT))
                {
                    pixel_mask[pixel_index] &= ~CF_WATER_BIT;
                }
            }
        }
        printf ("\n");

        /* Release the memory */
        free(nir_data);
        nir_data = NULL;
        free(swir1_data);
        swir1_data = NULL;
        free(filled_nir_data);
        filled_nir_data = NULL;
        free(filled_swir1_data);
        filled_swir1_data = NULL;
    }

    free (clear_mask);
    clear_mask = NULL;

    return SUCCESS;
}