Index: trunk/psLib/test/image/tst_psImageExtraction.c
===================================================================
--- trunk/psLib/test/image/tst_psImageExtraction.c	(revision 1924)
+++ trunk/psLib/test/image/tst_psImageExtraction.c	(revision 1929)
@@ -6,10 +6,11 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-29 01:10:27 $
+*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-29 20:17:58 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */
 #include<stdlib.h>
+#include<string.h>
 
 #include "psTest.h"
@@ -17,7 +18,12 @@
 #include "psType.h"
 
-static int testImageSlice( void );
+static int testImageSlice(void);
+static int testImageSubset(void);
+static int testImageSubsection(void);
 
 testDescription tests[] = {
+                              {testImageSubset,547,"psImageSubset",0,false},
+                              {testImageSubset,550,"psImageSubset",0,true},
+                              {testImageSubsection,730,"psImageSubsection",0,true},
                               {testImageSlice, 552, "psImageSlice", 0, false},
                               {NULL}
@@ -29,5 +35,5 @@
 }
 
-int testImageSlice( void )
+int testImageSlice(void)
 {
     const int r = 1000;
@@ -286,2 +292,390 @@
 }
 
+// #547: psImageSubset shall create child image of a specified size from a parent psImage structure
+int testImageSubset(void)
+{
+    psImage preSubsetStruct;
+    psImage* original;
+    psImage* subset1 = NULL;
+    psImage* subset2 = NULL;
+    psImage* subset3 = NULL;
+    int c = 128;
+    int r = 256;
+
+    original = psImageAlloc(c,r,PS_TYPE_U32);
+    for (int row=0;row<r;row++) {
+        for (int col=0;col<c;col++) {
+            original->data.F32[row][col] = row*1000+col;
+        }
+    }
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+
+    subset2 = psImageSubset(original,c/4,r/4,c/4+c/2,r/4+r/2);
+
+    subset3 = psImageSubset(original,0,0,c/2,r/2);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure members nrow and ncol are equal to "
+             "the input parameter nrow and ncol respectively.");
+
+    if (subset2->numCols != c/2 || subset2->numRows != r/2) {
+        psError(__func__,"psImageSubset output size was not proper(%dx%d, should be %dx%d).",
+                subset2->numCols, subset2->numRows, c/2,r/2);
+        return 1;
+    }
+
+    if (subset3->numCols != c/2 || subset3->numRows != r/2) {
+        psError(__func__,"psImageSubset output size was not proper(%dx%d, should be %dx%d).",
+                subset3->numCols, subset3->numRows, c/2,r/2);
+        return 2;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure contains expected values in the "
+             "row member, if the input psImage structure image contains known values.");
+
+    for (int row=0;row<r/2;row++) {
+        for (int col=0;col<c/2;col++) {
+            if (subset2->data.U32[row][col] != original->data.U32[row+r/4][col+c/4]) {
+                psError(__func__,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                        row,col,subset2->data.U32[row][col], original->data.U32[row+r/4][col+c/4]);
+                return 3;
+            }
+            if (subset3->data.U32[row][col] != original->data.U32[row][col]) {
+                psError(__func__,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                        row,col,subset2->data.U32[row][col], original->data.U32[row][col]);
+                return 4;
+            }
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member type is equal to the input "
+             "psImage structure member type.");
+
+    if (subset2->type.type != PS_TYPE_U32) {
+        psError(__func__,"psImageSubset output type was not proper(%d, should be %d).",
+                subset2->type.type, PS_TYPE_U32);
+        return 6;
+    }
+    if (subset3->type.type != PS_TYPE_U32) {
+        psError(__func__,"psImageSubset output type was not proper(%d, should be %d).",
+                subset3->type.type, PS_TYPE_U32);
+        return 7;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure members row0 and col0 are equal to "
+             "the input parameters row0 and col0 respectively.");
+
+    if (subset2->col0 != c/4 || subset2->row0 != r/4) {
+        psError(__func__,"psImageSubset didn't set col0/row0 for subset2 (%d/%d, should be %d/%d).",
+                subset2->col0,subset2->row0,c/4,r/4);
+        return 8;
+    }
+    if (subset3->col0 != 0 || subset3->row0 != 0) {
+        psError(__func__,"psImageSubset didn't set col0/row0 for subset3 (%d/%d, should be %d/%d).",
+                subset3->col0,subset3->row0,0,0);
+        return 9;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member parent is equal to the "
+             "input psImage structure pointer image.");
+
+    if (subset2->parent != original || subset3->parent != original) {
+        psError(__func__,"psImageSubset didn't set parent.");
+        return 10;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member children is null.");
+
+    if (subset2->children != NULL || subset3->children != NULL) {
+        psError(__func__,"psImageSubset didn't set children to NULL.");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the input psImage structure image only has the following members "
+             "changed: 1) Nchildren is increased by one. 2) parent contains pointer psImage structure "
+             "out at parent[Nchildren-1].");
+
+    if (original->children == NULL || original->children->n != 2) {
+        psError(__func__,"psImageSubset didn't increment number of children by one per subset.");
+        return 12;
+    }
+    if (original->children->data[0] != subset2 || original->children->data[1] != subset3) {
+        psError(__func__,"psImageSubset didn't properly store the children pointers.");
+        return 13;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop, if the input parameter image is null. Also verified the input "
+             "psImage structure is not modified.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,0,0,c/2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when input image was NULL.");
+        return 14;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             " execution doesn't stop, if the input parameters nrow and/or ncol are zero. Also verify "
+             "input psImage structure is not modified.");
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,r/2,c/2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when numRows=0.");
+        return 15;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,c/2,0,c/2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when numCols=0.");
+        return 16;
+    }
+    if (memcmp(original,&preSubsetStruct,sizeof(psImage)) != 0) {
+        psError(__func__,"psImageSubset changed the original struct though it failed to subset.");
+        return 17;
+    }
+
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop, if the input parameters row0 and col0 are not within the range of "
+             "values of psImage structure image.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,0,c/2,r*2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (via cols).");
+        return 18;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,0,c*2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (via rows).");
+        return 19;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,-1,0,c/2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (col0=-1).");
+        return 20;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,-1,c/2,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset origin was outside of "
+                "image (row0=-1).");
+        return 21;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop if the input parameters nrow, ncol, row0 and col0 specify a range of "
+             "data not within the input psImage structure image.  Also verify the input psImage structure "
+             "is not modified.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,0,c/2,r+1);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset was outside of image (via rows).");
+        return 22;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,0,c+1,r/2);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset was outside of image (via cols).");
+        return 23;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,0,0,c+1,r+1);
+    if (subset1 != NULL) {
+        psError(__func__,"psImageSubset didn't return NULL when subset was outside of image (via row+cols).");
+        return 24;
+    }
+
+    psLogMsg(__func__, PS_LOG_INFO, "psImageFreeChildren shall deallocate any children images of a "
+             "psImage structure");
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+
+    psImageFreeChildren(original);
+
+    // Verify the returned psImage structure member Nchildren is set to zero.
+    if (original->children != NULL && original->children->n > 0) {
+        psError(__func__,"psImageFreeChildren didn't set number of children to zero.");
+        return 25;
+    }
+
+    //Verify the returned psImage structure members type, nrow, ncol, row0, col0, rows and parent are not
+    // modified.
+    if (preSubsetStruct.numRows != original->numRows ||
+            preSubsetStruct.numCols != original->numCols ||
+            preSubsetStruct.row0 != original->row0 ||
+            preSubsetStruct.col0 != original->col0) {
+
+        psError(__func__,"psImageFreeChildren modified parent's non-children elements.");
+        return 27;
+    }
+
+    psFree(original);
+
+    return 0;
+}
+
+// #547: psImageSubset shall create child image of a specified size from a parent psImage structure
+int testImageSubsection(void)
+{
+    psImage* original;
+    psImage* subset;
+    int c = 128;
+    int r = 256;
+    int i;
+    int numRegions = 4;
+    int x1[] = {  0, 32, 64, 32};
+    int x2[] = { 32, 64,127, 64};
+    int y1[] = {  0, 32, 32,128};
+    int y2[] = { 32, 64, 64,255};
+
+    original = psImageAlloc(c,r,PS_TYPE_U32);
+    for (int row=0;row<r;row++) {
+        for (int col=0;col<c;col++) {
+            original->data.F32[row][col] = row*1000+col;
+        }
+    }
+
+    for (i=0; i<numRegions; i++) {
+        char sectionStr[64];
+        sprintf(sectionStr,"[%d:%d,%d:%d]",x1[i],x2[i],y1[i],y2[i]);
+
+        psLogMsg(__func__,PS_LOG_INFO,"Testing subsection %s.",
+                 sectionStr);
+
+        subset = psImageSubsection(original,sectionStr);
+
+        if (subset == NULL) {
+            psError(__func__,"psImageSubsection returned a NULL with a subset of %s.",
+                    sectionStr);
+            return 10*i+1;
+        }
+
+        if (subset->type.type != PS_TYPE_U32) {
+            psError(__func__,"psImageSubsection output type was not proper(%d, should be %d).",
+                    subset->type.type, PS_TYPE_U32);
+            return 10*i+2;
+        }
+
+        if (subset->col0 != x1[i] || subset->row0 != y1[i]) {
+            psError(__func__,"psImageSubsection didn't set properly col0/row0 (%d/%d, should be %d/%d).",
+                    subset->col0,subset->row0,x1[i],y1[i]);
+            return 10*i+3;
+        }
+
+        if (subset->parent != original) {
+            psError(__func__,"psImageSubsection didn't set parent.");
+            return 10*i+4;
+        }
+
+        if (subset->children != NULL) {
+            psError(__func__,"psImageSubsection didn't set children to NULL.");
+            return 10*i+5;
+        }
+
+        if (original->children == NULL || original->children->n != i+1) {
+            psError(__func__,"psImageSubsection didn't increment number of children by one per subset.");
+            return 10*i+6;
+        }
+
+
+        if (original->children->data[i] != subset) {
+            psError(__func__,"psImageSubsection didn't properly store the children pointer.");
+            return 10*i+7;
+        }
+
+        int numCols = x2[i]-x1[i]+1;
+        int numRows = y2[i]-y1[i]+1;
+        if (subset->numCols != numCols || subset->numRows != numRows) {
+            psError(__func__,"psImageSubsection output size was not proper(%dx%d, should be %dx%d).",
+                    subset->numCols, subset->numRows, numCols, numRows);
+            return 10*i+8;
+        }
+
+        for (int row=0;row<numRows;row++) {
+            for (int col=0;col<numCols;col++) {
+                if (subset->data.U32[row][col] != original->data.U32[row+y1[i]][col+x1[i]]) {
+                    psError(__func__,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                            row,col,subset->data.U32[row][col], original->data.U32[row+y1[i]][col+x1[i]]);
+                    return 10*i+9;
+                }
+            }
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (x1>x2)");
+    subset = psImageSubsection(original,"[64:32,32:64]");
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when x1 > x2.");
+        return 10*i+10;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (y1>y2)");
+    subset = psImageSubsection(original,"[32:64,64:32]");
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when y1 > y2.");
+        return 10*i+11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (x2>nCols)");
+    subset = psImageSubsection(original,"[64:256,32:64]"); // assumes c<256
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when x2 > c.");
+        return 10*i+12;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (y2>=nRows)");
+    subset = psImageSubsection(original,"[32:64,64:256]"); // assumes r==256
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when y2 > r.");
+        return 10*i+13;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (malformed string - no brackets)");
+    subset = psImageSubsection(original,"32:64,32:64");
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when subsection was '32:64,32:64'.");
+        return 10*i+14;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (malformed string - no colons)");
+    subset = psImageSubsection(original,"[32-64,32-64]");
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when subsection was '[32-64,32-64]'.");
+        return 10*i+15;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (malformed string - not four numbers)");
+    subset = psImageSubsection(original,"[32:64,32]");
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when subsection was '[32:64,32]'.");
+        return 10*i+16;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (image is NULL)");
+    subset = psImageSubsection(NULL,"[32:64,32:64]");
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when image was NULL.");
+        return 10*i+17;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow (subsection string is NULL)");
+    subset = psImageSubsection(original,NULL);
+    if (subset != NULL) {
+        psError(__func__,"psImageSubsection didn't return NULL when subsection was NULL.");
+        return 10*i+18;
+    }
+
+    psFree(original);
+
+    return 0;
+}
