Ejemplo n.º 1
0
/* copy image section from input to putput, with binning */
int copyImageSection(fitsfile *ifptr, fitsfile *ofptr,
		     int *dims, double *cens, int bin, char *slice,
		     int *status)
{
  void *buf;
  char card[FLEN_CARD];
  char tbuf[SZ_LINE];
  int numkeys, nkey, bitpix, dtype;
  int start[2];
  int end[2];
  int naxis = 2;
  long nelements;
  long naxes[2];
  long fpixel[2] = {1,1};
  buf = getImageToArray(ifptr, dims, cens, bin, slice, start, end, &bitpix,
			status);
  if( !buf || *status ){
    fits_get_errstatus(*status, tbuf);
    fprintf(stderr, "ERROR: could not create section for output image: %s\n",
	    tbuf);
    return *status;
  }
  /* get image size and total number of elements */
  naxes[0] = (int)((end[0] - start[0] + 1) / bin);
  naxes[1] = (int)((end[1] - start[1] + 1) / bin);
  nelements = naxes[0] * naxes[1];
  /* convert bitpix to cfitio data type */
  switch(bitpix){
  case 8:
    dtype = TBYTE;
    break;
  case 16:
    dtype = TSHORT;
    break;
  case -16:
    dtype = TUSHORT;
    break;
  case 32:
    dtype = TINT;
    break;
  case 64:
    dtype = TLONGLONG;
    break;
  case -32:
    dtype = TFLOAT;
    break;
  case -64:
    dtype = TDOUBLE;
    break;
  default:
    fprintf(stderr, "ERROR: unknown data type for image section\n");
    return -1;
  }
  /* this code is modeled after cfitsio/cfileio.c/fits_copy_image_section() */
  fits_create_img(ofptr, bitpix, naxis, naxes, status);
  /* copy all other non-structural keywords from the input to output file */
  fits_get_hdrspace(ifptr, &numkeys, NULL, status);
  for(nkey=4; nkey<=numkeys; nkey++) {
    fits_read_record(ifptr, nkey, card, status);
    if (fits_get_keyclass(card) > TYP_CMPRS_KEY){
      /* write the record to the output file */
      fits_write_record(ofptr, card, status);
    }
  }
  if( *status > 0 ){
    fprintf(stderr,
	    "ERROR: can't copy header from input image to output section");
    return(*status);
  }
  /* write image to FITS file */
  fits_write_pix(ofptr, dtype, fpixel, nelements, buf, status);
  /* update LTM/TLV values in header */
  updateLTM(ifptr, ofptr,
	    (int)((end[0] + start[0]) / 2), (int)((end[1] + start[1]) / 2), 
	    (int)(end[0] - start[0] + 1), (int)(end[1] - start[1] + 1),
	    bin, 1);
  /* free up space */
  if( buf ){
    free(buf);
  }
  /* return status */
  return *status;
}
Ejemplo n.º 2
0
int main(int argc, char **argv)
{
  int c, i, j, got, args, jsonlen, istart;
  int odim1, odim2, blen, pad;
  int idim1=0, idim2=0, bitpix=0, ncard=0;
  int verbose=0;
  size_t totbytes, dlen;
  char tbuf[SZ_LINE];
  char *buf=NULL;
  char *jsonheader=NULL;
  char *iname=NULL, *oname=NULL;
  FILE *ofp=NULL;
  Optinfo optinfo;
#if HAVE_CFITSIO
  int status = 0;
  int n;
  int hdutype;
  int maxcard, morekeys;
  int dims[2] = {0, 0};
  int block = 1;
  void *dbuf;
  double d1, d2, d3, d4;
  double cens[2] = {0.0, 0.0};
  char *s;
  char *filter=NULL;
  char *evtlist = DEF_EVTLIST;
  char card[81];
  char s1[BUFLEN], s2[BUFLEN], s3[BUFLEN], s4[BUFLEN];
  fitsfile *fptr=NULL, *ofptr=NULL;
#elif HAVE_FUNTOOLS
  char *s=NULL;
  int dtype;
  Fun ifun=NULL, tfun=NULL;
#endif

  /* we want the args in the same order in which they arrived, and
     gnu getopt sometimes changes things without this */
  putenv("POSIXLY_CORRECT=true");

  /* process switch arguments */
  while ((c = getopt(argc, argv, "b:e:f:s:v")) != -1){
    switch(c){
    case 'b':
#if HAVE_CFITSIO
      block = atoi(optarg);
#else
      fprintf(stderr, "warning: -b switch only for cfitsio (ignoring)\n");
#endif
      break;
    case 'e':
#if HAVE_CFITSIO
      evtlist = optarg;
#else
      fprintf(stderr, "warning: -e switch only for cfitsio (ignoring)\n");
#endif
      break;
    case 'f':
#if HAVE_CFITSIO
      filter = optarg;
#else
      fprintf(stderr, "warning: -f switch only for cfitsio (ignoring)\n");
#endif
      break;
    case 's':
#if HAVE_CFITSIO
      s = strdup(optarg);
      if( strlen(s) > BUFLEN ) s[BUFLEN-1] = '\0';
      if( sscanf(s, "%[0-9.*] @ %[-0-9.*] , %[0-9.*] @ %[-0-9.*]%n",
		 s1, s2, s3, s4, &n) == 4){
	dims[0] = atof(s1);
	cens[0] = atof(s2);
	dims[1] = atof(s3);
	cens[1] = atof(s4);
      }  else if(sscanf(s, "%[-0-9.*] : %[-0-9.*] , %[-0-9.*] : %[-0-9.*]%n",
			s1, s2, s3, s4, &n) == 4){
	d1 = atof(s1);
	d2 = atof(s2);
	d3 = atof(s3);
	d4 = atof(s4);
	dims[0] = d2 - d1 + 1;
	cens[0] = dims[0] / 2;
	dims[1] = d4 - d3 + 1;
	cens[1] = dims[1] / 2;
      } else {
	fprintf(stderr, "warning: unknown arg for -s switch (ignoring)\n");
      }
      if( s ) free(s);
#else
      fprintf(stderr, "warning: -s switch only for cfitsio (ignoring)\n");
#endif
     break;
    case 'v':
      verbose++;
      break;
    }
  }

  /* check for required arguments */
  args = argc - optind;
  if( args < 2 ){
    fprintf(stderr, "usage: %s iname oname\n", argv[0]);
    exit(1);
  }
  iname = argv[optind++];
  oname = argv[optind++];

  /* optional info */
  if( !(optinfo = (Optinfo)calloc(sizeof(OptinfoRec), 1)) ){
    fprintf(stderr, "ERROR: can't allocate optional info rec\n");
    exit(1);
  }

  /* open the input FITS file */
#if HAVE_CFITSIO
  fptr = openFITSFile(iname, evtlist, &hdutype, &status);
  errchk(status);
#elif HAVE_FUNTOOLS
  if( !(ifun = FunOpen(iname, "r", NULL)) ){
    fprintf(stderr, "ERROR could not open input FITS file: %s (%s)\n", 
	    iname, strerror(errno));
    exit(1);
  }
#endif

  /* save the input filename in the png file */
  optinfo->fitsname = iname;

  /* open the output PGN file */
  if( !strcmp(oname, "-") || !strcmp(oname, "stdout") ){
    ofp = stdout;
  } else if( !(ofp = fopen(oname, "w")) ){
    fprintf(stderr, "ERROR: could not create output PNG file: %s (%s)\n", 
	    oname, strerror(errno));
    exit(1);
  }

#if HAVE_CFITSIO
  switch(hdutype){
  case IMAGE_HDU:
    // get image array
    dbuf = getImageToArray(fptr, NULL, NULL, &idim1, &idim2, &bitpix, &status);
    errchk(status);
    fits_get_hdrspace(fptr, &maxcard, &morekeys, &status);
    errchk(status);
    ofptr = fptr;
    break;
  default:
    ofptr = filterTableToImage(fptr, filter, NULL, dims, cens, block, &status);
    errchk(status);
    // get image array
    dbuf = getImageToArray(ofptr, NULL, NULL, &idim1, &idim2, &bitpix, &status);
    errchk(status);
    // get number of keys
    fits_get_hdrspace(ofptr, &maxcard, &morekeys, &status);
    errchk(status);
    break;
  }

#elif HAVE_FUNTOOLS
  /* copy the input fits header into a FITS image header */
  if( !(tfun = (Fun)calloc(1, sizeof(FunRec))) ){
      fprintf(stderr, "ERROR: could not create tfun struct\n");
      exit(1);
  }
  _FunCopy2ImageHeader(ifun, tfun);
  /* and save for storage in the png file */
  optinfo->fitsheader = (char *)tfun->header->cards;

  /* get image parameters. its safe to do this before calling image get
     so long as we don't change bitpix before that call */
  FunInfoGet(ifun,
	     FUN_SECT_BITPIX,  &bitpix,
	     FUN_SECT_DIM1,    &idim1,
	     FUN_SECT_DIM2,    &idim2,
	     0);
#endif

  /* convert FITS header into a json string */
  snprintf(tbuf, SZ_LINE-1, "{\"js9Protocol\": %s, ", JS9_PROTOCOL);
  scat(tbuf, &jsonheader);
  snprintf(tbuf, SZ_LINE-1, "\"js9Endian\": \"%s\", ", JS9_ENDIAN);
  scat(tbuf, &jsonheader);
  snprintf(tbuf, SZ_LINE-1, "\"cardstr\": \"");
  scat(tbuf, &jsonheader);
  // concat header cards into a single string
#if HAVE_CFITSIO
  while( ++ncard <= maxcard ){
    fits_read_record(ofptr, ncard, card, &status);
    errchk(status);
    // change " to '
    for(i=0; i<80; i++){
      if( card[i] == '"' ){
	card[i] = '\'';
      }
    }
    snprintf(tbuf, SZ_LINE-1, "%-80s", card);
    scat(tbuf, &jsonheader);
  }
#elif HAVE_FUNTOOLS
  while( (s = FunParamGets(tfun, NULL, ++ncard, NULL, &dtype)) ){
    for(i=0; i<80; i++){
      if( s[i] == '"' ){
	s[i] = '\'';
      }
    }
    scat(s, &jsonheader);
    if( s ) free(s);
  }
#endif
  // end with the number of cards
  snprintf(tbuf, SZ_LINE-1, "\", \"ncard\": %d}", ncard);
  scat(tbuf, &jsonheader);

  /* we want the image buffer to start on an 8-byte boundary, 
     so make jsonheader + null byte end on one */
  pad = 8 - (strlen(jsonheader) % 8) - 1;
  for(i=0; i<pad; i++){
    strcat(jsonheader, " ");
  }
  /* get final length of json header */
  jsonlen = strlen(jsonheader);

  /* total length of the header + null + image we are storing */
  blen = ABS(bitpix/8);
  dlen = (size_t)idim1 * (size_t)idim2 * blen;
  totbytes = jsonlen + 1 + dlen;

  /* all of this should now fit into the png image */
  /* somewhat arbitrarily, we use idim1 for odim1, and adjust odim2 to fit */
  odim1 = idim1;
  odim2 = (int)(((totbytes + odim1 - 1) / odim1) + (COLOR_CHANNELS-1)) / COLOR_CHANNELS;

  /* allocate buf to hold json header + null byte + RGB image */
  if( !(buf=calloc(COLOR_CHANNELS, odim1 * odim2)) ){
    fprintf(stderr, "ERROR: can't allocate image buf\n");
    exit(1);
  }

  /* move the json header into the output buffer */
  memmove(buf, jsonheader, jsonlen);
  /* add a null byte to signify end of json header */
  buf[jsonlen] = '\0';

  /* offset into image buffer where image starts, past header and null byte */
  istart = jsonlen + 1;

  /* debug output */
  if( verbose ){
    fprintf(stderr, 
    "idim=%d,%d (bitpix=%d jsonlen=%d istart=%d endian=%s) [%ld] -> odim=%d,%d [%d]\n", 
	    idim1, idim2, bitpix, jsonlen, istart, JS9_ENDIAN, totbytes, 
	    odim1, odim2, odim1 * odim2 * COLOR_CHANNELS);
  }

#if HAVE_CFITSIO
  /* move the json header into the output buffer */
  memmove(&buf[istart], dbuf, dlen);
#elif HAVE_FUNTOOLS
  /* extract and bin the data section into an image buffer */
  if( !FunImageGet(ifun, &buf[istart], NULL) ){
    fprintf(stderr, "ERROR: could not FunImageGet: %s\n", iname);
    exit(1);
  }
#endif

  /* debugging output to check against javascript input */
  if( verbose > 1 ){
    fprintf(stderr, "jsonheader: %s\n", jsonheader);
    for(j=0; j<idim2; j++){
      fprintf(stderr, "data #%d: ", j);
      for(i=0; i<idim1; i++){
	switch(bitpix){
	case 8:
	  fprintf(stderr, "%d ", 
		  *(unsigned char *)(buf + istart + ((j * idim1) + i) * blen));
	  break;
	case 16:
	  fprintf(stderr, "%d ", 
		  *(short *)(buf + istart + ((j * idim1) + i) * blen));
	  break;
	case -16:
	  fprintf(stderr, "%d ", 
		  *(unsigned short *)(buf + istart + ((j * idim1) + i) * blen));
	  break;
	case 32:
	  fprintf(stderr, "%d ",
		  *(int *)(buf + istart + ((j * idim1) + i) * blen));
	  break;
	case -32:
	  fprintf(stderr, "%.3f ",
		  *(float *)(buf + istart + ((j * idim1) + i) * blen));
	  break;
	case -64:
	  fprintf(stderr, "%.3f ", 
		  *(double *)(buf + istart + ((j * idim1) + i) * blen));
	  break;
	}
      }
      fprintf(stderr, "\n");
    }
    fprintf(stderr, "\n");
  }

  /* might have to swap to preferred endian for png creation */
  if( (!strncmp(JS9_ENDIAN, "l", 1) &&  is_bigendian()) ||
      (!strncmp(JS9_ENDIAN, "b", 1) && !is_bigendian()) ){
    swap_data(&buf[istart], idim1 * idim2, bitpix/8);
  }

  /* write the PNG file */
  got = writePNG(ofp, buf, odim1, odim2, optinfo);

  /* free up space */
  if( buf ) free(buf);
  if( optinfo ) free(optinfo);
  if( jsonheader ) free(jsonheader);

  /* close files */
#if HAVE_CFITSIO
  status = 0;
  if( ofptr && (ofptr != fptr) ) closeFITSFile(ofptr, &status);
  if( fptr ) closeFITSFile(fptr, &status);
  if( dbuf ) free(dbuf);
#elif HAVE_FUNTOOLS
  if( ifun ) FunClose(ifun);
  if( tfun ){
    FunClose(tfun);
    free(tfun);
  }
#endif
  if( ofp) fclose(ofp);

  /* return the news */
  return got;
}