/* extractheader.c                                           */
/*                                                           */
/* written by thomp, 04/97                                   */
/*                                                           */
/* This short C program reads the 1056 byte binary header    */
/* of a Cameca SX50 .img file and extracts and writes most   */
/* of the image acquisition parameters and spectrometer and  */
/* column settings to an ASCII text file.  It was written    */
/* to run on a Sun SPARCstation, but it should work on most  */
/* UNIX systems.  Integer variables are 4 byte(32 bit).      */
/* The 'Input filename:' command will accept any pathname up */
/* to 80 characters in length, but the 'Output filename:'    */
/* command will only accept a filename with the current      */
/* directory as a path.                                      */

#include <stdio.h>
#define	SPM 5		/* maximum number of spectrometers 
*/

main(argc,argv)

int argc;
char *argv[];

{

/* the image header consists of two parts: */

/* the first part contains 19 integers, most of them unknown */

struct first_hdr {
  int magic_number;
  int size_x;
  int size_y;
  int unknown_1;
  int unknown_2;
  int unknown_3;
  int unknown_4;
  int unknown_5;
  int unknown_6;
  int pix_depth;
  int unknown_7;
  int unknown_8;
  int unknown_9;
  int unknown_10;
  int unknown_11;
  int unknown_12;
  int unknown_13;
  int unknown_14;
  int hdr_offset;
} one_hdr,*pone_hdr;

/* the second part is described by the SX file 'desinc.h' */

struct second_hdr {
  char label[20];	/* cond. file without extension */
  char comnt[80];	/* comment line */
  char date[28];	/* creation date */
  float bmcur;		/* beam-current 0->10000 nA */
  float hgtv;		/* hight-voltage 0->50 Kv */
  char cond[8];		/* column condition on file */
  int spect;		/* number of spectrometer */
  int stgpos[3];	/* stage position X,Y,Z -100000 -> 100000 */
  int modx;		/* mode 0:64 , 1:128 , 2:256 or 3:512  */
  int mody;		/* = nptx , npty */
  float step;		/* um */
  float time;		/* ms */
  int modscan;		/* scanning mode 0:beam or 1:stage */
  int bmrot;		/* beam rotation 0->359 deg */
  int modacc;		/* acquisition mode 0:auto or 1:man = adjust 
*/
  int modz;		/* z correction 0:no or 1:yes  = iupdz */
  int semc;		/* SEM channels 0:no 1:M1 or 2:M2 */
  int vidc;		/* video channels 0:VS1 or 1:VS2 = numvs */
  int elecs;		/* Electron signal 0:SE , 1:BSE or 2:ABS */
  int ray[SPM];		/* 0->6 for : no ray,Ka,Kb,La,Lb,Ma or Mb */
  int pos[SPM];		/* Spectro position 22000->83000 */
  char symb[SPM][8];	/* element symbol for each spectro */
  int crys[SPM];	/* Crystal number in list of 4 */
  char namest[SPM][20];	/* standard name */
  int papc;		/* pap correction no/yes */
  int nxt[SPM][6];	/* Xtal configuration */
  int offset[3];	/* stage offset x,y,z */
  int stglim[3][2];	/* stage position limite min/max for x,y,z */
  int stgfoc[4][3];	/* each stage corner position x,y,z */
  int nwds;		/* number of specto use ( <spect ) */
  int npha[SPM][6];	/* Pha parameters for each spectro */
  char xnam[20][8];	/* crystal name list : 4 char */
  int bmsiz;		/* beam size */
  int splim[SPM][2];	/* Spectro limites min/max */
  int sprot[SPM];	/* Spectro position rotation */
  int optbse;		/* option for BSE: 1,2,3,4,5,6,Z,T (=0,,,7) */
  int nacq;		/* spectro used on acq. : [1,spect] */
  float mag;		/* magnification */
  int flag_acq;		/* 0 : CIAP or 1 : FCIAP */
  int frames;		/* FCIAP : accumulated frames number */
} two_hdr,*ptwo_hdr;

  FILE *input,*output;
  FILE *fopen();

  int i,xnam_index,spec;

  pone_hdr = &one_hdr;
  ptwo_hdr = &two_hdr;

  if (argc < 3)
  {
    puts("Error:  not enough arguments");
    puts("Usage:  extractheader <input> <output>");
    exit(8);
  }

  input = fopen(argv[1],"r");
  if (input == NULL)
  {
    puts("open input_file error");
    exit(8);
  }

  output = fopen(argv[2],"w");
  if (output == NULL)
  {
    puts("open output_file error");
    exit(8);
  }

  fread(pone_hdr,sizeof(*pone_hdr),1,input);
  fread(ptwo_hdr,sizeof(*ptwo_hdr),1,input);

  fclose(input);

  fprintf(output,"filename: %s\n",ptwo_hdr->label);
  fprintf(output,"creation date: %s\n",ptwo_hdr->date);
  fprintf(output,"image size (pixels): %d X %ld\n",
          pone_hdr->size_x,pone_hdr->size_y);
  fprintf(output,"pixel depth: %d bit\n",pone_hdr->pix_depth);
  fprintf(output,"header offset: %d bytes\n",pone_hdr->hdr_offset);
  fprintf(output,"beam current (nA): %f\n",ptwo_hdr->bmcur);
  fprintf(output,"high voltage (kV): %f\n",ptwo_hdr->hgtv);
  fprintf(output,"step size (microns): %f\n",ptwo_hdr->step);
  fprintf(output,"count time (milliseconds): %f\n",ptwo_hdr->time);
  fprintf(output,"beam size (microns): %d\n",ptwo_hdr->bmsiz);
  fprintf(output,"magnification: %f\n",ptwo_hdr->mag);
  fprintf(output,"image center (X,Y,Z): (%d,%d,%d)\n",ptwo_hdr-
>stgpos[0],
          ptwo_hdr->stgpos[1],ptwo_hdr->stgpos[2]);

  switch (ptwo_hdr->elecs)
  {
    case 0:
      fprintf(output,"electron signal: SE\n");
      break;
    case 1:
      fprintf(output,"electron signal: BSE\n");
      break;
    case 2:
      fprintf(output,"electron signal: ABS\n");
  }

  if (ptwo_hdr->flag_acq)
  {
    fprintf(output,"acquisition mode: FCIAP\n");
    fprintf(output,"accumulated frames: %d\n",ptwo_hdr->frames);
  }
  else
  {
    fprintf(output,"acquisition mode: CIAP\n");
  }

  if (ptwo_hdr->modscan)
  {
    fprintf(output,"scan mode: stage\n");
  }
  else
  {
    fprintf(output,"scan mode: beam\n");
  }
  if (ptwo_hdr->nwds)
  {
    fprintf(output,"Spectrometer parameters:\n");
    for (i=0; i<SPM; i++)
    {
      fprintf(output,"\tsp%d",i+1);
      xnam_index = ptwo_hdr->crys[i] + (i*4);
      fprintf(output,"\t%s",ptwo_hdr->xnam[xnam_index]);
      fprintf(output,"\t%d",ptwo_hdr->pos[i]);
      fprintf(output,"\t%s",ptwo_hdr->symb[i]);
      switch (ptwo_hdr->ray[i])
      {
        case 0:
          fprintf(output,"\tno ray\n");
          break;
        case 1:
          fprintf(output,"\tKa\n");
          break;
        case 2:
          fprintf(output,"\tKb\n");
          break;
        case 3:
          fprintf(output,"\tLa\n");
          break;
        case 4:
          fprintf(output,"\tLb\n");
          break;
        case 5:
          fprintf(output,"\tMa\n");
          break;
        case 6:
          fprintf(output,"\tMb\n");
          break;
      }
    }
  }    
  
  fclose(output);
}
