Ejemplo n.º 1
0
int main(int argc, char **argv)
{
  int i, got;
  int maxrow=1024;
  Ev ev, ebuf=NULL;
  Fun fun, ofun;
  /* open file for reading */
  if( !(fun=FunOpen(argv[1], "r", NULL)) ){
    fprintf(stderr, "ERROR: can't open input funtools file: %s\n", argv[1]);
    return 1;
  }
  if( !(ofun=FunOpen(argv[2], "w", fun)) ){
    fprintf(stderr, "ERROR: can't open output funtools file: %s\n", argv[2]);
    return 1;
  }
  /* select columns to read (and data types to convert to) */
  got = FunColumnSelect(fun, sizeof(EvRec), "merge=update",
			"pi",     "J", "rw", FUN_OFFSET(Ev, pi),
			NULL);
  /* read and process events */
  while(ebuf=(void *)FunTableRowGet(fun, NULL, maxrow, NULL, &got) ){
    for(i=0; i<got; i++){
      ev = (Ev)ebuf+i;
      ev->pi = ev->pi + 1;
    }
    if( FunTableRowPut(ofun, ebuf, got, 0, NULL) != got ){
      fprintf(stderr, "ERROR: writing to funtools file: %s\n", argv[2]);
      return 1;
    }
    if( ebuf) free(ebuf);
  }
  /* close files */
  FunClose(ofun);
  FunClose(fun);
}
Ejemplo n.º 2
0
int main(int argc, char **argv)
{
  int i;
  Fun fun;
  struct WorldCoor *wcs;  /* WCS info */
  double x,y,ra,dec,xr,yr;

  if(argc == 1){
    fprintf(stderr, "usage: twcs iname\n");
    exit(1);
  }

  /* open Funtools file */
  /* Funopen makes initial WCS library call: wcs = wcsinit(header_string) */
  if( !(fun = FunOpen(argv[1], "r ", NULL)) ){
    fprintf(stderr, "ERROR can't open file: %s\n", argv[1]);
    exit(1);
  }

  /* get wcs structure */
  FunInfoGet(fun,FUN_WCS,&wcs,0);
  if( !wcs || !iswcs(wcs) ){
    fprintf(stderr,"No WCS data");
    return(1);
  }

  /* read input, convert pixels to wcs and back */
  while(1){
    fprintf(stdout,"\nInput x y: ");
    if(scanf("%lf %lf", &x, &y) != EOF){
      if(x <= -999)
	break;
      /* convert image pixels to sky coords */
      pix2wcs(wcs, x, y, &ra, &dec);
      fprintf(stdout,"Convert from pixels to ra,dec using pix2wcs()\n");
      fprintf(stdout, "x=%.10g y=%.10g -> ra=%.10g dec=%.10g\n",
	      x, y, ra, dec);
      /* convert sky coords to image pixels */
      fprintf(stdout,"Convert from ra,dec -> pixels using wcs2pix()\n");
      wcs2pix(wcs, ra, dec, &xr, &yr, &i);
      fprintf(stdout, "ra=%.10g dec=%.10g -> x=%.10g y=%.10g offscale=%d\n",
	      ra, dec, xr, yr, i);
    }
    else
      break;
  }

  /* clean up */
  /* FunClose makes final WCS library call: wcsfree(wcs) */
  FunClose(fun);
  return(0);
}
Ejemplo n.º 3
0
/* global definitions and init calls go here */
$GLOBAL

/* main program */
int main (int argc, char **argv)
{
  int c, i, got, total, rectype, start, stop, skip, args;
  int del=0;
  char *s;
  Fun fun, ofun;
  Row rowbuf, rowptr;
  Row cur, prev, next;
  $AUTO
  
  /* local definitions, followed by init calls go here */
  $LOCAL

  /* exit on gio errors */
  setgerror(1);

  /* avoid shared library problems by using "process" type for filtering */
  putenv("FILTER_PTYPE=process");

  /* process switch arguments */
  while ((c = getopt(argc, argv, "d")) != -1){
    switch(c){
    case 'd':
      del = 1;
      break;
    }
  }
  /* check for required arguments */
  args = argc - optind;
  /* make sure we have minimal arguments */
  if( args < $ARGS ){
    if( $ARGS == 1 )
      fprintf(stderr,
      "usage: [expr] | funcalc [-e expr] [-f file] iname\n");
    else
      fprintf(stderr,
      "usage: [expr] | funcalc [-e expr] [-f file] iname oname [cols]\n");
    goto error;
  }

  /* set rectype: determine whether we need prev,next records */
  rectype=$RECTYPE;

  /* get maxrow,if user-specified */
  if( (s=(char *)getenv("FUN_MAXROW")) != NULL )
    maxrow = atoi(s);
  /* make sure max row is large enough to handle prev, next */
  if( rectype & (REC_PREV|REC_NEXT) ) maxrow = MAX(3,maxrow);

  /* open input file */
  if( !(fun = FunOpen(argv[optind+0], "rc", NULL)) ){
      gerror(stderr, "could not FunOpen input file: %s\n", argv[optind+0]);
      goto error;
  }

  /* open the output FITS image, inheriting params from input */
  if( $ARGS > 1 ){
    if( !(ofun = FunOpen(argv[optind+1], "w", fun)) ){
      gerror(stderr, "could not FunOpen output file: %s\n", argv[optind+1]);
      goto error;
    }
  }

  /* select columns */
  FunColumnSelect(fun, sizeof(RowRec), "merge=replace", 
		  $SELECT
		  NULL);

  /* activate specified columns -- these will be written to the output file */
  if( args >= 3 )
    FunColumnActivate(fun, argv[optind+2], NULL);

  /* allocate space for rowbuf -- we will manage this buffer ourselves */
  rowbuf = (Row)calloc(maxrow, sizeof(RowRec));

  /*  no record read yet */
  total = 0;

  /* any user-defined calls before we enter the row loop go here */
  $BEFORE

  /* main loop -- get rows and process */
  while( 1 ){
    /* need prev record */
    if( rectype & REC_PREV ){
      /* no records yet: read new batch of records into start of rowbuf */
      if( total == 0 ){
        rowptr = rowbuf;
      }
      /* we have read records: move last record from last batch into first
	 new record and read new records after that */
      else{
        /* if we are accessing next, we did not actually process final record,
           therefore we do it now */
        if( rectype & REC_NEXT ){
          memcpy(rowbuf, rowbuf+(got-2), sizeof(RowRec)*2);
          rowptr = rowbuf+2;
        }
        /* not accessing next, so we just move last record processed */
        else{
          memcpy(rowbuf, rowbuf+(got-1), sizeof(RowRec));
          rowptr = rowbuf+1;
        }
      }
      /* start at 2nd record so as to have a valid prev */
      start = 1;
    }
    /* processing that does not require prev */
    else{
      rowptr = rowbuf;
      start = 0;
    }

    /* adjust maxrow to account for handling of prev record */
    skip = (rowptr - rowbuf)/sizeof(RowRec);

    /* read new rows */
    if( !FunTableRowGet(fun, rowptr, maxrow-skip, NULL, &got) )
      break;

    /* if we need access to next record, don't process the last one we read */
    if( rectype & REC_NEXT ){
      stop = got - 1;
    }
    /* processing that does not require acces to next, process as cur */
    else{
      stop = got;
    }

    /* process all rows */
    for(i=start; i<stop; i++){
      /* set up pointer to current row */
      cur = rowbuf+i;
      /* set up pointer to prev and next as needed */
      if( rectype & REC_PREV ) prev = rowbuf+(i-1);
      if( rectype & REC_NEXT ) next = rowbuf+(i+1);
      /* execute the expression */
      $EXPR
      /* write out this row with the new column */
      if( $ARGS > 1 )
        FunTableRowPut(ofun, (char *)cur, 1, i, NULL);
    }
    total += got;
  }

  /* any user-defined calls after we finish the row loop go here */
  $AFTER

  /* free row data */
  if( rowbuf ) free(rowbuf);

  /* clean up -- close output before input to perform flush automatically */
  if( $ARGS > 1 )
    FunClose(ofun);
  FunClose(fun);

  /* delete program if necessary */
  if( del ) unlink(argv[0]);
  return(0);

error:
  /* delete program if necessary */
  if( del ) unlink(argv[0]);
  return(1);
}
Ejemplo n.º 4
0
int main (int argc, char **argv)
{
  int i, got;
  int maxrow=MAXROW;
  double x=0.5;
  char *tmode;
  char *s;
  Fun fun, fun2;
  Ev ebuf, ev;

  /* exit on gio errors */
  setgerror(2);

  /* make sure we have minimal arguments */
  if( argc < 3 )
    gerror(stderr, "usage: %s iname oname [columns]\n", argv[0]);

  /* get maxrow,if user-specified */
  if( (s=(char *)getenv("FUN_MAXROW")) != NULL )
    maxrow = atoi(s);

  /* open input file */
  if( !(fun = FunOpen(argv[1], "rc", NULL)) )
    gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);

  /* open the output FITS image, inheriting params from input */
  if( !(fun2 = FunOpen(argv[2], "w", fun)) )
    gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);

  /* if we have "time2", read it, else create it */
  if( FunColumnLookup(fun, "tinc", 0, NULL, NULL, NULL, NULL, NULL, NULL) )
    tmode = "rw";
  else
    tmode = "w";

  FunColumnSelect(fun, sizeof(EvRec), "merge=replace",
		  "time",     "D", 	"r",    FUN_OFFSET(Ev, time),
		  "ntime",    "D", 	"rw",    FUN_OFFSET(Ev, ntime),
		  "tinc",     "D",      tmode,   FUN_OFFSET(Ev, tinc),
		  NULL);

  /* activate specified columns -- these will be written to the output file */
  if( argc >= 4 )
    FunColumnActivate(fun, argv[3], NULL);

  /* get rows -- let routine allocate the row array */
  while( (ebuf = (Ev)FunTableRowGet(fun, NULL, maxrow, NULL, &got)) ){
    /* process all rows */
    for(i=0; i<got; i++){
      /* point to the i'th row */
      ev = ebuf+i;
      ev->tinc += (i*sqrt(cos(x)*cos(x) + sin(x)*sin(x)));
      ev->ntime = ev->time + ev->tinc;
      /* write out row with the new columns */
      FunTableRowPut(fun2, (char *)ev, 1, i, NULL);
    }
    /* free row data */
    if( ebuf ) free(ebuf);
  }

  /* clean up -- close output before input to perform flush automatically */
  FunClose(fun2);
  FunClose(fun);
  return(0);
}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
  int c;
  int args;
  int offscl;
  int dim1, dim2;
  int ix, iy;
  int offset;
  int debug=0;
  int dowcs=1;
  int idx=0;
  char tbuf[SZ_LINE];
  double dval1, dval2;
  double dx, dy;
  double *dbuf;
  struct WorldCoor *wcs;
  Fun fun;

  /* process switch arguments */
  while( (c = getopt(argc, argv, "d")) != -1){
    switch(c){
    case 'd':
      debug = 1;
      break;
    case 'i':
      dowcs = 0;
      break;
    }
  }

  /* check for required arguments */
  args = argc - optind;
  if( args < 1 ){
    fprintf(stderr, "usage: %s iname -d -i\n", argv[0]);
    fprintf(stderr, "\n");
    fprintf(stderr, "where:\n");
    fprintf(stderr, "  -d\tprint out input and output position values\n");
    fprintf(stderr, "  -i\tinput values are image x,y (not ra,dec in deg)\n");
    fprintf(stderr, "\n");
    exit(1);
  }

  /* exit on gio errors */
  setgerror(2);

  /* open the input FITS file */
  if( !(fun = FunOpen(argv[optind], "r", NULL)) )
    gerror(stderr, "could not FunOpen input file: %s\n", argv[optind]);

  /* extract and bin the data section into a double float image buffer */
  if( !(dbuf = FunImageGet(fun, NULL, "bitpix=-64")) )
    gerror(stderr, "could not FunImageGet: %s\n", argv[1]);

  /* get required information from funtools structure */
  FunInfoGet(fun,
	     FUN_SECT_DIM1,	&dim1,
	     FUN_SECT_DIM2,	&dim2,
	     FUN_WCS, 		&wcs,
	     0);

  /* for each line in the contour file ... */
  while( fgets(tbuf, SZ_LINE, stdin) ){
    /* ignore comments */
    if( *tbuf == '#' )
      continue;
    /* blank lines means reset counter */
    if( *tbuf == '\n' ){
      fprintf(stdout, "\n");
      idx = 0;
      continue;
    }
    /* input contour values: ra, dec in degrees (or image coords if -i) */
    if(sscanf(tbuf, "%lf %lf", &dval1, &dval2) != 2){
      gerror(stderr, "invalid line in contour file: %s\n", tbuf);
    }
    /* convert input ra, dec to image x, y */
    if( dowcs ){
      wcs2pix(wcs, dval1, dval2, &dx, &dy, &offscl);
      /* make sure we are not off scale */
      if( offscl ){
	fprintf(stderr, "warning: wcs position is offscale: %s\n", tbuf);
	continue;
      }
    }
    else{
      dx = dval1;
      dy = dval2;
    }
    /* convert image values to integers */
    ix = (int)(dx+0.5);
    iy = (int)(dy+0.5);
    /* sanity checks -- must be inside the image */
    if( (ix < 1) || (ix > dim1) || (iy < 1) || (iy > dim2)){
      fprintf(stderr, "warning: image position off image: %s\n", tbuf);
      continue;
    }
    /* calculate offset into dbuf */
    offset = (iy-1)*dim1 + ix-1;
    /* write out the index and the pixel value at the image position */
    fprintf(stdout, "%d\t%f", idx, dbuf[offset]);
    /* debugging info, if necessary */
    if( debug ){
      fprintf(stdout, "\t %f %f\t%d %d", dval1, dval2, ix, iy);
    }
    /* finish off line */
    fprintf(stdout, "\n");
    /* bump to next index */
    idx++;
  }

  /* close output first so that flush happens automatically */
  FunClose(fun);
  if( dbuf ) free(dbuf);
  return(0);
}
Ejemplo n.º 6
0
int main(int argc, char **argv)
{
  int i;
  int got;
  int npha;
  char tbuf[SZ_LINE];
  Ev ebuf, ev, nev;
  Fun fun, fun2;

  /* make sure we have minimal arguments */
  if( argc < 3 ){
    fprintf(stderr, "usage: %s iname oname [columns]\n", argv[0]);
    exit(1);
  }

  /* exit on gio errors */
  setgerror(2);

  /* open input FITS file for reading, and allowing copy of other extensions */
  if( !(fun = FunOpen(argv[1], "rc", NULL)) )
    gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);

  /* look for the size of the phas vector */
  if( !FunColumnLookup(fun, "phas", 0, NULL, NULL, NULL, NULL, &npha, NULL) )
    gerror(stderr, "can't find phas column\n");

  /* open the output FITS image, inheriting params from input */
  if( !(fun2 = FunOpen(argv[2], "w", fun)) )
    gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);

  /* allocate a new row buffer, now that we know the size of phas */
  nev = (Ev)calloc(1, sizeof(EvRec));
  nev->phas = (int *)calloc(npha, sizeof(int));

  /* create format statement for the pha vector, @ means its a pointer */
  sprintf(tbuf, "@%dJ", npha);
  /* specify input columns we want brought into user space */
  FunColumnSelect(fun, sizeof(EvRec), "merge=replace",
		  "$x",   "D",  "rw", FUN_OFFSET(Ev, x),
		  "$y",   "D",  "rw", FUN_OFFSET(Ev, y),
		  "phas", tbuf, "rw", FUN_OFFSET(Ev, phas),
		  NULL);

  /* set columns to be written to the output file */
  if( argc >= 4 )
    FunColumnActivate(fun, argv[3], NULL);

  /* loop through rows and replicate */
  while( (ebuf=(Ev)FunTableRowGet(fun, NULL, MAXROW, NULL, &got)) ){
    for(i=0; i<got; i++){
      /* get pointer to the user info containing x,y, phas */
      ev = ebuf+i;
      /* generate a new rows (with new x, y, phas values) */
      Reverse(ev->x, ev->y, ev->phas,
	      &(nev->x), &(nev->y), nev->phas, npha);
      /* write this new row -- with the replacements from user space */
      FunTableRowPut(fun2, nev, 1, i, NULL);
    }
    if( ebuf ) free(ebuf);
  }

  /* free the new row */
  if( nev ){
    if( nev->phas ) free(nev->phas);
    free(nev);
  }
      
  /* close output before input so that funtools will copy the rest of the
     input extensions to the output (if such copy is requred) */
  FunClose(fun2);
  FunClose(fun);
  return(0);
}
Ejemplo n.º 7
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;
}