Index: trunk/psModules/src/detrend/pmFlatField.c
===================================================================
--- trunk/psModules/src/detrend/pmFlatField.c	(revision 15673)
+++ trunk/psModules/src/detrend/pmFlatField.c	(revision 18893)
@@ -11,4 +11,60 @@
 #include "pmFPAMaskWeight.h"
 #include "pmFlatField.h"
+#include "pmDetrendThreads.h"
+
+bool pmFlatFieldScan_Threaded (psThreadJob *job) {
+    psImage *inImage   = job->args->data[0];
+    psImage *inMask    = job->args->data[1];
+    psImage *flatImage = job->args->data[2];
+    psImage *flatMask  = job->args->data[3];
+
+    psMaskType badFlat = PS_SCALAR_VALUE(job->args->data[4],U8);
+    int xOffset        = PS_SCALAR_VALUE(job->args->data[5],S32);
+    int yOffset        = PS_SCALAR_VALUE(job->args->data[6],S32);
+    int rowStart       = PS_SCALAR_VALUE(job->args->data[7],S32);
+    int rowStop        = PS_SCALAR_VALUE(job->args->data[8],S32);
+    bool status = pmFlatFieldScan (inImage, inMask, flatImage, flatMask, badFlat, xOffset, yOffset, rowStart, rowStop);
+    return status;
+}
+
+// Macro for all PS types
+#define FLAT_DIVISION_CASE(TYPE, SPECIAL)	\
+    case PS_TYPE_##TYPE:			\
+    for (int j = rowStart; j < rowStop; j++) { \
+        for (int i = 0; i < inImage->numCols; i++) { \
+            ps##TYPE flatValue = flatImage->data.TYPE[j + yOffset][i + xOffset]; \
+            if (!isfinite(flatValue) || flatValue <= 0.0 || \
+                (flatMask && flatMask->data.U8[j + yOffset][i + xOffset])) { \
+                if (inMask) { \
+                    inMask->data.PS_TYPE_MASK_DATA[j][i] |= badFlat; \
+                } \
+                inImage->data.TYPE[j][i] = SPECIAL; \
+            } else { \
+                inImage->data.TYPE[j][i] /= flatValue; \
+            } \
+        } \
+    } \
+    break;
+
+bool pmFlatFieldScan (psImage *inImage, psImage *inMask, psImage *flatImage, psImage *flatMask, psMaskType badFlat, int xOffset, int yOffset, int rowStart, int rowStop) {
+
+    switch (inImage->type.type) {
+        FLAT_DIVISION_CASE(U8,  0);
+        FLAT_DIVISION_CASE(U16, 0);
+        FLAT_DIVISION_CASE(U32, 0);
+        FLAT_DIVISION_CASE(U64, 0);
+        FLAT_DIVISION_CASE(S8,  0);
+        FLAT_DIVISION_CASE(S16, 0);
+        FLAT_DIVISION_CASE(S32, 0);
+        FLAT_DIVISION_CASE(S64, 0);
+        FLAT_DIVISION_CASE(F32, NAN);
+        FLAT_DIVISION_CASE(F64, NAN);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unsupported type for input image: %x\n",
+                inImage->type.type);
+        return false;
+    }
+    return true;
+}
 
 bool pmFlatField(pmReadout *in, const pmReadout *flat, psMaskType badFlat)
@@ -71,38 +127,54 @@
     }
 
-    // Macro for all PS types
-    #define FLAT_DIVISION_CASE(TYPE, SPECIAL) \
-case PS_TYPE_##TYPE: \
-    for (int j = 0; j < inImage->numRows; j++) { \
-        for (int i = 0; i < inImage->numCols; i++) { \
-            ps##TYPE flatValue = flatImage->data.TYPE[j + yOffset][i + xOffset]; \
-            if (!isfinite(flatValue) || flatValue <= 0.0 || \
-                (flatMask && flatMask->data.U8[j + yOffset][i + xOffset])) { \
-                if (inMask) { \
-                    inMask->data.PS_TYPE_MASK_DATA[j][i] |= badFlat; \
-                } \
-                inImage->data.TYPE[j][i] = SPECIAL; \
-            } else { \
-                inImage->data.TYPE[j][i] /= flatValue; \
-            } \
-        } \
-    } \
-    break;
+    bool threaded = true;
+    int scanRows = pmDetrendGetScanRows();
+    if (scanRows == 0) { 
+	threaded = false;
+	scanRows = inImage->numRows;
+    }
 
-    switch (inImage->type.type) {
-        FLAT_DIVISION_CASE(U8,  0);
-        FLAT_DIVISION_CASE(U16, 0);
-        FLAT_DIVISION_CASE(U32, 0);
-        FLAT_DIVISION_CASE(U64, 0);
-        FLAT_DIVISION_CASE(S8,  0);
-        FLAT_DIVISION_CASE(S16, 0);
-        FLAT_DIVISION_CASE(S32, 0);
-        FLAT_DIVISION_CASE(S64, 0);
-        FLAT_DIVISION_CASE(F32, NAN);
-        FLAT_DIVISION_CASE(F64, NAN);
-    default:
-        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unsupported type for input image: %x\n",
-                inImage->type.type);
-        return false;
+    for (int rowStart = 0; rowStart < inImage->numRows; rowStart += scanRows) {
+      int rowStop = PS_MIN (rowStart + scanRows, inImage->numRows);
+
+# define PS_ARRAY_ADD_SCALAR(ARRAY, VALUE, TYPE) { \
+      psScalar *scalar = psScalarAlloc(VALUE, TYPE); \
+      psArrayAdd(ARRAY, 1, scalar); \
+      psFree (scalar); }
+      
+      if (threaded) {
+	  // allocate a job, construct the arguments for this job
+	  psThreadJob *job = psThreadJobAlloc ("PSMODULES_DETREND_FLAT");
+	  psArrayAdd (job->args, 1, inImage);
+	  psArrayAdd (job->args, 1, inMask);
+	  psArrayAdd (job->args, 1, flatImage);
+	  psArrayAdd (job->args, 1, flatMask);
+	  PS_ARRAY_ADD_SCALAR (job->args, badFlat, PS_TYPE_U8);
+	  PS_ARRAY_ADD_SCALAR (job->args, xOffset, PS_TYPE_S32);
+	  PS_ARRAY_ADD_SCALAR (job->args, yOffset, PS_TYPE_S32);
+	  PS_ARRAY_ADD_SCALAR (job->args, rowStart, PS_TYPE_S32);
+	  PS_ARRAY_ADD_SCALAR (job->args, rowStop, PS_TYPE_S32);
+
+	  // ppImageDetrendReadout(config, options, view)
+	  if (!psThreadJobAddPending (job)) {
+	      return false;
+	  }
+      } else {
+	  pmFlatFieldScan (inImage, inMask, flatImage, flatMask, badFlat, xOffset, yOffset, rowStart, rowStop);
+      }
+    }
+
+    if (threaded) {
+	// wait here for the threaded jobs to finish
+	if (!psThreadPoolWait ()) {
+	    psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+	    return false;
+	}
+	fprintf (stderr, "success for threaded jobs\n");
+
+	// free done jobs
+	psThreadJob *job = NULL;
+	while ((job = psThreadJobGetDone()) != NULL) {
+	    psFree (job);
+	}
     }
 
