views:

37

answers:

3

Greetings all,

I read 3d grid data (from multiple TIF images) into a structure as follows :

typedef struct VolumeData{
 int nx;
 int ny;
 int nz;
 unsigned char *data; // size is nx*ny*nz
}

Now I want to get the plane slices from this 1-D grid data:

eg:

unsigned char* getXYPlaneStack(VolumeData *vol,int z); 

 I could implement above function because the *data array stores image stack.

But i am having difficult time implement along the other axes:

unsigned char* getYZPlaneStack(VolumeData *vol,int x);

and

unsigned char* getXZPlaneStack(VolumeData *vol,int y);

any easy algorithm for this? thanks in advance.

+1  A: 

C arrays are always sequential in memory. What you're after seems like it would require a more complicated relationship between the address of subsequent elements, than just adding the size of the element.

I think you're going to either have to abstract it further, so that you get a function (getAt() or something) to call to index into the array, or create new slices dynamically and copying the data across.

unwind
+1  A: 

This is not possible with the the return type you mentioned.

I will explain.

In the first function, you return a pointer, and the caller expects address of continuously packed data. This is okay, because the original structure supports it.

For the second function, if you want to return the address of the continuously packed plane, you will have to do [1] reordering, meaning, copy it elsewhere [2] allocating memory, because of the copying elsewhere, and [3] freeing the memory, because of the allocation done in 2.

If copying is acceptable from performance point of view, the best approach is to use smart objects which will handle the work for you. STL's std::vector is probably the best.

If you have very large data or performance is a concern, then you would have to design a different approach without copying the data. You would have to implement custom indexers - that is, avoid the transformation you ask for.

Pavel Radzivilovsky
+1  A: 

2nd and 3rd functions both resample your data set (they are basically expressing your image in a new referential).

So they must reorganize the data:

  1. Create a new array of size ny*nz for YZ and nx*nz for XZ
  2. Fill the array with data laying in the given plane
  3. Return the pointer to the newly allocated array

(In this scenario, the caller is responsible of deallocating the newly allocated memory.)

Your algorithm for the YZ plane is:

// I assume this sorting order:
//       Z ^          Slices are
//        /           stacked along
//       /            the Z axis
//      +-------> X
//      |
//      |
//    Y v

// Assumes your data is stored in row major order:
//          +-------> X        +---------> X
// slice 0: | 0 1 2 | slice 1: | 6  7  8 | etc.
//          | 3 4 5 |          | 9 10 11 |
//        Y v                Y v
// Assumes x is the column index, y the row index, z the slice index.
// For example, you want element #9:
// - col 0   -> x = 0
// - row 1   -> y = 1
// - slice 1 -> z = 1
// I suggest you rename nx, ny, nz into nbCols, nbRows, nbSlices to make
// things explicit
index computeIndex(VolumeData *vol, int x, int y, int z)
{
    int nx = vol->nx, // nb cols
        ny = vol->ny, // nb rows
        nz = vol->nz; // nb slices
    int index = nx*ny*z // size of one slice, multiplied by slice index
              + nx*y    // size of one row (nb cols), multiplied by row index
              + x;      // offset in row (column index)
    return index;
}

unsigned char* getYZPlaneStack(VolumeData *vol,int x)
{
    int nx = vol->nx, // nb rows
        ny = vol->ny, // nb columns
        nz = vol->nz; // nb slices
    unsigned char *newData = new unsigned char[ny*nz];
    // Depth is now along the X axis
    //   +-----> Z
    //   |
    //   |
    // Y v
    for(int y = 0; y < ny; ++y)      // For each row
        for(int z = 0; z < nz; ++z ) // For each column
        {
            int i = computeIndex(vol, x, y, z);
            newData[nz*y+z] = vol->data[i];
        }
    return newData;
}
Julien L.
thanks alot! just what I wanted
umanga