/* File: rgb2bil.c

   Sample program to convert an RGB image to a binary raster of land use 
   categories suitable for ingest by the geogrid component of the 
   WRF Preprocessing System.

   An RGB image file may be created from a TIFF image, for example, with the
   ImageMagick convert utility.

   Input: A text file, cat.tbl, and an RGB image, whose file name is 
          specified on the command line. The cat.tbl file lists the category 
          index, red intensity, green intensity, and blue intensity of the 
          pixels in the RGB image representing the category. Intensities range 
          from 0 to 255. For example, the cat.tbl file may contain

          31  219 153 130
          32  242 0   0
          33  170 0   0

   Output: Upon successful completion, the file data.bil will be created in the 
           current working directory. To use this file in geogrid, after 
           creating an index file, the data.bil file may be renamed to 
           00001-XXXXX.00001-YYYYY, where XXXXX and YYYYY are the values of xdim
           and ydim in 5.5i format, respectively.

   Michael G. Duda, NCAR/MMM
*/


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char ** argv)
{
   FILE * RGBfile;
   FILE * BILfile;
   FILE * MAPfile;
   unsigned char * RGBbuf;
   unsigned char * BILbuf;
   int category;
   int xdim, ydim;
   int * cat, * red, * green, * blue;
   int ncats;
   int i, j;
   int stat;

   if (argc != 4) {
      fprintf(stderr,"\nUsage: %s file.rgb xdim ydim\n\n",argv[0]);
      return 1;
   }

   xdim = atoi(argv[2]);
   ydim = atoi(argv[3]);

   /* Read in color values for each category */
   ncats = 19;
   cat   = (int *)malloc(ncats*sizeof(int));
   red   = (int *)malloc(ncats*sizeof(int));
   green = (int *)malloc(ncats*sizeof(int));
   blue  = (int *)malloc(ncats*sizeof(int));

   MAPfile = fopen("cat.tbl","r");
   i = 0;
   while (fscanf(MAPfile, "%i %i %i %i", &category, &red[i], &green[i], &blue[i]) > 0)
   {
      cat[i] = category;
      i++; 
   }
   fclose(MAPfile);

   /* Read in RGB information */
   RGBfile = fopen(argv[1],"rb");

   RGBbuf = (unsigned char *)malloc(3*xdim*ydim);
   fread((void *)RGBbuf, (size_t)(1), (size_t)(3*xdim*ydim), RGBfile); 

   fclose(RGBfile);

   BILbuf = (unsigned char *)malloc(xdim*ydim);

   /* Extract urban categories from RGB information */
   for(i=0; i<3*xdim*ydim; i+=3) {

      BILbuf[i/3] = (unsigned char)0;
      for(j=0; j<ncats; j++) {
#ifdef INEXACT
         if (abs((int)RGBbuf[i] - red[j]) < 2 && abs((int)RGBbuf[i+1] == green[j]) < 2 && abs((int)RGBbuf[i+2] == blue[j]) < 2) {
            BILbuf[i/3] = (unsigned char)cat[j];
            break;
         } 
#else
         if ((int)RGBbuf[i] == red[j] && (int)RGBbuf[i+1] == green[j] && (int)RGBbuf[i+2] == blue[j]) {
            BILbuf[i/3] = (unsigned char)cat[j];
            break;
         } 
#endif
      }
/*    if (BILbuf[i/3] == (unsigned char)0) printf("%i %i %i\n",(int)RGBbuf[i],(int)RGBbuf[i+1],(int)RGBbuf[i+2]); */

   }

   /* Now write out data in BIL format */
   BILfile = fopen("data.bil","wb");

   fwrite((const void *)BILbuf, (size_t)1, (size_t)(xdim*ydim), BILfile);

   fclose(BILfile);

   free(RGBbuf);
   free(BILbuf);
   free(cat);
   free(red);
   free(green);
   free(blue);

   return 0;
}

