Index: trunk/psLib/src/fits/psFitsScale.c
===================================================================
--- trunk/psLib/src/fits/psFitsScale.c	(revision 17447)
+++ trunk/psLib/src/fits/psFitsScale.c	(revision 17660)
@@ -46,5 +46,5 @@
     psAssert(options, "impossible");
 
-    double range = pow(2.0, options->bitpix); // Range of values for target BITPIX
+    double range = pow(2.0, options->bitpix) - 1.0; // Range of values for target BITPIX, reduced by the BLANK
     double min = INFINITY, max = -INFINITY; // Minimum and maximum values
     int numCols = image->numCols, numRows = image->numRows; // Size of image
@@ -86,5 +86,5 @@
         *bzero = min;
     } else {
-        *bscale = (max - min) / (range - 1.0);
+        *bscale = (max - min) / range ;
         *bzero = min + 0.5 * range * (*bscale);
     }
@@ -157,7 +157,4 @@
 
     return true;
-
-
-    return true;
 }
 
@@ -168,4 +165,5 @@
 bool psFitsScaleDetermine(double *bscale, // Scaling, to return
                           double *bzero, // Zero point, to return
+                          long *blank,  // Blank value, to return
                           const psImage *image, // Image to scale
                           const psFits *fits // FITS options
@@ -174,4 +172,5 @@
     PS_ASSERT_PTR_NON_NULL(bscale, false);
     PS_ASSERT_PTR_NON_NULL(bzero, false);
+    PS_ASSERT_PTR_NON_NULL(blank, false);
     PS_ASSERT_IMAGE_NON_NULL(image, false);
     PS_ASSERT_FITS_NON_NULL(fits, false);
@@ -179,4 +178,5 @@
     *bscale = 1.0;
     *bzero = 0.0;
+    *blank = 0;
 
     psFitsOptions *options = fits->options; // FITS options
@@ -201,4 +201,6 @@
     }
 
+    *blank = (1 << (options->bitpix - 1)) - 1;
+
     switch (options->scaling) {
       case PS_FITS_SCALE_NONE:
@@ -229,5 +231,12 @@
     }
 
-    psTrace("psLib.fits", 3, "BSCALE = %.10lf, BZERO = %.10lf\n", *bscale, *bzero);
+    if (options->bitpix == 8) {
+        // FITS standard wants unsigned for BITPIX=8, two's-complement for BITPIX=16,32,64.
+        *bzero -= *bscale * 128;
+        *blank = 255;
+    }
+
+
+    psTrace("psLib.fits", 3, "BSCALE = %.10lf, BZERO = %.10lf, BLANK = %ld\n", *bscale, *bzero, *blank);
     return true;
 }
@@ -252,5 +261,6 @@
     switch (bitpix) {
       case 8:
-        outType = PS_TYPE_S8;
+        // Note: Use unsigned integer for BITPIX=8
+        outType = PS_TYPE_U8;
         break;
       case 16:
@@ -283,8 +293,9 @@
 #define SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, OUTTYPE) \
     case PS_TYPE_##OUTTYPE: { \
-        ps##INTYPE scale = 1.0 / bscale; \
-        ps##INTYPE zero = bzero; \
-        ps##INTYPE min = - (1 << (options->bitpix - 1)); \
-        ps##INTYPE max = (1 << (options->bitpix - 1)) - 1; \
+        double scale = 1.0 / bscale; \
+        double zero = bzero; \
+        /* Note: BITPIX=8 treated differently, since it uses unsigned values; the rest use signed */ \
+        double min = bitpix == 8 ? 0 : -pow(2.0, options->bitpix - 1); \
+        double max = bitpix == 8 ? 255 : (pow(2.0, options->bitpix - 1) - 1.0); \
         for (int y = 0; y < numRows; y++) { \
             for (int x = 0; x < numCols; x++) { \
@@ -301,6 +312,6 @@
                         value += psRandomUniform(rng); \
                     } \
-                    /* Check for underflow and overflow */ \
-                    (OUT)->data.OUTTYPE[y][x] = (value < min ? min : (value > max ? max : value)); \
+                    /* Check for underflow and overflow; set either to max */ \
+                    (OUT)->data.OUTTYPE[y][x] = (value < min || value > max ? max : value); \
                 } \
             } \
@@ -312,5 +323,5 @@
     case PS_TYPE_##INTYPE: { \
         switch (outType) { \
-            SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, S8); \
+            SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, U8); \
             SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, S16); \
             SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, S32); \
