Exemplo n.º 1
0
/*
       The portable graymap format is a lowest common denominator
       grayscale file format.  The definition is as follows:

       - A "magic number" for identifying the file type.   A  pgm
         file's magic number is the two characters "P5".

       - Whitespace (blanks, TABs, CRs, LFs).

       - A width, formatted as ASCII characters in decimal.

       - Whitespace.
       - A height, again in ASCII decimal.

       - Whitespace.

       - The maximum gray value (Maxval), again in ASCII decimal.
         Must be less than 65536.

       - Newline or other single whitespace character.

       - A raster of  Width  *  Height  gray  values,  proceeding
         through the image in normal English reading order.  Each
         gray value is a number from 0  through  Maxval,  with  0
         being  black and Maxval being white.  Each gray value is
         represented in pure binary by either 1 or 2  bytes.   If
         the  Maxval  is less than 256, it is 1 byte.  Otherwise,
         it is 2 bytes.  The most significant byte is first.

       - Characters from a "#" to the  next  end-of-line,  before
         the maxval line, are comments and are ignored.
*/
int readPgmImage(const char *name,_image *im)
{
  
  char string[256];
  int x=0, y=0;
  int max=0;
  
  fgetns( string, 255, im );
  if ( strncmp(string, PGM_MAGIC, strlen(PGM_MAGIC) ) ) {
    fprintf( stderr, "readPgmImage: bad magic string in \'%s\'\n", name );
    return( -1 );
  }
  
  do {
    fgetns( string, 255, im );

    if ( string[0] != '#' ) {
      if ( x == 0 && y == 0 ) {
	sscanf( string, "%d %d", &x, &y );
      }
      else if ( max == 0 ) {
	sscanf( string, "%d", &max );
      }
    }
  } while ( max == 0 );


  im->xdim = x;
  im->ydim = y;
  im->zdim = 1;
  im->vdim = 1;

  im->wordKind = WK_FIXED;
  im->sign = SGN_UNSIGNED;

  if ( max < 256 ) im->wdim = 1;
  else if ( max < 65536 ) {
    im->wdim = 2;
    fprintf( stderr, "readPgmImage: Warning, data of \'%s\' may have to be swapped\n", name );
  }
  else {
    fprintf( stderr, "readPgmImage: max value too large (%d) in \'%s\'\n", max, name );
    return( -1 );
  }
  im->data = ImageIO_alloc( x*y );		     
  
  ImageIO_read( im, im->data,  x*y );
  
  return 1;
}
Exemplo n.º 2
0
Arquivo: gis.cpp Projeto: FMX/CGAL
int readGisHeader( const char* name,_image* im)
{
  char *s, *str = NULL;
  int status;
  int n=0, nusermax = 20;
  

  str = (char*)ImageIO_alloc( _LGTH_STRING_+1 );
  
  if ( !fgetns(str, _LGTH_STRING_, im) ) 
    { ImageIO_free( str ); return -1; }
  status = sscanf( str,"%d %d %d %d", &(im->xdim), &(im->ydim), 
		   &(im->zdim), &(im->vdim) );
  switch ( status ) {
  case 2 :    im->zdim = 1;
  case 3 :    im->vdim = 1;
  case 4 :    break;
  default :
    fprintf( stderr, "readGisHeader: unable to read dimensions in '%s'\n", name );
    ImageIO_free( str ); 
    return -1;
  }
  if ( im->vdim > 1 ) {
    im->vectMode = VM_INTERLACED;
  } 
  else {
    im->vectMode = VM_SCALAR;
  }
#define ADD_USER_STRING { \
    if ( n == 0 ) { \
      im->user = (char**)ImageIO_alloc( nusermax * sizeof( char*) ); \
      for ( n=0; n<nusermax; n++ ) im->user[n] = NULL; \
      n = 0; \
    } \
    im->user[n] = (char*)ImageIO_alloc( 1+strlen( s ) ); \
    strcpy( im->user[n++], s ); \
  }



  while( fgetns( str, _LGTH_STRING_, im ) != 0 ) {
    s = str;
    do {

      while ( *s == ' ' || *s == '\t' ) s++;

      if ( !strncmp( s, "-dx ", 4 ) ) {
	s += 4;
	status = sscanf( s, "%lf", &(im->vx) );
	if ( status != 1 ) {
	  fprintf( stderr, "readGisHeader: error while reading -dx in '%s'\n", s-4 );
	  *s = '\0';
	} 
	else {
	  while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++;
	}
      }
      else if ( !strncmp( s, "-dy ", 4 ) ) {
	s += 4;
	status = sscanf( s, "%lf", &(im->vy) );
	if ( status != 1 ) {
	  fprintf( stderr, "readGisHeader: error while reading -dy in '%s'\n", s-4 );
	  *s = '\0';
	} 
	else {
	  while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++;
	}
      }
      else if ( !strncmp( s, "-dz ", 4 ) ) {
	s += 4;
	status = sscanf( s, "%lf", &(im->vz) );
	if ( status != 1 ) {
	  fprintf( stderr, "readGisHeader: error while reading -dz in '%s'\n", s-4 );
	  *s = '\0';
	} 
	else {
	  while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++;
	}
      }
      else if ( !strncmp( s, "-dt ", 4 ) ) {
	ADD_USER_STRING
	s += 4; 
	while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; 
      }

      else if ( !strncmp( s, "-type ", 6 ) ) {
	s += 6; 
	if ( !strncmp( s, "U8", 2 ) ) {
	  im->wdim     = 1;
	  im->wordKind = WK_FIXED;
	  im->sign     = SGN_UNSIGNED;
	  s += 2;
	}
	else if ( !strncmp( s, "S8", 2 ) ) {
	  im->wdim     = 1;
	  im->wordKind = WK_FIXED;
	  im->sign     = SGN_SIGNED;
	  s += 2;
	} 
	else if ( !strncmp( s, "U16", 3 ) ) {
	  im->wdim     = 2;
	  im->wordKind = WK_FIXED;
	  im->sign     = SGN_UNSIGNED;
	  s += 3;
	}
	else if ( !strncmp( s, "S16", 3 ) ) {
	  im->wdim     = 2;
	  im->wordKind = WK_FIXED;
	  im->sign     = SGN_SIGNED;
	  s += 3;
	}
	else if ( !strncmp( s, "U32", 3 ) ) {
	  im->wdim     = 4;
	  im->wordKind = WK_FIXED;
	  im->sign     = SGN_UNSIGNED;
	  s += 3;
	}
	else if ( !strncmp( s, "S32", 3 ) ) {
	  im->wdim     = 4;
	  im->wordKind = WK_FIXED;
	  im->sign     = SGN_SIGNED;
	  s += 3;
	}
	else if ( !strncmp( s, "FLOAT", 5 ) ) {
	  im->wdim     = sizeof( float );
	  im->wordKind = WK_FLOAT;
	  im->sign     = SGN_UNKNOWN;
	  s += 5;
	}
	else if ( !strncmp( s, "DOUBLE", 6 ) ) {
	  im->wdim     = sizeof( double );
	  im->wordKind = WK_FLOAT;
	  im->sign     = SGN_UNKNOWN;
	  s += 6;
	}
	else {
	  fprintf( stderr, "readGisHeader: unknown type '%s'\n", s-6 );
	  *s = '\0'; 
	}
      }

      else if ( !strncmp( s, "-bo ", 4 ) ) {
	s += 4;
	if ( !strncmp( s, "ABCD", 4 ) ) {
	  im->endianness = END_BIG;
	  s += 4;
	}
	else if ( !strncmp( s, "SUN", 3 ) ) {
	  im->endianness = END_BIG;
	  s += 3;
	}
	else if ( !strncmp( s, "DCBA", 4 ) ) {
	  im->endianness = END_LITTLE;
	  s += 4;
	}
	else if ( !strncmp( s, "ALPHA", 5 ) ) {
	  im->endianness = END_LITTLE;
	  s += 5;
	}
	else {
	  fprintf( stderr, "readGisHeader: unknown byte order '%s'\n", s-4 );
	  *s = '\0'; 
	}
      }

      else if ( !strncmp( s, "-ar ", 4 ) ) {
	s += 4;
	if ( !strncmp( s, "SUN", 3 ) ) {
	  im->endianness = END_BIG;
	  s += 3;
	}
	else if ( !strncmp( s, "ALPHA", 5 ) ) {
	  im->endianness = END_LITTLE;
	  s += 5;
	}
	else {
	  fprintf( stderr, "readGisHeader: unknown architecture '%s'\n", s-4 );
	  *s = '\0'; 
	}
      }

      else if ( !strncmp( s, "-om ", 4 ) ) {
	s += 4;
	if ( !strncmp( s, "binar", 5 ) ) {
	  im->dataMode = DM_BINARY;
	  s += 5;
	} 
	else if ( !strncmp( s, "ascii", 5 ) ) {
	  im->dataMode = DM_ASCII;
	  s += 5;
	} 
	else {
	  fprintf( stderr, "readGisHeader: unknown data type '%s'\n", s-4 );
	  ImageIO_free( str );
	  return -1;
	}
      }
      
      
      else {
	fprintf( stderr, "readGisHeader: unknown indentifier '%s'\n", s );
	ADD_USER_STRING
	*s = '\0'; 
      }

    } while( *s != '\0' && *s != '\n' );

  }
  ImageIO_free( str );
  

  if ( im->endianness == END_UNKNOWN ) {
    im->endianness = _getEndianness();
  }


  /* header is read. close header file and open data file. */
  if( name != NULL ) {
    
    int length = strlen(name) ;
    char* data_filename = (char *) ImageIO_alloc(length+4) ;
    
    if( strcmp( name+length-4, ".dim" ) ) {
      fprintf (stderr,
	       "readGisHeader: error: file header extension must be .dim\n");
      ImageIO_free( data_filename );
      return -1;
    }
    
    ImageIO_close(im);


    /* open data file
     */
    
    strcpy(data_filename,name);
    strcpy(data_filename+length-3, "ima.gz");
    _openReadImage(im,data_filename);
    
    if(!im->fd) {
      
      strcpy(data_filename,name);
      strcpy(data_filename+length-3, "ima");
      _openReadImage(im,data_filename);
      if(!im->fd) {
	fprintf(stderr, "readGisHeader: error: unable to open data file \'%s\'\n", data_filename);
	ImageIO_free( data_filename );
	return -1;
	
      }
    }
    ImageIO_free( data_filename );





    /* read data if ascii
       only U8 and S8
     */
    if ( im->dataMode == DM_ASCII ) {
      int size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim;
      unsigned int n;
      char *tmp;
      int ret, iv=0;
      
      if ( im->wdim != 1 || im->wordKind != WK_FIXED ) {
	fprintf(stderr, "readGisHeader: error: unable to read such ascii type\n" );
	return -1;
      }

      n = 0 ;
      if ( size <= 0 ) return -1;
      if(!im->data) {
	im->data = ( void*) ImageIO_alloc(size);
	if(!im->data) return -1;
      }
      
      n = 0;
      str = (char*)ImageIO_alloc( _LGTH_STRING_+1 );
      while( fgetns( str, _LGTH_STRING_, im ) != 0 &&
	     n < im->xdim * im->ydim * im->zdim * im->vdim ) {
	tmp = str;
	while ( *tmp != '\n' && *tmp != '\0' && *tmp != EOF &&
		n < im->xdim * im->ydim * im->zdim * im->vdim ) {
	  /* skip trailing whitespace
	   */
	  while ( *tmp == ' ' || *tmp == '\t' )
	    tmp++;
	  if ( *tmp == '\0' || *tmp == '\n' || *tmp == EOF )
	    continue;
	  
	  /* read a number
	   */
	  switch ( im->wordKind ) {
	  case WK_FIXED :
	    ret = sscanf( tmp, "%d", &iv );
	  break;
	  default :
	    ImageIO_free( im->data ); im->data = NULL;
	    ImageIO_free( str );
	    return -1;
	  }
	  
	  if ( ret != 1 ) {
	    fprintf( stderr, "readGisHeader: error in reading ascii data\n" );
	    ImageIO_free( im->data ); im->data = NULL;
	    ImageIO_free( str );
	    return -1;	
	  }
	  
	  if ( im->wordKind == WK_FIXED 
	       && im->sign == SGN_UNSIGNED 
	       && im->wdim == 1 ) {
	    unsigned char *buf = (unsigned char *)im->data;
	    buf += n;
	    if ( iv < 0 )        *buf = (unsigned char)0;
	    else if ( iv > 255 ) *buf = (unsigned char)255;
	    else                 *buf = (unsigned char)iv;
	    n ++;
	  }
	  else if ( im->wordKind == WK_FIXED 
		    && im->sign == SGN_SIGNED 
		    && im->wdim == 1 ) {
	    char *buf = (char *)im->data;
	    buf += n;
	    if ( iv < -128 )     *buf = (char)-128;
	    else if ( iv > 127 ) *buf = (char)127;
	    else                 *buf = (char)iv;
	    n ++;
	  }
	  else if ( im->wordKind == WK_FIXED 
		    && im->sign == SGN_UNSIGNED 
		    && im->wdim == 2 ) {
	    unsigned short int *buf = (unsigned short int *)im->data;
	    buf += n;
	    if ( iv < 0 )          *buf = (unsigned short int)0;
	    else if ( iv > 65535 ) *buf = (unsigned short int)65535;
	    else                   *buf = (unsigned short int)iv;
	    n ++;
	  }
	  else if ( im->wordKind == WK_FIXED 
		    && im->sign == SGN_SIGNED 
		    && im->wdim == 2 ) {
	    short int *buf = (short int *)im->data;
	    buf += n;
	    if ( iv < -32768 )     *buf = (short int)-32768;
	    else if ( iv > 32767 ) *buf = (short int)32767;
	    else                   *buf = (short int)iv;
	    n ++;
	  }
	  else {
	    ImageIO_free( im->data ); im->data = NULL;
	    ImageIO_free( str );
	    return -1;
	  }
	  


	  /* skip a number 
	   */
	  while ( (*tmp >= '0' && *tmp <= '9') || *tmp == '.' || *tmp == '-' )
	    tmp++;
	}
      }
      ImageIO_free( str );
      ImageIO_close(im);
    }

  }

  
  /* check header validity */
  if ( im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 &&
       im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 &&
       ( im->wordKind == WK_FLOAT ||
	 (im->wordKind == WK_FIXED && im->sign != SGN_UNKNOWN) ) &&
       im->endianness != END_UNKNOWN ) {
    return 0;
  }

  return -1;
}
Exemplo n.º 3
0
/*
       The portable graymap format is a lowest common denominator
       grayscale file format.  The definition is as follows:

       - A "magic number" for identifying the file type.   A  pgm
         file's magic number is the two characters "P2".

       - Whitespace (blanks, TABs, CRs, LFs).

       - A width, formatted as ASCII characters in decimal.

       - Whitespace.
       - A height, again in ASCII decimal.

       - Whitespace.

       - The maximum gray value (Maxval), again in ASCII decimal.
         Must be less than 65536.

       - Newline or other single whitespace character.

       - A raster of  Width  *  Height  gray  values,  proceeding
         through the image in normal English reading order.  Each
         gray value is a number from 0  through  Maxval,  with  0
         being  black and Maxval being white.  Each gray value is
         represented in pure binary by either 1 or 2  bytes.   If
         the  Maxval  is less than 256, it is 1 byte.  Otherwise,
         it is 2 bytes.  The most significant byte is first.

       - Characters from a "#" to the  next  end-of-line,  before
         the maxval line, are comments and are ignored.
*/
int readPgmAsciiImage(const char *name,_image *im)
{
  char string[256];
  int x=0, y=0;
  int max=0;

  int n;
  char *tmp;
  int iv;

  fgetns( string, 255, im );
  if ( strncmp(string, PGM_ASCII_MAGIC, strlen(PGM_ASCII_MAGIC) ) ) {
    fprintf( stderr, "readAsciiPgmImage: bad magic string in \'%s\'\n", name );
    return( -1 );
  }
  
  do {
    fgetns( string, 255, im );

    if ( string[0] != '#' ) {
      if ( x == 0 && y == 0 ) {
	sscanf( string, "%d %d", &x, &y );
      }
      else if ( max == 0 ) {
	sscanf( string, "%d", &max );
      }
    }
  } while ( max == 0 );

  im->xdim = x;
  im->ydim = y;
  im->zdim = 1;
  im->vdim = 1;

  im->wordKind = WK_FIXED;
  im->sign = SGN_UNSIGNED;

  if ( max < 256 ) im->wdim = 1;
  else if ( max < 65536 ) {
    im->wdim = 2;
  }
  else {
    fprintf( stderr, "readAsciiPgmImage: max value too large (%d) in \'%s\'\n", max, name );
    return( -1 );
  }
  im->data = ImageIO_alloc( x*y );		     
  
  n=0;

  while( fgetns( string, 255, im ) != 0 && n < x*y ) {
    tmp = string;
    while ( *tmp != '\n' && *tmp != '\0' && *tmp != EOF && n < x*y ) {
      /* skip trailing whitespace
       */
      while ( *tmp == ' ' || *tmp == '\t' )
	tmp++;
      if ( *tmp == '\0' || *tmp == '\n' || *tmp == EOF )
	continue;
      
      /* read a number
       */
      switch ( im->wordKind ) {
      case WK_FIXED :
	if ( sscanf( tmp, "%d", &iv ) != 1 ) {
	  fprintf( stderr, "readAsciiPgmImage: error in reading ascii data\n" );
	  ImageIO_free( im->data ); im->data = NULL;
	  return 0;
	}
	break;
      default :
	ImageIO_free( im->data ); im->data = NULL;
	return 0;
      }
	  
      if ( im->wdim == 1 ) {
	unsigned char *buf = (unsigned char *)im->data;
	buf += n;
	if ( iv < 0 )        *buf = (unsigned char)0;
	else if ( iv > 255 ) *buf = (unsigned char)255;
	else                 *buf = (unsigned char)iv;
	n ++;
      }
      else if ( im->wdim == 2 ) {
	unsigned short int *buf = (unsigned short int *)im->data;
	buf += n;
	if ( iv < 0 )          *buf = (unsigned short int)0;
	else if ( iv > 65535 ) *buf = (unsigned short int)65535;
	else                   *buf = (unsigned short int)iv;
	n ++;
      }
      else {
	fprintf( stderr, "readAsciiPgmImage: word im not handled\n" );
	ImageIO_free( im->data ); im->data = NULL;
	return 0;
      }
      
      /* skip a number 
       */
      while ( (*tmp >= '0' && *tmp <= '9') || *tmp == '.' || *tmp == '-' )
	tmp++;
    }
  }

  
  return 1;
}
Exemplo n.º 4
0
/* read header of an opened inrimage */
int readInrimageHeader(const char *,_image *im) {
  char str[257];
  int n, nusr;
  stringListHead strl = { NULL, NULL };
  stringListElement *oel, *el;

  Set_numeric_locale num_locale("C");

  if(im->openMode != OM_CLOSE) {
    /* read image magic number */
    if(!fgetns(str, 257, im )) return -1;
    if(strcmp(str, INR4_MAGIC)) return -1;


    /* while read line does not begin with '#' or '\n', read line
       and decode field */
    if(!fgetns(str, 257, im)) return -1;

    while(str[0] != '#' && str[0] != '\0') {

      if(!strncmp(str, "XDIM=", 5)) {
	if(sscanf(str+5, "%u", &im->xdim) != 1) return -1;
      }
      else if(!strncmp(str, "YDIM=", 5)) {
	if(sscanf(str+5, "%u", &im->ydim) != 1) return -1;
      }
      else if(!strncmp(str, "ZDIM=", 5)) {
	if(sscanf(str+5, "%u", &im->zdim) != 1) return -1;
      }
      else if(!strncmp(str, "VDIM=", 5)) {
	if(sscanf(str+5, "%u", &im->vdim) != 1) return -1;
	if(im->vdim == 1) im->vectMode = VM_SCALAR;
	else im->vectMode = VM_INTERLACED;
      }
      else if(!strncmp(str, "VX=", 3)) {
	if(sscanf(str+3, "%lf", &im->vx) != 1) return -1;
      }
      else if(!strncmp(str, "VY=", 3)) {
	if(sscanf(str+3, "%lf", &im->vy) != 1) return -1;
      }
      else if(!strncmp(str, "VZ=", 3)) {
	if(sscanf(str+3, "%lf", &im->vz) != 1) return -1;
      }
      else if(!strncmp(str, "TYPE=", 5)) {
	if(!strncmp(str+5, "float", 5)) im->wordKind = WK_FLOAT;
	else {
	  if(!strncmp(str+5, "signed fixed", 12)) {
	    im->wordKind = WK_FIXED;
	    im->sign = SGN_SIGNED;
	  }
	  else if(!strncmp(str+5, "unsigned fixed", 14)) {
	    im->wordKind = WK_FIXED;
	    im->sign = SGN_UNSIGNED;
	  }
	  else return -1;
	}
      }
      /* before "sscanf(str+8, "%i %n", &im->wdim, &n) != 1"
	 was used. 
	 However the man said 
         ...
	 n      Nothing is expected; instead, the number of charac­
              ters consumed thus far from  the  input  is  stored
              through  the  next pointer, which must be a pointer
              to int.  This is not a conversion, although it  can
              be  suppressed  with  the  *  flag.  The C standard
              says: `Execution of a %n directive does not  incre­
              ment  the  assignment count returned at the comple­
              tion of execution' but  the  Corrigendum  seems  to
              contradict  this.  Probably  it is wise not to make
              any assumptions on the effect of %n conversions  on
              the return value.
	 ...
	 Thus I change it. It was yielding a RETURN_FAILURE with 
	 insight (GM).
      */
      else if(!strncmp(str, "PIXSIZE=", 8)) {
	if(sscanf(str+8, "%u", &im->wdim) != 1) return -1;
	if(im->wdim != 8 && im->wdim != 16 && im->wdim != 32 &&
	   im->wdim != 64) return -1;
	
	if ( im->wdim <= 9 ) {
	  if(strncmp(str+8+1, " bits", 5)) return -1;
	}
	else if ( im->wdim <= 99 ) {
	  if(strncmp(str+8+2, " bits", 5)) return -1;
	}
	else {
	  return -1;
	}

	im->wdim >>= 3;
      }
      else if(!strncmp(str, "SCALE=", 6)) ;
      else if(!strncmp(str, "CPU=", 4)) {
	if(!strncmp(str+4, "decm", 4)) im->endianness = END_LITTLE;
	else if(!strncmp(str+4, "alpha", 5)) im->endianness = END_LITTLE;
	else if(!strncmp(str+4, "pc", 2)) im->endianness = END_LITTLE;
	else if(!strncmp(str+4, "sun", 3)) im->endianness = END_BIG;
	else if(!strncmp(str+4, "sgi", 3)) im->endianness = END_BIG;
	else return -1;
      }

      else if(!strncmp(str, "XO=", 3)) {
	if(sscanf(str+3, "%d", &im->cx) != 1) return -1;
      }
      else if(!strncmp(str, "YO=", 3)) {
	if(sscanf(str+3, "%d", &im->cy) != 1) return -1;
      }
      else if(!strncmp(str, "ZO=", 3)) {
	if(sscanf(str+3, "%d", &im->cz) != 1) return -1;
      }

      else if(!strncmp(str, "TX=", 3)) {
	if(sscanf(str+3, "%f", &im->tx) != 1) return -1;
      }
      else if(!strncmp(str, "TY=", 3)) {
	if(sscanf(str+3, "%f", &im->ty) != 1) return -1;
      }
      else if(!strncmp(str, "TZ=", 3)) {
	if(sscanf(str+3, "%f", &im->tz) != 1) return -1;
      }
      else if(!strncmp(str, "RX=", 3)) {
	if(sscanf(str+3, "%f", &im->rx) != 1) return -1;
      }
      else if(!strncmp(str, "RY=", 3)) {
	if(sscanf(str+3, "%f", &im->ry) != 1) return -1;
      }
      else if(!strncmp(str, "RZ=", 3)) {
	if(sscanf(str+3, "%f", &im->rz) != 1) return -1;
      }

      if(!fgetns(str, 257, im)) return -1;
    }

    /* parse user strings */
    im->nuser = nusr = 0;
    while(str[0] == '#' && strncmp(str, "##}", 3)) {
      addStringElement(&strl, str + 1);
      while(strlen(str) == 256) {
	if(!fgetns(str, 257, im)) return -1;
	concatStringElement(&strl, str);
      }
      nusr++;
      if(!fgetns(str, 257, im)) return -1;      
    }
    
    /* go to end of header */
    while(strncmp(str, "##}", 3)) {
      if(!fgetns(str, 257, im)) return -1;
    }
    

    /* check header validity */
    if(im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 &&
       im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 &&
       (im->wordKind == WK_FLOAT || (im->wordKind == WK_FIXED &&
				     im->sign != SGN_UNKNOWN)) &&
       im->endianness != END_UNKNOWN) {
      if(nusr > 0) {
	im->nuser = nusr;
	im->user = (char **) ImageIO_alloc(im->nuser * sizeof(char *));
	oel = NULL;
	for(el = strl.begin, n = 0; el != NULL; el = oel, n++) {
	  im->user[n] = el->string;
	  oel = el->next;
	  ImageIO_free(el);
	}
      }
      return 0;
    }
    else return -1;

  }