
/*

________________________________________________________________

        biffinfo
        $Id: biffinfo.c,v 1.33 1997/07/11 14:18:52 svein Exp $
        Copyright 1990, 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: biffinfo.c,v 1.33 1997/07/11 14:18:52 svein Exp $, Blab, UiO";




/*P:biffinfo*

________________________________________________________________

		biffinfo
________________________________________________________________

Name:		biffinfo - extract information from biff-file

Syntax:		| biffinfo [-f] [-t] [-b] [-u] [-h] [-i] [c] [-n <band>] \\
                |  [<filename>...] [<dirname>...]

Description:    'biffinfo' reads the info block of one or more images or all
                images in a directory. If no options are given, the info will
                be written formatted. See example.

Options:	If one or more options are specified (exept -i and -c)
		the output will be unformatted.
                
                &-f
		Print the filename
                &-b
		Print number of bands
                &-n band
		Print info for 'band'
                | band pixtyp xsize ysize xstart ystart xmag ymag
                &-u
		Print info for all bands
		&-t
		Print the image title
                &-h
		Print text (history)  block
		&-i
		Print images only
		&-c
		Print colortables only

		-&You may specify more than one options.
		In unformatted output, the rules are:
		&'-n' or '-u' is specified
		Combine -f -b -n -u -t to one output line/band.
		|    <filename> <bands> <bandinfo> <title>
		|    Print text (-h)
		&Otherwise:
		Combine -f -b -t to one line/image
		|    <filename> <bands> <title>
		|    Print text (-h)
		
Return value:   0 = success, 2 = failure

Author:		Tor Lønnestad and Otto Milvang

Examples:       
                1. Type out all info about a biff-file
		| >> biffinfo mona.img
		| 
		| Filename  : mona.img
		| Title     : MONA                            
		| Bands     : 3
		| Textlen   : 0
		| Band      : Pixeltype Xsize Ysize Xstart Ystart Xmag Ymag
		|    1        uns_byte   512   512    1      1      1    1
		|    2        uns_byte   512   768    1      1      1    1
		|    3        uns_byte   256   256    1      1      1    1
		| Textfield :
		| Fri Jan 11 15:54:05 1991 addw Weight1: 1.00 Weight2: 1.00

		2. Print out the nuber of bands in mona.img
                | >> biffinfo -b mona.img
                | 3

		3. Print title of 2 images sent as standard input
                | cat mona1.img mona2.img | biffinfo -t - -
                | MONA 1
                | MONA 2
                |

		4. Formattet output: filename bands bandinfo
		| >> biffinfo -fbu mona.img
		| mona.img 3 1 3 512 512 1 1 1 1
		| mona.img 3 2 3 512 768 1 1 1 1
		| mona.img 3 3 3 256 256 1 1 1 1

		5. List all images in a directory
		| >> biffinfo -if /local/blab/img
		| /local/blab/mona.img
		| /local/blab/mona1.img
		| /local/blab/mona2.img

Id: 		$Id: biffinfo.c,v 1.33 1997/07/11 14:18:52 svein Exp $
________________________________________________________________

*/

#include <xite/includes.h>
#include <xite/cdoc.h>
#include <xite/biff.h>
#include <stdlib.h>
#include <xite/blab.h>
#include <xite/message.h>
#include XITE_TYPES_H
#ifndef NO_DIRENT
# include <dirent.h>
#else
# include <sys/dir.h>
# define dirent direct
#endif
#include XITE_STDIO_H
#include XITE_UNISTD_H
#include XITE_TYPES_H
#include XITE_STAT_H

#include <sys/param.h>

static DIR *dir_s;
static struct dirent *dirEnt_s;
static struct stat buf_s;

#define readstat(a, b) stat(a,b)
#define testdir(buf) ((buf.st_mode & S_IFMT) == S_IFDIR) 
#define dname(dirEnt) (dirEnt->d_name)

extern int optind;
extern char *optarg;

static char pathname_s[1025];
static int p;

#ifndef FUNCPROTO
static void readsw(argc, argv, format, b, name, title, n, u, hist, img, col)
int argc, *title, *b, *format, *hist, *n, *u, *name, *img, *col;
char *argv[];
#else /* FUNCPROTO */
static void readsw(int argc, char **argv, int *format, int *b, int *name, int *title, int *n, int *u, int *hist, int *img, int *col)
#endif /* FUNCPROTO */
{
  int c;
  while((c = attgetopt(argc, argv, "bfn:uthic")) != EOF)
    {
    if ((char) c != 'i' && (char) c != 'c') *format = FALSE;
    switch ((char) c)
      {
      case 'b': *b = TRUE;               break;
      case 'f': *name  = TRUE;           break;
      case 't': *title = TRUE;           break;
      case 'n': sscanf(optarg,"%d",n);   break;
      case 'u': *u = TRUE;               break;
      case 'h': *hist = TRUE;            break;
      case 'i': *img  = TRUE;            break;
      case 'c': *col  = TRUE;            break;
      default:  printf("error %d\n", c);       break;
      }
  }
}

#ifndef FUNCPROTO
static int readnm(name, filename, dirname, pipe, i, isdir)
char *name, **filename, **dirname;
int *isdir, *pipe;
IMAGE *i;
#else /* FUNCPROTO */
static int readnm(char *name, char **filename, char **dirname, int *pipe, IMAGE *i, int *isdir)
#endif /* FUNCPROTO */
{
  int rstat;

  *pipe  = 0;
  *isdir = 0;
  if (name[0] == '-') {
    *pipe = 1;
    *i = Iread_image(name);
    if (*i EQ 0) exit(0);
    rstat = Iok;
    *isdir = 0;
  } else {
    if (readstat(name, &buf_s) != 0) {
      *filename = name;
      return(-1);
    }
    *isdir = testdir(buf_s);
    if (*isdir == 0) {
      *filename = name;
      rstat = Iopen_image(i, name,Ireadonly);
    } else {
      *dirname = name;
      dir_s = opendir(*dirname);
      dirEnt_s = readdir(dir_s);
      rstat = -1;
    }
  }
  return(rstat);
}

#ifndef FUNCPROTO
static BiffStatus readdr(filename, i)
char **filename;
IMAGE *i;
#else /* FUNCPROTO */
static BiffStatus readdr(char **filename, IMAGE *i)
#endif /* FUNCPROTO */
{
  *filename = dname(dirEnt_s);
  return(Iopen_image(i, *filename, Ireadonly));
}

#ifndef FUNCPROTO
static void print_name(isdir, dirname, filename)
int isdir;
char *dirname, *filename;
#else /* FUNCPROTO */
static void print_name(int isdir, char *dirname, char *filename)
#endif /* FUNCPROTO */
{
  if (p++) printf(" ");
  if (isdir)
    printf("%s/%s",dirname, filename); else
      printf("%s",filename);
}

#ifndef FUNCPROTO
static void print_title(i)
IMAGE i;
#else /* FUNCPROTO */
static void print_title(IMAGE i)
#endif /* FUNCPROTO */
{
  if (p++) printf(" ");
  printf("%s",Ititle(i));
} 

#ifndef FUNCPROTO
static void print_nbands(i)
IMAGE i;
#else /* FUNCPROTO */
static void print_nbands(IMAGE i)
#endif /* FUNCPROTO */
{
  if (p++) printf(" ");
  printf("%ld",Inbands(i));
} 


#ifndef FUNCPROTO
static void print_bandinfo(i, n)
IMAGE i;
int n;
#else /* FUNCPROTO */
static void print_bandinfo(IMAGE i, int n)
#endif /* FUNCPROTO */
{
  if (n >= 1 && n <= Inbands(i))
    {
      if (p++) printf(" ");
      printf("%4d %4ld %6ld %6ld %6ld %6ld %6ld %6ld",
	     n, Ipixtyp(i[n]), Ixsize(i[n]), Iysize(i[n]),
	     Ixstart(i[n]),Iystart(i[n]),Ixmag(i[n]),Iymag(i[n]));
    }
} 

#ifndef FUNCPROTO
static void print_history(i, pipe)
IMAGE i;
int pipe;
#else /* FUNCPROTO */
static void print_history(IMAGE i, int pipe)
#endif /* FUNCPROTO */
{
  if (! pipe) Iread_text(i);
  Itype_text(i, stdout);
}

#ifndef FUNCPROTO
static void print_format(i, pipe, argc, isdir, dirname, filename)
IMAGE i;
int pipe, argc;
int isdir;
char *dirname, *filename;
#else /* FUNCPROTO */
static void print_format(IMAGE i, int pipe, int argc, int isdir, char *dirname, char *filename)
#endif /* FUNCPROTO */
{
  int j;
  printf("\nFilename  : ");
  if (!pipe) { print_name(isdir, dirname, filename); printf("\n"); }
  else printf("stdin\n");
  printf("Title     : %s\n",Ititle(i));
  printf("Bands     : %ld\n",Inbands(i));
  printf("Textlen   : %ld\n",Inchars(i));
  if (Inbands(i))
    {
      printf("Band        Pixeltype   Xsize  Ysize");
      printf(" Xstart Ystart   Xmag   Ymag\n");
    }
  for (j=1; j <= Inbands(i);  j++)
    {
      printf("  %2d        %-10s %6ld %6ld %6ld %6ld %6ld %6ld\n",
	     j, Ipixname(Ipixtyp(i[j])),
	     Ixsize(i[j]),Iysize(i[j]),
	     Ixstart(i[j]),Iystart(i[j]),Ixmag(i[j]),Iymag(i[j]));
    }
  if (! pipe) Iread_text(i);
  if (! Iend_of_text(i))
    { 
      printf("Textfield :\n");
      Itype_text(i, stdout);
    }
  if (argc - optind > 0) printf("\n\n");
} 

#ifndef FUNCPROTO
int main(argc,argv)
int argc;
char *argv[];
#else /* FUNCPROTO */
int main(int argc, char **argv)
#endif /* FUNCPROTO */
{
  IMAGE i;
  int rstat, j, isdir, isimg, iscol;
  int n=0, u = FALSE, name = FALSE, img=FALSE, col=FALSE;
  int title = FALSE, b=FALSE, format=TRUE, hist = FALSE, pipe = FALSE;
  char *dirname = NULL, *filename = NULL;
    
  Iset_message(FALSE);
  InitMessage(&argc, argv, xite_app_std_usage_text(
    "Usage: %s [<option>...] [<filename>...] [<dirname>]\n\
       where <option> is chosen from\n\
         -f        : Print the filename\n\
	 -b        : Print number of bands\n\
	 -n <band> : Print info for 'band'\n\
	             <band> <pixtyp> <xsize> <ysize>\n\
                            <xstart> <ystart> <xmag> <ymag>\n\
	 -u        : Print info for all bands\n\
	 -t        : Print the image title\n\
	 -h        : Print text (history)  block\n\
	 -i        : Print images only\n\
	 -c        : Print colortables only\n"));

  readsw(argc, argv, &format, &b, &name, &title, &n, 
	 &u, &hist, &img, &col); 

  if (argc == 1) Usage(1, NULL);

  /* Treat remaining command-line arguments as image filenames. */
  while (argc - optind > 0) {
    rstat = readnm(argv[optind++], &filename, &dirname, &pipe, &i, &isdir); 
    if (isdir) { 
      (void) getcwd(pathname_s, MAXPATHLEN);
      chdir(dirname);
    }
    do {
      if (isdir) rstat = readdr(&filename, &i); 
      
      if (rstat != Iok) {
	if (format && (isdir == 0)) 
	  printf("biffinfo: %s is not a BIFF-file\n\n",filename);
	continue;
      }
      if (u) 
	for(j=1; j <= Inbands(i); j++) {
	  isimg = Ipixtyp(i[j]) < 256;
	  iscol = !isimg;
	  if ((img && isimg) || (col && iscol) || (img == col)) {
	    p = 0;
	    if (name && !pipe) print_name(isdir, dirname, filename);
	    if (b)             print_nbands(i);
	    print_bandinfo(i, j);
	    if (title)         print_title(i);
	    if(p) printf("\n");
	  }
      } else {
	if (n) {
	  isimg = Ipixtyp(i[n]) < 256;
	  iscol = !isimg;
	} else {
	  isimg = 1;
	  iscol = 1;
	  for (j=1; j<= Inbands(i); j++) {
	    isimg = isimg && (Ipixtyp(i[j]) < 256);
	    iscol = iscol && (Ipixtyp(i[j]) >= 256);
	  }
	}
	if ((img && isimg) || (col && iscol) || (img == col)) {
	  p = 0;
	  if (name && !pipe) print_name(isdir, dirname, filename);
	  if (b)             print_nbands(i);
	  if (n)             print_bandinfo(i, n);
	  if (title)         print_title(i);
	  if(p) printf("\n");
	}
      }
      if (hist) print_history(i, pipe);
      if (format) {
	isimg = 1;
	iscol = 1;
	for (j=1; j<= Inbands(i); j++) {
	  isimg = isimg && (Ipixtyp(i[j]) < 256);
	  iscol = iscol && (Ipixtyp(i[j]) >= 256);
	}
	if ((img && isimg) || (col && iscol) || (img == col))
	  print_format(i, pipe, argc, isdir, dirname, filename);
      }
    }
    while(isdir && (dirEnt_s  = readdir(dir_s)));
    if (isdir) chdir(pathname_s);
    if ((! pipe) && (rstat == Iok)) Iclose_image(i);
    if (argc - optind > 0 && filename == NULL) break;
  }
  return(0);
}
