Index: /trunk/psLib/src/imageops/Makefile.am
===================================================================
--- /trunk/psLib/src/imageops/Makefile.am	(revision 12587)
+++ /trunk/psLib/src/imageops/Makefile.am	(revision 12588)
@@ -13,4 +13,5 @@
 	psImageStructManip.c \
 	psImageMaskOps.c \
+	psImageBinning.c \
 	psImageUnbin.c
 
@@ -26,4 +27,5 @@
 	psImageStructManip.h \
 	psImageMaskOps.h \
+	psImageBinning.h \
 	psImageUnbin.h
 
Index: /trunk/psLib/src/imageops/psImageBinning.c
===================================================================
--- /trunk/psLib/src/imageops/psImageBinning.c	(revision 12588)
+++ /trunk/psLib/src/imageops/psImageBinning.c	(revision 12588)
@@ -0,0 +1,160 @@
+/** @file  psImageBinning.c
+ *
+ *  @brief Functions to define the binning strategy and to perform image binning / unbinning
+ *  (resampling).
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-27 02:43:22 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include "psError.h"
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psRegion.h"
+#include "psImage.h"
+#include "psImageBinning.h"
+
+static void psImageBinningFree(psImageBinning *binning) {
+    return;
+}
+
+psImageBinning *psImageBinningAlloc() {
+    psImageBinning *binning = (psImageBinning*)psAlloc(sizeof(psImageBinning));
+    psMemSetDeallocator(binning, (psFreeFunc)psImageBinningFree);
+
+    return binning;
+}
+
+void psImageBinningSetRuffSize(psImageBinning *binning, psImageBinningAlign align) {
+    
+    assert (binning->nXfine > 0);
+    assert (binning->nYfine > 0);
+    assert (binning->nXbin > 0);
+    assert (binning->nYbin > 0);
+
+    binning->nXruff = binning->nXfine / binning->nXbin;
+    if (binning->nXfine % binning->nXbin) binning->nXruff ++;
+
+    binning->nYruff = binning->nYfine / binning->nYbin;
+    if (binning->nYfine % binning->nYbin) binning->nYruff ++;
+
+    switch (align) {
+      case PS_IMAGE_BINNING_LEFT:
+	binning->nXoff = 0;
+	binning->nYoff = 0;
+	break;
+      case PS_IMAGE_BINNING_CENTER:
+	binning->nXoff = (binning->nXfine % binning->nXbin) / 2;
+	binning->nYoff = (binning->nYfine % binning->nYbin) / 2;
+	break;
+      case PS_IMAGE_BINNING_RIGHT:
+	binning->nXoff = (binning->nXfine % binning->nXbin);
+	binning->nYoff = (binning->nYfine % binning->nYbin);
+	break;
+      default:
+	psAbort ("programming error in %s: impossible case\n", __func__);
+    }
+    return;
+}
+
+void psImageBinningSetFineSize(psImageBinning *binning, psImageBinningAlign align) {
+
+    binning->nXfine = binning->nXruff * binning->nXbin;
+    binning->nYfine = binning->nYruff * binning->nYbin;
+    return;
+}
+
+void psImageBinningSetSkip(psImageBinning *binning, psImage *image) {
+
+    binning->nXskip = image->col0 - binning->nXoff;
+    binning->nYskip = image->row0 - binning->nYoff;
+    return;
+}
+
+void psImageBinningSetScale(psImageBinning *binning, psImageBinningAlign align) {
+    
+    assert (binning->nXfine > 0);
+    assert (binning->nYfine > 0);
+    assert (binning->nXruff > 0);
+    assert (binning->nYruff > 0);
+
+    binning->nXbin = binning->nXfine / binning->nXruff;
+    if (binning->nXfine % binning->nXruff) binning->nXbin ++;
+
+    binning->nYbin = binning->nYfine / binning->nYruff;
+    if (binning->nYfine % binning->nYruff) binning->nYbin ++;
+
+    switch (align) {
+      case PS_IMAGE_BINNING_LEFT:
+	binning->nXoff = 0;
+	binning->nYoff = 0;
+	break;
+      case PS_IMAGE_BINNING_CENTER:
+	binning->nXoff = (binning->nXfine % binning->nXbin) / 2;
+	binning->nYoff = (binning->nYfine % binning->nYbin) / 2;
+	break;
+      case PS_IMAGE_BINNING_RIGHT:
+	binning->nXoff = (binning->nXfine % binning->nXbin);
+	binning->nYoff = (binning->nYfine % binning->nYbin);
+	break;
+      default:
+	psAbort ("programming error in %s: impossible case\n", __func__);
+    }
+    return;
+}
+
+psRegion psImageBinningSetFineRegion (psImageBinning *binning, psRegion ruffRegion) {
+
+    psRegion fineRegion;
+
+    fineRegion.x0 = ruffRegion.x0 * binning->nXbin;
+    fineRegion.x1 = ruffRegion.x1 * binning->nXbin;
+    fineRegion.y0 = ruffRegion.y0 * binning->nYbin;
+    fineRegion.y1 = ruffRegion.y1 * binning->nYbin;
+    return fineRegion;
+}
+
+psRegion psImageBinningSetRuffRegion (psImageBinning *binning, psRegion fineRegion) {
+
+    psRegion ruffRegion;
+
+    ruffRegion.x0 = fineRegion.x0 / binning->nXbin;
+    ruffRegion.x1 = fineRegion.x1 / binning->nXbin;
+    ruffRegion.y0 = fineRegion.y0 / binning->nYbin;
+    ruffRegion.y1 = fineRegion.y1 / binning->nYbin;
+    return ruffRegion;
+}
+
+/*** pmFPACopy.c:binRegion had the following logic ***/
+# if (0)
+    // Want to include the lower bound: 1 binned by 4 --> 0; 3 binned by 4 --> 0; 4 binned by 4 --> 1
+    region->x0 = (int)(region->x0 / xBin);
+    region->y0 = (int)(region->y0 / yBin);
+    // Want to exclude the upper bound: 4 binned by 4 --> 1; 5 binned by 4 --> 2; 7 binned by 4 --> 2
+    region->x1 = (int)((region->x1 + xBin - 1) / xBin);
+    region->y1 = (int)((region->y1 + yBin - 1) / yBin);
+# endif
+
+/* 
+ * dvoMakeCorrUnbin ** OK
+ * psphotImageMedian ** OK?
+ * psphotMagnitudes ** OK
+ * pmFPACopy ** OK
+ * pmConceptsUpdate ** OK
+ * pmFPAMosaic ** OK (needs more use of psImageBinning functions)
+ * psImageUnbin 
+ * psImageRebin
+ * ppImageRebinReadout
+ */
+
Index: /trunk/psLib/src/imageops/psImageBinning.h
===================================================================
--- /trunk/psLib/src/imageops/psImageBinning.h	(revision 12588)
+++ /trunk/psLib/src/imageops/psImageBinning.h	(revision 12588)
@@ -0,0 +1,54 @@
+/** @file  psImageBinning.c
+ *
+ *  @brief Functions to define the binning strategy and to perform image binning / unbinning
+ *  (resampling).
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-27 02:43:22 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_BINNING_H
+#define PS_IMAGE_BINNING_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+// description of the image binning relationship between a binned and an unbinned
+// image. binning is defined for a specific input size and output image size.
+typedef struct {
+    int nXfine; 			// width of the hi-res image
+    int nYfine;				// height of the hi-res image
+    int nXruff; 			// width of the lo-res image 
+    int nYruff;				// height of the lo-res image
+    int nXbin;				// X binning factor (~ nXfine/nXruff)
+    int nYbin;				// Y binning factor (~ nYfine/nYruff)
+    int nXoff;				// offset in fine pixels to start of ruff 0 pixel (x_fine - nXoff) / nXbin = x_ruff
+    int nYoff;				// offset in fine pixels to start of ruff 0 pixel (x_fine - nXoff) / nXbin = x_ruff
+    int nXskip;				// offset in fine pixels from start of fine parent 0 pixel to ruff 0 pixel (nXskip = col0 - nXoff)
+    int nYskip;				// offset in fine pixels from start of fine parent 0 pixel to ruff 0 pixel (nYskip = row0 - nYoff)
+} psImageBinning;
+
+typedef enum {
+    PS_IMAGE_BINNING_LEFT,
+    PS_IMAGE_BINNING_CENTER,
+    PS_IMAGE_BINNING_RIGHT,
+} psImageBinningAlign;
+
+
+psImageBinning *psImageBinningAlloc();
+
+void psImageBinningSetRuffSize(psImageBinning *binning, psImageBinningAlign align);
+void psImageBinningSetFineSize(psImageBinning *binning, psImageBinningAlign align);
+void psImageBinningSetScale(psImageBinning *binning, psImageBinningAlign align);
+void psImageBinningSetSkip(psImageBinning *binning, psImage *image);
+psRegion psImageBinningSetFineRegion (psImageBinning *binning, psRegion ruffRegion);
+psRegion psImageBinningSetRuffRegion (psImageBinning *binning, psRegion fineRegion);
+
+/// @}
+#endif // #ifndef PS_IMAGE_GEOM_MANIP_H
Index: /trunk/psLib/src/imageops/psImageUnbin.c
===================================================================
--- /trunk/psLib/src/imageops/psImageUnbin.c	(revision 12587)
+++ /trunk/psLib/src/imageops/psImageUnbin.c	(revision 12588)
@@ -1,2 +1,16 @@
+/** @file  psImageUnbin.c
+ *
+ *  @brief Functions to perform unbinning (resampling) of images.
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-27 02:43:22 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
@@ -4,8 +18,9 @@
 
 #include <stdio.h>
-
 #include "psError.h"
+#include "psAssert.h"
+#include "psRegion.h"
 #include "psImage.h"
-#include "psAssert.h"
+#include "psImageBinning.h"
 #include "psImageUnbin.h"
 
@@ -15,8 +30,14 @@
 // binned pixel. 
 // XXX check that this is still consistent with psphotImageMedian...
-psImage *psImageUnbin(psImage *out, const psImage *in, int DX, int DY, int dx, int dy)
+psImage *psImageUnbin(psImage *out, const psImage *in, const psImageBinning *binning)
 {
     PS_ASSERT_IMAGE_NON_NULL(in, NULL);
     PS_ASSERT_IMAGE_NON_NULL(out, NULL);
+
+    int DX = binning->nXbin;
+    int DY = binning->nYbin;
+    int dx = binning->nXskip;
+    int dy = binning->nYskip;
+
     PS_ASSERT_INT_POSITIVE(DX, NULL);
     PS_ASSERT_INT_POSITIVE(DY, NULL);
@@ -28,4 +49,6 @@
     long Nx = out->numCols;
     long Ny = out->numRows;
+
+    // XXX validate the binning structure vs the input and output images?
 
     psF32 **vIn = in->data.F32;
@@ -183,11 +206,17 @@
  * cases should be added
  */
-double psImageUnbinPixel(const int ix, const int iy, // desired Unbinned point
+double psImageUnbinPixel(const int ix, const int iy, // desired Unbinned point (parent coords)
                          const psImage *in, // binned image
-                         const int DX, const int DY,  //!< Scaling factors in x and y
-                         const int dx, const int dy)   //!< Overhang
+                         const psImageBinning *binning)   //!< Overhang
 {
+
+    int DX = binning->nXbin;
+    int DY = binning->nYbin;
+    int dx = binning->nXskip;
+    int dy = binning->nYskip;
+
     PS_ASSERT_IMAGE_NON_NULL(in, NAN);
     assert (in->type.type == PS_TYPE_F32);
+
     PS_ASSERT_INT_POSITIVE(DX, NAN);
     PS_ASSERT_INT_POSITIVE(DY, NAN);
@@ -197,6 +226,7 @@
      * Find which binned pixel we're in
      */
-    const int Xs = (ix + dx)/DX; // index of binned pixel
-    const int Ys = (iy + dy)/DY;
+
+    const int Xs = (ix - dx)/DX; // index of binned pixel
+    const int Ys = (iy - dy)/DY;
     if (Xs < 0 || Xs >= in->numCols || Ys < 0 || Ys >= in->numRows) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Point (%d,%d) lies outside binned image", ix, iy);
Index: /trunk/psLib/src/imageops/psImageUnbin.h
===================================================================
--- /trunk/psLib/src/imageops/psImageUnbin.h	(revision 12587)
+++ /trunk/psLib/src/imageops/psImageUnbin.h	(revision 12588)
@@ -6,6 +6,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  $Date: 2007-01-23 22:47:23 $
+ *  $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  $Date: 2007-03-27 02:43:22 $
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
  */
@@ -17,16 +17,13 @@
 /// @{
 
-#include "psImage.h"
-
 // This needs to be considered more carefully
 psImage *psImageUnbin (psImage *out,    //!< Output image
                        const psImage *in, //!< Input image
-                       int DX, int DY,  //!< Scaling factors in x and y
-                       int dx, int dy   //!< Overhang
-                      );
+                       const psImageBinning *binning ///< binning definition
+    );
+
 double psImageUnbinPixel(const int ix, const int iy, //!< desired Unbinned point
                          const psImage *in, //!< binned image
-                         const int DX, const int DY,  //!< Scaling factors in x and y
-                         const int dx, const int dy   //!< Overhang
+			 const psImageBinning *binning ///< binning definition
                         );
 
Index: /trunk/psLib/src/pslib_strict.h
===================================================================
--- /trunk/psLib/src/pslib_strict.h	(revision 12587)
+++ /trunk/psLib/src/pslib_strict.h	(revision 12588)
@@ -9,6 +9,6 @@
 *  @author Eric Van Alst, MHPCC
 *
-*  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2007-02-06 21:55:28 $
+*  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-03-27 02:43:22 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -43,4 +43,5 @@
 //#include "psXML.h"
 
+#include "psRegion.h"
 #include "psImageConvolve.h"
 #include "psImageGeomManip.h"
@@ -50,4 +51,5 @@
 #include "psImageStructManip.h"
 #include "psImageMaskOps.h"
+#include "psImageBinning.h"
 #include "psImageUnbin.h"
 
@@ -65,5 +67,4 @@
 #include "psMinimizePolyFit.h"
 #include "psRandom.h"
-#include "psRegion.h"
 #include "psRegionForImage.h"
 #include "psPolynomial.h"
