Index: /trunk/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- /trunk/Ohana/src/libfits/include/gfitsio.h	(revision 41473)
+++ /trunk/Ohana/src/libfits/include/gfitsio.h	(revision 41474)
@@ -214,6 +214,6 @@
 int     gfits_byteswap_zdata   	        PROTO((char *zdata, off_t Nzdata, int pixsize));
 int     gfits_compressed_data_pixsize   PROTO((char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions));
-int     gfits_uncompressed_data_pixsize PROTO((char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions));
-int     gfits_uncompressed_data_bitpix  PROTO((char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions));
+int     gfits_uncompressed_data_pixsize PROTO((char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions, int rice_use_bitpix));
+int     gfits_uncompressed_data_bitpix  PROTO((char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions, int rice_use_bitpix));
 int     gfits_vartable_heap_pixsize     PROTO((char format));
 int     gfits_cmptype_valid             PROTO((char *cmptype));
Index: /trunk/Ohana/src/libfits/matrix/F_compress_M.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_compress_M.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/matrix/F_compress_M.c	(revision 41474)
@@ -76,11 +76,4 @@
   if (!gfits_modify (theader, "ZCMPTYPE", "%s", 1, zcmptype)) ESCAPE;
 
-  // define compression-specific keywords, update header as needed.
-  if (!strcasecmp(zcmptype, "GZIP_1") || !strcasecmp(zcmptype, "GZIP_2")) {
-    if ((header[0].bitpix == -32) || (header[0].bitpix == -64)) {
-      if (!gfits_modify (theader, "ZQUANTIZ", "%s", 1, "NONE")) ESCAPE;
-    }
-  }
-
   if (!gfits_modify_alt (theader, "ZSIMPLE", "%t", 1, TRUE)) ESCAPE;
   // gfits_modify (header, "ZTENSION", "%s", 1, exttype);
@@ -124,4 +117,11 @@
   int oblank = 32767;
   // gfits_modify (header, "BLANK", "%d", 1, oblank);
+
+  // define compression-specific keywords, update header as needed.
+  if (!strcasecmp(zcmptype, "GZIP_1") || !strcasecmp(zcmptype, "GZIP_2")) {
+    if ((header[0].bitpix == -32) || (header[0].bitpix == -64)) {
+      if (!gfits_modify (theader, "ZQUANTIZ", "%s", 1, "NONE")) ESCAPE;
+    }
+  }
 
 # if (0)
@@ -159,8 +159,12 @@
   unsigned long int max_tile_size = gfits_imtile_maxsize (matrix, ztile);
 
-  // size of a pixel in the raw pixel buffer (before compression)
-  int raw_pixsize = gfits_uncompressed_data_pixsize (zcmptype, header[0].bitpix, NULL, NULL, 0);
-  int raw_bitpix  = gfits_uncompressed_data_bitpix (zcmptype, header[0].bitpix, NULL, NULL, 0);
+  // size of a pixel in the compressed data (cmp_pixsize), used for byteswap below
   int cmp_pixsize = gfits_compressed_data_pixsize (zcmptype, header[0].bitpix, NULL, NULL, 0);
+
+  // size of a pixel in the raw pixel buffer (before compression) (last option says RICE uses header.bitpix)
+  int raw_pixsize = gfits_uncompressed_data_pixsize (zcmptype, header[0].bitpix, NULL, NULL, 0, TRUE);
+
+  // we also need the bitpix value for the raw uncompressed buffer to distinguish int and floats
+  int raw_bitpix  = gfits_uncompressed_data_bitpix (zcmptype, header[0].bitpix, NULL, NULL, 0, TRUE);
 
   // define compression-specific keywords, update header as needed.
@@ -237,15 +241,10 @@
     }
 
-    // GZIP_1 is swapped before compression; GZIP_2 implies swapping.  All other
-    // compression modes require swapping after compression (compresssion & decompression
-    // operate on native ENDIAN)
-    if (strcasecmp(zcmptype, "NONE_2") && // strcasecmp(zcmptype, "NONE") && 
-	strcasecmp(zcmptype, "GZIP_1") && 
-	strcasecmp(zcmptype, "GZIP_2") && 
-	strcasecmp(zcmptype, "RICE_1") && 
-	strcasecmp(zcmptype, "RICE_ONE")) {
-      // Nzdata is number of bytes
-      if (!gfits_byteswap_zdata (zdata, Nzdata, cmp_pixsize)) ESCAPE;
-    }
+    // BYTESWAP the compressed data after compressing.  Compression algorithms which do
+    // not need to byteswap here return 1 for cmp_pixsize.  GZIP_1 is swapped before
+    // compression; GZIP_2 implies swapping.  All other compression modes require swapping
+    // after compression (the compresssion & decompression functions operate on native
+    // ENDIAN data values).
+    if (!gfits_byteswap_zdata (zdata, Nzdata, cmp_pixsize)) ESCAPE;
 
     if (VERBOSE_DUMP && (i == 0)) {
Index: /trunk/Ohana/src/libfits/matrix/F_compress_data.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_compress_data.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/matrix/F_compress_data.c	(revision 41474)
@@ -120,5 +120,5 @@
 
     if (status) {
-      fprintf (stderr, "error in hdecompress\n");
+      fprintf (stderr, "error in hcompress\n");
       return (FALSE);
     }
Index: /trunk/Ohana/src/libfits/matrix/F_compress_utils.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_compress_utils.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/matrix/F_compress_utils.c	(revision 41474)
@@ -104,4 +104,5 @@
   // fprintf (stderr, "swapping %d bytes in pix of size %d bytes...\n", Nzdata, pixsize);
   switch (pixsize) {
+    case 0:
     case 1:
       break;
@@ -186,5 +187,49 @@
 }
 
-int gfits_uncompressed_data_pixsize (char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions) {
+// the size of the compressed data pixels, needed to perform swaps
+int gfits_compressed_data_pixsize (char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions) {
+
+  // NONE should be swapped to mimic swapping types
+  if (!strcasecmp(cmptype, "NONE") || !strcasecmp(cmptype, "NONE_1")) {
+    if (out_bitpix ==   8) return (1);
+    if (out_bitpix ==  16) return (2);
+    if (out_bitpix ==  32) return (4);
+    if (out_bitpix == -32) return (4);
+    if (out_bitpix == -64) return (8);
+    return (1);
+  }
+
+  // GZIP_1, GZIP_2 should not be swapped after compression / before decompression
+  if (!strcasecmp(cmptype, "GZIP_1") || 
+      !strcasecmp(cmptype, "GZIP_2") || 
+      !strcasecmp(cmptype, "NONE_2")) {
+    if (out_bitpix ==   8) return (1);
+    if (out_bitpix ==  16) return (1);
+    if (out_bitpix ==  32) return (1);
+    if (out_bitpix == -32) return (1);
+    if (out_bitpix == -64) return (1);
+    return (1);
+  }
+
+  // RICE_1 should not be swapped after compression / before decompression
+  if (!strcasecmp(cmptype, "RICE_1") ||
+      !strcasecmp(cmptype, "RICE_ONE")) {
+    return (1);
+  }
+
+  // PLIO_1 always results in 4-byte ints (not 2 byte ints?)
+  if (!strcasecmp(cmptype, "PLIO_1")) {
+    return (4);
+  }
+
+  if (!strcasecmp(cmptype, "HCOMPRESS_1")) {
+    if (out_bitpix == 8)  return (4);
+    if (out_bitpix == 16) return (4);
+    return (8);
+  }
+  return (0);
+}
+
+int gfits_uncompressed_data_pixsize (char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions, int rice_use_bitpix) {
 
   int i, Nbyte;
@@ -207,4 +252,10 @@
   if (!strcasecmp(cmptype, "RICE_1") ||
       !strcasecmp(cmptype, "RICE_ONE")) {
+    // on compression, user may set BYTEPIX based on header.bitpix:
+    if (rice_use_bitpix) {
+      if (out_bitpix ==   8) return (1);
+      if (out_bitpix ==  16) return (2);
+      if (out_bitpix ==  32) return (4);
+    }
     // if BYTEPIX option is specified, use that for Nbyte
     for (i = 0; i < Noptions; i++) {
@@ -214,8 +265,5 @@
       }
     }
-    if (out_bitpix ==   8) return (1);
-    if (out_bitpix ==  16) return (2);
-    if (out_bitpix ==  32) return (4);
-    return (4);
+    return (4); // RICE_1 default is 4 byte int if BYTEPIX undefined (White et al 6.2)
   }
 
@@ -233,60 +281,5 @@
 }
 
-int gfits_compressed_data_pixsize (char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions) {
-
-  int i, Nbyte;
-
-  // NONE should be swapped to mimic swapping types
-  if (!strcasecmp(cmptype, "NONE") || !strcasecmp(cmptype, "NONE_1")) {
-    if (out_bitpix ==   8) return (1);
-    if (out_bitpix ==  16) return (2);
-    if (out_bitpix ==  32) return (4);
-    if (out_bitpix == -32) return (4);
-    if (out_bitpix == -64) return (8);
-    return (1);
-  }
-
-  // GZIP_1, GZIP_2 should not be swapped after compression
-  if (!strcasecmp(cmptype, "GZIP_1") || 
-      !strcasecmp(cmptype, "GZIP_2") || 
-      !strcasecmp(cmptype, "NONE_2")) {
-    if (out_bitpix ==   8) return (1);
-    if (out_bitpix ==  16) return (1);
-    if (out_bitpix ==  32) return (1);
-    if (out_bitpix == -32) return (1);
-    if (out_bitpix == -64) return (1);
-    return (1);
-  }
-
-  // RICE_1 must operate on integer pixels
-  if (!strcasecmp(cmptype, "RICE_1") ||
-      !strcasecmp(cmptype, "RICE_ONE")) {
-    // if BYTEPIX option is specified, use that for Nbyte
-    for (i = 0; i < Noptions; i++) {
-      if (!strcmp(optname[i], "BYTEPIX")) {
-	Nbyte = atoi (optvalue[i]);
-	return (Nbyte);
-      }
-    }
-    if (out_bitpix ==   8) return (1);
-    if (out_bitpix ==  16) return (2);
-    if (out_bitpix ==  32) return (4);
-    return (4);
-  }
-
-  // PLIO_1 always results in 4-byte ints (not 2 byte ints?)
-  if (!strcasecmp(cmptype, "PLIO_1")) {
-    return (4);
-  }
-
-  if (!strcasecmp(cmptype, "HCOMPRESS_1")) {
-    if (out_bitpix == 8)  return (4);
-    if (out_bitpix == 16) return (4);
-    return (8);
-  }
-  return (0);
-}
-
-int gfits_uncompressed_data_bitpix (char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions) {
+int gfits_uncompressed_data_bitpix (char *cmptype, int out_bitpix, char **optname, char **optvalue, int Noptions, int rice_use_bitpix) {
 
   int i, Nbyte;
@@ -304,4 +297,9 @@
   if (!strcasecmp(cmptype, "RICE_1") ||
       !strcasecmp(cmptype, "RICE_ONE")) {
+    if (rice_use_bitpix) {
+      if (out_bitpix ==   8) return (out_bitpix);
+      if (out_bitpix ==  16) return (out_bitpix);
+      if (out_bitpix ==  32) return (out_bitpix);
+    }
     // if BYTEPIX option is specified, use that for Nbyte
     for (i = 0; i < Noptions; i++) {
@@ -311,7 +309,4 @@
       }
     }
-    if (out_bitpix ==   8) return (out_bitpix);
-    if (out_bitpix ==  16) return (out_bitpix);
-    if (out_bitpix ==  32) return (out_bitpix);
     return (32);
   }
Index: /trunk/Ohana/src/libfits/matrix/F_uncompress_M.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_uncompress_M.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/matrix/F_uncompress_M.c	(revision 41474)
@@ -40,4 +40,13 @@
     gfits_modify (header, NAME, TYPE, 1, OUT); }
 
+# define DUMP_ROWBYTES(BUF, INFO)	       \
+  if (VERBOSE_DUMP && (row == 0)) {	       \
+    int k;				       \
+    fprintf (stderr, "%s: ", INFO);	       \
+    for (k = 0; k < 64; k++) {		       \
+      fprintf (stderr, "%02hhx", BUF[k]);    \
+      if (k % 4 == 3) fprintf (stderr, " ");   \
+    } fprintf (stderr, "\n"); }
+
 int gfits_uncompress_image (Header *header, Matrix *matrix, FTable *ftable) {
 
@@ -97,4 +106,5 @@
   } else {
     gfits_delete (header, "ZTILE1", 1);
+    // if ZTILE1 exists, all ZTILEn must exist:
     for (axis = 1; axis < header->Naxes; axis++) {
       snprintf (key, 10, "ZTILE%d", axis + 1); 
@@ -127,13 +137,18 @@
   }
 
-  // XXX get ZMASKCMP 
-  int zsimple, have_zsimple;
-  int have_ztension;
+  // check for ZMASKCMP (not yet supported 2021.01.23)
+  char zmaskcmp[81];
+  int have_zmaskcmp = gfits_scan (header, "ZMASKCMP", "%s", 1, zmaskcmp);
+  if (have_zmaskcmp) {
+    fprintf (stderr, "null pixels were compressed with %s, not implemented in Ohana\n", zmaskcmp);
+    ESCAPE;
+  }
 
   // NOTE target of %t must be int length
-  have_zsimple  = gfits_scan_alt (header, "ZSIMPLE", "%t", 1, &zsimple);
-  have_ztension = gfits_scan (header, "ZTENSION", "%s", 1, exttype);
-
-  // this is a very bogus case: we cannot have both keywords
+  int zsimple;
+  int have_zsimple  = gfits_scan_alt (header, "ZSIMPLE", "%t", 1, &zsimple);
+  int have_ztension = gfits_scan (header, "ZTENSION", "%s", 1, exttype);
+
+  // this is a bogus case: we cannot have both keywords
   if (have_zsimple && have_ztension) ESCAPE;
 
@@ -179,4 +194,5 @@
     }
   } else {
+    // if this is a PHU (whether or not ZSIMPLE is present), PCOUNT & GCOUNT must be basic (0,1)
     header->pcount = 0;
     header->gcount = 1;
@@ -188,18 +204,12 @@
   MOD_KEYWORD ("ZDATASUM", "DATASUM",  "%s", datasum,         datasum);
 
-  zscale = 1;
-  gfits_scan (header, "ZSCALE", "%f", 1, &zscale);
-
-  zblank = 32767;
-  gfits_scan (header, "ZBLANK", "%d", 1, &zblank);
-
-  oblank = 32767;
-  gfits_scan (header, "BLANK", "%d", 1, &oblank);
-
-  zzero = 0;
-  gfits_scan (header, "ZZERO", "%f", 1, &zzero);
+  // get other basic keywords (default values supplied)
+  zscale = 1;      gfits_scan (header, "ZSCALE", "%f", 1, &zscale);
+  zblank = 32767;  gfits_scan (header, "ZBLANK", "%d", 1, &zblank);
+  oblank = 32767;  gfits_scan (header, "BLANK", "%d", 1, &oblank);
+  zzero = 0;       gfits_scan (header, "ZZERO", "%f", 1, &zzero);
 
   // find the COMPRESSED_DATA column (format should be 1PB, 1PI, 1PJ)
-  // is it required that this be the only column?
+  // XXX is it required that this be the only column? -- not if ZMASKCMP exists (not yet supported)
   int colnum;
   for (colnum = 1; TRUE; colnum++) {
@@ -242,15 +252,22 @@
 
   // heapdata.pixsize : zdef.format
-  // zdata.pixsize : depends on compression
-  // odata.pixsize : depends on compression
-  // idata.pixsize : header.bitpix
+  // zdata.pixsize : depends on compression method (cmp_pixsize below)
+  // odata.pixsize : depends on compression method (raw_pixsize below)
+  // idata.pixsize : depends on header.bitpix
 
   // size of an element in the vartable heap section
   // zdata_pixsize = gfits_vartable_heap_pixsize (zdef.format); XXX
 
-  // size of a pixel in the output from the decompression routine
+  // depending on the compression method, the data may need to be byteswapped either before
+  // or after uncompression:
+
+  // size of a pixel in the compressed data (cmp_pixsize), used for byteswap below
   int cmp_pixsize = gfits_compressed_data_pixsize (cmptype, header[0].bitpix, optname, optvalue, Noptions);
-  int raw_bitpix  = gfits_uncompressed_data_bitpix (cmptype, header[0].bitpix, optname, optvalue, Noptions);
-  int raw_pixsize = gfits_uncompressed_data_pixsize (cmptype, header[0].bitpix, optname, optvalue, Noptions);
+
+  // size of a pixel in the raw uncomprssed buffer (raw_pixsize) after uncompression (last option says RICE ignores bitpix)
+  int raw_pixsize = gfits_uncompressed_data_pixsize (cmptype, header[0].bitpix, optname, optvalue, Noptions, FALSE);
+
+  // we also need the bitpix value for the raw uncompressed buffer to distinguish int and floats
+  int raw_bitpix  = gfits_uncompressed_data_bitpix (cmptype, header[0].bitpix, optname, optvalue, Noptions, FALSE);
 
   // size of a pixel in the final image (not needed)
@@ -261,16 +278,9 @@
   ALLOCATE (out, char, Nout_alloc);
 
-  off_t row;
-
-  if (VERBOSE_DUMP) { 
-    int k;
-    fprintf (stderr, "unc tbl: "); 
-    for (k = 0; k < 64; k++) { fprintf (stderr, "%02hhx", ftable->buffer[k]); if (k % 4 == 3) fprintf (stderr, " "); } 
-    fprintf (stderr, "\n");
-  }
-
   // uncompress the data
   Nzrows = ftable->header->Naxis[1];
-  for (row = 0; row < Nzrows; row++) {
+  for (off_t row = 0; row < Nzrows; row++) {
+
+    DUMP_ROWBYTES (ftable->buffer, "tbl dat");
 
     // expected output size for this tile
@@ -280,40 +290,18 @@
     if (!zdata) ESCAPE;
 
-    if (VERBOSE_DUMP && (row == 0)) {
-      int k;
-      fprintf (stderr, "unc dat: "); 
-      for (k = 0; k < 64; k++) { fprintf (stderr, "%02hhx", zdata[k]); if (k % 4 == 3) fprintf (stderr, " "); } 
-      fprintf (stderr, "\n");
-    }
-
-    if (strcasecmp(cmptype, "NONE_2") && // strcasecmp(cmptype, "NONE") && 
-	strcasecmp(cmptype, "GZIP_1") && 
-	strcasecmp(cmptype, "GZIP_2") && 
-	strcasecmp(cmptype, "RICE_1") && 
-	strcasecmp(cmptype, "RICE_ONE")) {
-      // Nzdata is number of bytes
-      if (!gfits_byteswap_zdata (zdata, Nzdata, cmp_pixsize)) ESCAPE;
-    }
-
-    if (VERBOSE_DUMP && (row == 0)) {
-      int k;
-      fprintf (stderr, "unc SWP: "); 
-      for (k = 0; k < 64; k++) { fprintf (stderr, "%02hhx", zdata[k]); if (k % 4 == 3) fprintf (stderr, " "); } 
-      fprintf (stderr, "\n");
-      fprintf (stderr, "Nout  : %lu -> ", Nout);
-    }
+    DUMP_ROWBYTES (zdata, "cmp dat");
+
+    // byteswap the compressed data before uncompressing.
+    // compression algorithms which do not need to byteswap here return 1 for cmp_pixsize
+    if (!gfits_byteswap_zdata (zdata, Nzdata, cmp_pixsize)) ESCAPE;
+
+    DUMP_ROWBYTES (zdata, "cmp swp");
     
     // gfits_uncompress_data uncompresses from zdata to the temporary output buffer which must be allocated
-    // XXX the tile must not be > 2GB
-    // Nout going in is number of bytes 
+    // Note: the tile must not be > 2GB
+    // Nout going in is the expected number of bytes 
     if (!gfits_uncompress_data ((char *)zdata, Nzdata, cmptype, optname, optvalue, Noptions, out, &Nout, Nout_alloc, raw_pixsize)) ESCAPE;
 
-    if (VERBOSE_DUMP && (row == 0)) {
-      int k;
-      fprintf (stderr, "%lu\n", Nout);
-      fprintf (stderr, "unc swp: "); 
-      for (k = 0; k < 64; k++) { fprintf (stderr, "%02hhx", out[k]); if (k % 4 == 3) fprintf (stderr, " "); } 
-      fprintf (stderr, "\n");
-    }
+    DUMP_ROWBYTES (out, "unc swp");
     
     if (!strcasecmp(cmptype, "GZIP_1")) {
@@ -322,10 +310,5 @@
     }
     
-    if (VERBOSE_DUMP && (row == 0)) {
-      int k;
-      fprintf (stderr, "unc raw: "); 
-      for (k = 0; k < 64; k++) { fprintf (stderr, "%02hhx", out[k]); if (k % 4 == 3) fprintf (stderr, " "); } 
-      fprintf (stderr, "\n");
-    }
+    DUMP_ROWBYTES (out, "unc raw");
 
     // copy the uncompressed pixels into their correct locations 	    
@@ -336,10 +319,5 @@
     }
 
-    if (VERBOSE_DUMP && (row == 0)) {
-      int k;
-      fprintf (stderr, "unc mat: "); 
-      for (k = 0; k < 64; k++) { fprintf (stderr, "%02hhx", matrix->buffer[k]); if (k % 4 == 3) fprintf (stderr, " "); } 
-      fprintf (stderr, "\n");
-    }
+    DUMP_ROWBYTES (matrix->buffer, "out raw");
 
     // update the tile counters, carrying to the next dimension if needed
@@ -370,5 +348,6 @@
 }
 
-// bitpix is the input data size/type
+// raw_bitpix is the data size/type for the temporary buffer of uncompressed data
+// matrix->bitpix is the data size/type of the output image data
 int gfits_distribute_data (Matrix *matrix, char *raw, unsigned long int Nraw, int raw_bitpix, int *otile, int oblank, unsigned long int *ztile, int zblank, float zscale, float zzero) {
 
@@ -514,6 +493,10 @@
 }
 
-// bitpix is the input data size/type
+// raw_bitpix is the data size/type for the temporary buffer of uncompressed data
+// matrix->bitpix is the data size/type of the output image data
+// The gzip2 algorithm organizes the compressed data in groups by significant byte sequence (most significant byte of all pixels first, etc).
+// gfits_distribute_gzp2 needs to shuffle the bytes back into the correct location in the tile.
 int gfits_distribute_gzp2 (Matrix *matrix, char *raw, unsigned long int Nraw, int raw_bitpix, int *otile, int oblank, unsigned long int *ztile, int zblank, float zscale, float zzero) {
+  // unused parameters are supplied to make this function have the same API as gfits_distribute_data()
   OHANA_UNUSED_PARAM(oblank);
   OHANA_UNUSED_PARAM(zblank);
Index: /trunk/Ohana/src/libfits/matrix/F_uncompress_data.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_uncompress_data.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/matrix/F_uncompress_data.c	(revision 41474)
@@ -5,4 +5,10 @@
 
 # define ESCAPE(RET) { fprintf (stderr, "gzip error in %s @ %s:%d\n", __func__, __FILE__, __LINE__); return (RET); }
+
+/* This function uncompresses the data in 'zdata' into the pre-allocated output buffer 'outdata'.
+   The compression algorithm is chosen based on 'cmptype', with options specified by 'optname, optvalue, Nopt'
+   zdata : input compressed data, Nzdata : number of compressed BYTES
+   outdata : output buffer, Nout : number of actual output PIXELS, Nout_alloc : number of allocated bytes in the buffer, out_pixsize : bytes per output pixel
+ */
 
 int gfits_uncompress_data (char *zdata, unsigned long Nzdata, char *cmptype, char **optname, char **optvalue, int Nopt, char *outdata, unsigned long int *Nout, unsigned long int Nout_alloc, int out_pixsize) {
Index: /trunk/Ohana/src/libfits/table/F_get_column.c
===================================================================
--- /trunk/Ohana/src/libfits/table/F_get_column.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/table/F_get_column.c	(revision 41474)
@@ -403,24 +403,33 @@
   if (!strcmp (type, "int")) {
     ALLOCATE (array, char, Ny*4);
-    Pout = array;
-    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+    int *tmpPtr = (int *)array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, tmpPtr ++) {
       memcpy (line, Pin, Nval*Nbytes);
-      sscanf (line, cformat, (int *)Pout);
+      sscanf (line, "%d", tmpPtr);
+      // fprintf (stderr, "test: %d %d\n", Nscan, tmpValue);
     }
   }
   if (!strcmp (type, "int64_t")) {
     ALLOCATE (array, char, Ny*8);
-    Pout = array;
-    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=8) {
+    int64_t *tmpPtr = (int64_t *)array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, tmpPtr ++) {
       memcpy (line, Pin, Nval*Nbytes);
-      sscanf (line, "%" PRId64, (int64_t *)Pout);
+      sscanf (line, "%" PRId64, tmpPtr);
     }
   }
   if (!strcmp (type, "float")) {
     ALLOCATE (array, char, Ny*4);
-    Pout = array;
-    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+    float *tmpPtr = (float *) array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, tmpPtr ++) {
       memcpy (line, Pin, Nval*Nbytes);
-      sscanf (line, cformat, (float *)Pout);
+      sscanf (line, "%e", tmpPtr);
+    }
+  }
+  if (!strcmp (type, "double")) {
+    ALLOCATE (array, char, Ny*8);
+    double *tmpPtr = (double *) array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, tmpPtr++) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%le", tmpPtr);
     }
   }
Index: /trunk/Ohana/src/libfits/table/F_table_format.c
===================================================================
--- /trunk/Ohana/src/libfits/table/F_table_format.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/table/F_table_format.c	(revision 41474)
@@ -92,5 +92,5 @@
 int gfits_table_format (char *format, char *type, int *Nval, int *Nbytes) {
 
-  char Fchar, Size[80], Type;
+  char Fchar, Size[80];
   int Nv;
 
@@ -107,6 +107,7 @@
   }
   
-  Type = 'x';
-  if (Fchar == 'D') { *Nbytes = 1;  strcpy (type, "double"); Type = 'e'; *Nval = Nv; }
+  int isLong = FALSE;
+  char Type = 'x';
+  if (Fchar == 'D') { *Nbytes = 1;  strcpy (type, "double"); Type = 'e'; *Nval = Nv; isLong = TRUE; }
   if (Fchar == 'E') { *Nbytes = 1;  strcpy (type, "float");  Type = 'e'; *Nval = Nv; }
   if (Fchar == 'F') { *Nbytes = 1;  strcpy (type, "float");  Type = 'f'; *Nval = Nv; }
@@ -115,5 +116,15 @@
   if (!*Nbytes) { return (FALSE); }
   
-  sprintf (format, "%%-%s%c", Size, Type); // NOTE: this line is not used 
+  if (0) {
+    // this format is appropriate for scanning, but not printing
+    if (isLong) {
+      sprintf (format, "%%%sl%c", Size, Type);
+    } else {
+      sprintf (format, "%%%s%c", Size, Type);
+    }
+  }
+  
+  // this format is appropriate for printing, but not scanning
+  sprintf (format, "%%-%s%c", Size, Type);
 
   return (TRUE);
Index: /trunk/Ohana/src/libfits/test/compress.sh
===================================================================
--- /trunk/Ohana/src/libfits/test/compress.sh	(revision 41473)
+++ /trunk/Ohana/src/libfits/test/compress.sh	(revision 41474)
@@ -1,3 +1,22 @@
 input tap.dvo
+
+## NOTE: in order to run this test suite, you must have a modern version of fpack / funpack.
+## The IPP version included in the build tree (3100-p5) does not have support for gzip2 in fpack.
+
+## Acceptable versions can be obtained by downloading a current copy
+## of CFITSIO (https://heasarc.gsfc.nasa.gov/fitsio/).
+
+## To avoid installing the library or funpack/fpack in your psconfig
+## tree, only build the code locally and do NOT install.  
+
+## in the cfitsio directory, edit the Makefile with the following changes:
+
+## LDFLAGS_BIN =	-g -O2 -Wl,-rpath,${CFITSIO_LIB} -static
+## CFLAGS =	-g -Dg77Fortran -fPIC
+## (comment out the old versions)
+
+## run psconfigure, make, make fpack funpack
+
+## after building these (static) binaries, link them into this test directory
 
 macro tests
@@ -5,4 +24,7 @@
   test_table_all_rnd
 end
+
+$FPACK = ./fpack
+$FUNPACK = ./funpack
 
 macro test_image_all 
@@ -53,11 +75,12 @@
 
  if ($cmpmode == GZIP_1)
-   exec fpack -q 0 -g -S test.raw.fits > test.fpk.fits
+   ## mana does not (yet) handle non-zero quantization 
+   exec $FPACK -q 0 -g -S test.raw.fits > test.fpk.fits
  end
  if ($cmpmode == GZIP_2)
-   exec fpack -q 0 -g2 -S test.raw.fits > test.fpk.fits
+   exec $FPACK -q 0 -g2 -S test.raw.fits > test.fpk.fits
  end
  if ($cmpmode == RICE_1)
-   exec fpack -r -S test.raw.fits > test.fpk.fits
+   exec $FPACK -r -S test.raw.fits > test.fpk.fits
  end
  # echo "load fpack version"
@@ -68,11 +91,11 @@
  tapOK {$SIGMA      < 0.001} "read fpack $cmpmode $bitpix (SIGMA = $SIGMA)"
 
- if ($cmpmode == RICE_1_0) 
-   echo "*** funpack fails on RICE_1 ****"
-   return
- end
+ # if ($cmpmode == RICE_1_0) 
+ #   echo "*** funpack fails on RICE_1 ****"
+ #   return
+ # end
 
  # echo "run funpack on our version"
- exec funpack -S test.cmp.fits > test.fun.fits
+ exec $FUNPACK -S test.cmp.fits > test.fun.fits
  rd e test.fun.fits
  set d = x - e
@@ -213,5 +236,5 @@
  if (1)
    tapEXEC /bin/cp -f test.raw.tbl test.fpk.tbl
-   tapEXEC fpack -table -F test.fpk.tbl
+   tapEXEC $FPACK -table -F test.fpk.tbl
    
    data test.fpk.tbl
@@ -236,5 +259,5 @@
  # try to run fpack on ours
  tapEXEC /bin/cp -f test.cmp.tbl test.fun.tbl
- tapEXEC funpack -F test.fun.tbl
+ tapEXEC $FUNPACK -F test.fun.tbl
 
  data test.fun.tbl
@@ -403,5 +426,5 @@
  if (1)
    tapEXEC /bin/cp -f test.raw.tbl test.fpk.tbl
-   tapEXEC fpack -table -F test.fpk.tbl
+   tapEXEC $FPACK -table -F test.fpk.tbl
    
    data test.fpk.tbl
@@ -431,5 +454,5 @@
  # try to run fpack on ours
  tapEXEC /bin/cp -f test.cmp.tbl test.fun.tbl
- tapEXEC funpack -F test.fun.tbl
+ tapEXEC $FUNPACK -F test.fun.tbl
 
  data test.fun.tbl
Index: /trunk/Ohana/src/libfits/test/imagecomp.c
===================================================================
--- /trunk/Ohana/src/libfits/test/imagecomp.c	(revision 41473)
+++ /trunk/Ohana/src/libfits/test/imagecomp.c	(revision 41474)
@@ -3,10 +3,13 @@
 # include "tap_ohana.h"
 
+# define MEM_VERBOSE FALSE
+
 int test_compress (int bitpix, char *zcmptype);
 int test_compress_fullrange (int bitpix, char *zcmptype);
 int test_compress_fulltile (int bitpix, char *zcmptype);
 
-// char *cmptype[] = {"NONE", "NONE_2", "GZIP_1", "GZIP_2", "PLIO_1", "RICE_1", "RICE_ONE", "HCOMPRESS_1", NULL};
+// XXX FULL SET : char *cmptype[] = {"NONE", "NONE_2", "GZIP_1", "GZIP_2", "PLIO_1", "RICE_1", "RICE_ONE", "HCOMPRESS_1", NULL};
 char *cmptype[] = {"NONE", "NONE_1", "NONE_2", "GZIP_1", "GZIP_2", "RICE_1", "RICE_ONE", NULL};
+// XXX NOT WORKING: char *cmptype[] = {"HCOMPRESS_1", NULL};
 int bitpix[] = {8, 16, 32, -32, -64, 0};
 
@@ -31,5 +34,5 @@
       test_compress_fulltile (bitpix[j], cmptype[i]);
       test_compress_fullrange (bitpix[j], cmptype[i]);
-      ok (ohana_memcheck (TRUE), "no memory corruption");
+      ok (ohana_memcheck (MEM_VERBOSE), "no memory corruption");
     }
   }
@@ -43,5 +46,5 @@
       test_compress_fulltile (bitpix[j], cmptype[i]);
       test_compress_fullrange (bitpix[j], cmptype[i]);
-      ok (ohana_memcheck (TRUE), "no memory corruption");
+      ok (ohana_memcheck (MEM_VERBOSE), "no memory corruption");
     }
   }
@@ -55,5 +58,5 @@
       test_compress_fulltile (bitpix[j], cmptype[i]);
       test_compress_fullrange (bitpix[j], cmptype[i]);
-      ok (ohana_memcheck (TRUE), "no memory corruption");
+      ok (ohana_memcheck (MEM_VERBOSE), "no memory corruption");
     }
   }
@@ -138,4 +141,5 @@
   }     
   
+  // diag ("--- Image has a total of %d pixels of which %d are bad ---", NX*NY, Nbad);
   ok (!Nbad, "all image pixels match");
 
