Index: trunk/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- trunk/Ohana/src/libfits/include/gfitsio.h	(revision 15007)
+++ trunk/Ohana/src/libfits/include/gfitsio.h	(revision 15038)
@@ -126,4 +126,6 @@
 int   gfits_add_rows               PROTO ((FTable *, char *, int, int));
 char *gfits_table_print            PROTO ((FTable *,...));
+int   gfits_table_scale_data       PROTO ((FTable *ftable));
+int   gfits_table_scale_storage    PROTO ((FTable *ftable));
 
 /******************************* Matrix functions *************/
Index: trunk/Ohana/src/libfits/table/F_table_format.c
===================================================================
--- trunk/Ohana/src/libfits/table/F_table_format.c	(revision 15007)
+++ trunk/Ohana/src/libfits/table/F_table_format.c	(revision 15038)
@@ -189,3 +189,141 @@
 }
 
-    /* vsnprintf (&line[off], Nchar + 1, format, argp); */
+// apply table tzero, tscal in situ (from storage to data)
+int gfits_table_scale_data (FTable *ftable) {
+
+  int i, j, n, Nx, Ny, Nfields;
+  int off, Nchar, Nval, Nbytes, status;
+  char *line, format[64], field[16], type[16];
+  double tzero, tscale;
+  char *tmpChar;
+  short *tmpShort;
+  int *tmpInt;
+
+  off = 0;
+
+  gfits_scan (ftable[0].header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2",  "%d", 1, &Ny);
+  gfits_scan (ftable[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (ftable[0].header, field, "%s", 1, format);       /* get field format */
+    gfits_bintable_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+
+    sprintf (field, "TZERO%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tzero);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+
+    sprintf (field, "TSCAL%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tscale);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+    if (tscale == 0.0) {
+	off += Nchar; 
+	continue;
+    }
+
+    if (!strcmp (type, "char"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpChar = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpChar = *tmpChar * tscale + tzero;
+	}
+      }
+    }
+    if (!strcmp (type, "short"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpShort = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpShort = *tmpShort * tscale + tzero;
+	}
+      }
+    }
+    if (!strcmp (type, "int"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpInt = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpInt = *tmpInt * tscale + tzero;
+	}
+      }
+    }
+    off += Nchar;
+  }
+  return (TRUE);
+}
+
+// apply table tzero, tscal in situ (from data to storage)
+int gfits_table_scale_storage (FTable *ftable) {
+
+  int i, j, n, Nx, Ny, Nfields;
+  int off, Nchar, Nval, Nbytes, status;
+  char *line, format[64], field[16], type[16];
+  double tzero, tscale;
+  char *tmpChar;
+  short *tmpShort;
+  int *tmpInt;
+
+  off = 0;
+
+  gfits_scan (ftable[0].header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2",  "%d", 1, &Ny);
+  gfits_scan (ftable[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (ftable[0].header, field, "%s", 1, format);       /* get field format */
+    gfits_bintable_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+
+    sprintf (field, "TZERO%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tzero);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+
+    sprintf (field, "TSCAL%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tscale);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+    if (tscale == 0.0) {
+	off += Nchar; 
+	continue;
+    }
+
+    if (!strcmp (type, "char"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpChar = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpChar = (*tmpChar - tzero) / tscale;
+	}
+      }
+    }
+    if (!strcmp (type, "short"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpShort = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpShort = (*tmpShort - tzero) / tscale;
+	}
+      }
+    }
+    if (!strcmp (type, "int"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpInt = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpInt = (*tmpInt - tzero) / tscale;
+	}
+      }
+    }
+    off += Nchar;
+  }
+  return (TRUE);
+}
