/*C*


________________________________________________________________

        glcm
        $Id: glcm.c,v 1.16 1997/01/14 13:02:18 svein Exp $
        Copyright 1991, Blab, UiO
        Image processing lab, Department of Informatics
        University of Oslo
        E-mail: blab@ifi.uio.no
________________________________________________________________
  
  Permission to use, copy, modify and distribute this software and its
  documentation for any purpose and without fee is hereby granted, 
  provided that this copyright notice appear in all copies and that 
  both that copyright notice and this permission notice appear in supporting
  documentation and that the name of B-lab, Department of Informatics or
  University of Oslo not be used in advertising or publicity pertaining 
  to distribution of the software without specific, written prior permission.

  B-LAB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL B-LAB
  BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 

*/
static char *Id = "$Id: glcm.c,v 1.16 1997/01/14 13:02:18 svein Exp $, Blab, UiO";


#include <math.h>
#include <stdlib.h>
#include <xite/includes.h>
#include <xite/biff.h>
#include <xite/texture.h>
#include <xite/blab.h>
#include <xite/histo.h>
#include <xite/readarg.h>
#include <xite/message.h>
#include XITE_STDIO_H




/*F:glcm*

________________________________________________________________

		glcm
________________________________________________________________

Name:		glcm - Computes Grey Level Cooccurrence Matrix 

Syntax:         | #include <xite/texture.h>
		|
                | int glcm( IBAND input, ID_BAND output, int dx,
                |    int dy, int nogreylevel );

Description:    Computes the Grey Level Cooccurence Matrix of an image.
                The angle and the displacement will be computed from the
                given 'dx' and 'dy'. 'dx' and 'dy' can be negative. All the 
                greylevel values (< 'nogreylevels') on the input band will 
                be increased by one on the output band coordinate system. 
                It means that if there is a greylevel combination (0,1) on the 
                input band then the index (1,2) on the output band will 
                be increased. 

Restrictions:   'input' must have pixel type unsigned byte. 'output' must
                have pixel type double.

Return value:   | 0 => ok
                | 1 => there are grey levels > "nogreylevel" in 
                |      the input band
		| 2 => bad pixel type in input
                | 3 => output is not integer type
                | 4 => horizontal size of output is less than "nogreylevel"
                | 5 => vertical size of output is less than "nogreylevel"

Reference:      | R. M. Haralick, K. Shanmugam, and I. Dinstein,
                | "Textural Features for Image Classification",
                | IEEE Trans. on Systems, Man and Cybernetics,
                | Vol. SMC-3, pp. 610-621, 1973.

Author:		Yogesan K., BLAB, Ifi, UiO

Id: 		$Id: glcm.c,v 1.16 1997/01/14 13:02:18 svein Exp $
________________________________________________________________

*/



#ifndef FUNCPROTO
int glcm(input,output,dx,dy,nogreylevel)
IBAND input;
ID_BAND output;
int dx, dy, nogreylevel;
#else /* FUNCPROTO */
int glcm(IBAND input, ID_BAND output, int dx, int dy, int nogreylevel)
#endif /* FUNCPROTO */
{
  int x, y, pv1, pv2, stat=0;
  int xstart, ystart, xstop, ystop;
  
  if (Ipixtyp(input) != Iu_byte_typ)
    return(Error(2, "Input pixel type must be unsigned byte.\n"));
  if (Ipixtyp((IBAND) output) != Idouble_typ)
    return(Error(3, "Output pixel type must be double.\n"));
  if (Ixsize((IBAND) output) < nogreylevel)
    return(Error(4, "Horizontal output size smaller than nogreylevel.\n"));
  if (Iysize((IBAND) output) < nogreylevel)
    return(Error(5, "Vertical output size smaller than nogreylevel.\n"));

  xstart = (dx>=0) ? 1 : -dx;
  ystart = (dy>=0) ? 1 : -dy;
  xstop  = (dx>=0) ? Ixsize(input)-dx : Ixsize(input);
  ystop  = (dy>=0) ? Iysize(input)-dy : Iysize(input);

  for (y=ystart; y <= ystop; y++)
    for (x=xstart; x <= xstop; x++) {
      pv1 = input[y][x]+1;
      pv2 = input[y+dy][x+dx]+1;
      if ((pv1 > nogreylevel) || (pv2 > nogreylevel)) stat=1;
      else output[pv1][pv2]++; 
    }

  return(stat);
}


/*P:glcm*

________________________________________________________________

		glcm
________________________________________________________________

Name:		glcm - Computes Grey Level Cooccurrence Matrix 

Syntax:		glcm [-heq] <inimage> <outimage> <dx> <dy> [<noofgreylevels>]

Description:    Computes the Grey Level Cooccurence Matrix of an image.
                The angle and the displacement will be computed from the
                given 'dx' and 'dy'. 'dx' and 'dy' can be negative. The
		output image (or grey level cooccurrence matrix) will be of
		size 'noofgreylevels' x 'noofgreylevels'. All the greylevel 
                values (< 'nogreylevels') on the input image will 
                be increased by one on the output image coordinate system. 
                It means that if there is a greylevel combination (0,1) on the 
                input image then the index (1,2) on the output image will 
                be increased.

		'dx', horizontal distance, must fulfill (-50 <= 'dx' <= 50).
                'dy', vertical distance, must fulfill (-50 <= dy <= 50).

		Pixels less than 'noofgreylevels' will be considered. If the
		option '-heq' is set, then the histogram equalization will be
		performed on the input image and the number of grey levels
		will be set to 'noofgreylevels'. Default is 256.

Options:        &-heq
                Histogram equalize 'inimage'.

Reference:      | R. M. Haralick, K. Shanmugam, and I. Dinstein,
                | "Textural Features for Image Classification",
                | IEEE Trans. on Systems, Man and Cybernetics,
                | Vol. SMC-3, pp. 610-621, 1973.

Restrictions:   'inimage' must have bands with pixel type unsigned byte.

Author:		Yogesan K., BLAB, Ifi, UiO

Examples:	| glcm mona.img monaglcm.img 1 1 100
                | glcm -heq mona.img monaglcm.img 1 1 100
		| glcm mona.img monaglcm.img 1 1 
		| glcm -heq mona.img monaglcm.img 1 1 

Id: 		$Id: glcm.c,v 1.16 1997/01/14 13:02:18 svein Exp $
________________________________________________________________

*/

#ifdef MAIN

#ifndef FUNCPROTO
int main(argc, argv)
int argc;
char *argv[];
#else /* FUNCPROTO */
int main(int argc, char **argv)
#endif /* FUNCPROTO */
{
  int dx, dy, nogreylevel, nbands, bn, heq;
  IMAGE inimg;
  ID_IMAGE outimg;
  char *args;

  Iset_message(TRUE);
  Iset_abort(TRUE);
  InitMessage(&argc, argv, xite_app_std_usage_text(
    "Usage: %s [-heq] <inimage> <outimage> <dx> <dy> [<noofgreylevels>]\n"));

  if (argc == 1) Usage(1, NULL);
  args = argvOptions(argc, argv);

  heq = read_bswitch(&argc, argv, "-heq");

  if ((argc < 5) || (argc > 6)) Usage(1, "Illegal number of arguments.\n");

  if (abs(dx = atoi(argv[3])) > 50 || abs(dy = atoi(argv[4])) > 50)
    Usage(2, "-50 <= dx, dy <= 50\n");

  nogreylevel = (argc == 5) ? 256 :  atoi(argv[5]);
  if(nogreylevel > 256) Usage(2, "Number of grey levels should be <= 256.\n");

  inimg = Iread_image(argv[1]);
  if (NOT inimg) Error(2, "Can't find %s.\n", argv[1]);

  nbands = Inbands(inimg);
  outimg = (ID_IMAGE) Imake_image(nbands, "glcm-image", Idouble_typ,
				  nogreylevel, nogreylevel);

  for (bn=1; bn <= nbands; bn++) {
    Iset_start((IBAND) outimg[bn], 0, 0);
    if (heq) 
      if (histoEq(inimg[bn],inimg[bn],nogreylevel))
	Error(2, "histoEq error.\n");

    if (glcm(inimg[bn], outimg[bn],dx, dy, nogreylevel))
      Error(2, "glcm error.\n");
  }

  Ihistory((IMAGE) outimg, argv[0], args);
  Iwrite_image((IMAGE) outimg, argv[2]);

  return(0);
}

#endif










