arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

gliftNrrd.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////
00002 // 9/6/02       Aaron Lefohn    Scientific Computing and Imaging Institute
00003 // School of Computing          University of Utah
00004 //
00005 //  This library is free software; you can redistribute it and/or
00006 //  modify it under the terms of the GNU Lesser General Public
00007 //  License as published by the Free Software Foundation; either
00008 //  version 2.1 of the License, or (at your option) any later version.
00009 //
00010 //  This library is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 //  Lesser General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU Lesser General Public
00016 //  License along with this library; if not, write to the Free Software
00017 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 ////////////////////////////////////////////////////////////////////////
00019 
00020 
00021 #ifdef GLIFT_NRRD
00022 
00023 #include <util/gliftNrrd.h>
00024 #include <iostream>
00025 #include <stdio.h>
00026 
00027 using namespace std;
00028 using namespace gutz;
00029 
00030 using namespace glift;
00031 
00032 /// Convert a nrrdType to an OpenGL type
00033 GLenum typeN2GL( int nrrdType )
00034 {
00035    GLenum glType;
00036 
00037    switch( nrrdType )
00038    {
00039    case nrrdTypeChar:   glType = GL_BYTE;                       break;  /*   signed 1-byte integer */
00040    case nrrdTypeUChar: glType = GL_UNSIGNED_BYTE;       break;  /* unsigned 1-byte integer */
00041    case nrrdTypeShort: glType = GL_SHORT;                       break;  /*   signed 2-byte integer */
00042    case nrrdTypeUShort:glType = GL_UNSIGNED_SHORT;      break;  /* unsigned 2-byte integer */
00043    case nrrdTypeInt:    glType = GL_INT;                        break;  /*   signed 4-byte integer */
00044    case nrrdTypeUInt:   glType = GL_UNSIGNED_INT;       break;  /* unsigned 4-byte integer */
00045    case nrrdTypeFloat: glType = GL_FLOAT;                       break;  /*          4-byte floating point */
00046    default:
00047       cerr << "typeN2GL(" << nrrdType << ") Error: OpenGL does not support that type\n";
00048       exit(1);
00049    }
00050 
00051    return glType;
00052 }
00053 
00054 /// Convert an OpenGL type to a nrrdType
00055 GLenum typeGL2N( GLenum glType)
00056 {
00057    int nrrdType;
00058 
00059    switch( glType )
00060    {
00061    case GL_BYTE:                        nrrdType = nrrdTypeChar;        break;  /*   signed 1-byte integer */
00062    case GL_UNSIGNED_BYTE:       nrrdType = nrrdTypeUChar;       break;  /* unsigned 1-byte integer */
00063    case GL_SHORT:                       nrrdType = nrrdTypeShort;       break;  /*   signed 2-byte integer */
00064    case GL_UNSIGNED_SHORT:      nrrdType = nrrdTypeUShort ;     break;  /* unsigned 2-byte integer */
00065    case GL_INT:                 nrrdType = nrrdTypeInt;         break;  /*   signed 4-byte integer */
00066    case GL_UNSIGNED_INT:        nrrdType = nrrdTypeUInt;        break;  /* unsigned 4-byte integer */
00067    case GL_FLOAT:                       nrrdType = nrrdTypeFloat;       break;  /*          4-byte floating point */
00068    default:
00069       cerr << "typeGL2N(" << glType << ") Error: Nrrd does not support that type\n";
00070       exit(1);
00071    }
00072 
00073    return nrrdType;
00074 }
00075 
00076 // Return GliftFormatPGM, GliftFormatPPM, or GliftFormatUnknown
00077 GliftFormat gliftNrrdTypePNM( Nrrd* nIn )
00078 {
00079    int format = nrrdFitsInFormat(nIn, nrrdEncodingRaw, nrrdFormatPNM, AIR_FALSE);
00080    GliftFormat type = GliftFormatUnknown; 
00081 
00082    if( format == 2 ) {
00083       type = GliftFormatPGM;
00084    }
00085    else if( format == 3 ) {
00086       type = GliftFormatPPM;
00087    }
00088 
00089    return type;
00090 }
00091 
00092 // Read just the Nrrd header of 'fileName'
00093 int gliftNrrdLoadHeader( Nrrd* nIn, const char* fileName )
00094 {
00095    char me[] = "nrrdLoadHeader_glift", err[AIR_STRLEN_MED];
00096    airArray *mop;
00097 
00098    mop = airMopNew();
00099    FILE *inFile = fopen( fileName, "rb" );
00100    if( !inFile ) {
00101       fprintf(stderr, "nrrdLoadHeader_glift(...) Error: Can't open input file '%s'.\nProgram aborted.\n\n", fileName);
00102       exit(1);
00103    }
00104    airMopAdd(mop, inFile, (airMopper)airFclose, airMopAlways);
00105 
00106    // Allocate a nrrdStruct
00107    NrrdIO* nIO = nrrdIONew();
00108    airMopAdd(mop, nIO, (airMopper)nrrdIONix, airMopAlways);
00109    nIO->skipData = true;        // Only read the header
00110    nIO->dir = airStrdup("This is a hack that should not need to exist!");
00111 
00112    // Read the header
00113    if( nrrdRead(nIn, inFile, nIO) ) {
00114       sprintf(err, "%s: Error in reading header of file \"%s\"", me, fileName);
00115       biffAdd(NRRD, err); airMopError(mop); return 1;
00116    }
00117 
00118    // Cleanup
00119    airMopOkay(mop);
00120    //airArrayNix(mop);
00121    return 0;
00122 }
00123 
00124 // Flip the y-axis for data in 'data'
00125 void gliftNrrdFlipYub( arrayo2ub& data )
00126 {       
00127    int e = 0;
00128    Nrrd* nIn = nrrdNew();
00129    Nrrd* nOut= nrrdNew();
00130 
00131    nerr( nrrdWrap( nIn, (void*)data.data(), nrrdTypeUChar, 2, data.dim(1), data.dim(0) ), e );
00132    nerr( nrrdFlip( nOut, nIn, 1 ), e );
00133 
00134    if(e) {
00135       cerr << "gliftNrrdFlipYub(...) Nrrd Error:\n\t"
00136          << biffGetDone(NRRD) << endl;
00137       exit(1);
00138    }
00139 
00140    data.transfer( data.dim(0), data.dim(1), (ubyte*)nOut->data, false);
00141 
00142    nrrdNix(nIn);
00143    nrrdNix(nOut);
00144 }
00145 
00146 
00147 // Tile 3D scalar data only in X and Y
00148 void gliftNrrdTileDataXYub( const arrayw3ub& srcData3, const vec2i& tileSize, arrayo5ub& tiledData )
00149 {
00150    vec3i srcSize( srcData3.dim(2), srcData3.dim(1), srcData3.dim(0) );
00151    vec2i numTiles = vec2i(srcSize) / tileSize;
00152    assert( srcSize.x % tileSize.x == 0 );
00153    assert( srcSize.y % tileSize.y == 0 );
00154 
00155    int e = 0;
00156    Nrrd* nIn  = nrrdNew();
00157    Nrrd* nOut = nrrdNew();
00158 
00159    // Create nrrd of: sx, tx, sy, ty, z
00160    nerr( nrrdWrap( nIn, (void*)srcData3.data(), nrrdTypeUChar, 3, srcSize.x, srcSize.y, srcSize.z ), e );
00161    nerr( nrrdReshape( nIn, nIn, 5, tileSize.x, numTiles.x, tileSize.y, numTiles.y, srcSize.z ), e );
00162 
00163    // Change to: sx, sy, tx, ty, z
00164    int axes[5] = {0, 2, 1, 3, 4};
00165    nerr( nrrdAxesPermute( nOut, nIn, axes ), e );
00166 
00167    if(e) {
00168       cerr << "gliftNrrdTileDataXYub(...) Nrrd Error:\n\t"
00169          << biffGetDone(NRRD) << endl;
00170       exit(1);
00171    }
00172 
00173    // Store tiled monster in arrayo5ub
00174    tiledData.transfer( srcSize.z, numTiles.y, numTiles.x, tileSize.y, tileSize.x, (ubyte*)nOut->data, false); 
00175 
00176    nrrdNix(nIn);
00177    nrrdNix(nOut);
00178 }
00179 
00180 // Untile XY-tiled (5D), 3D data into a standard 3D scalar format
00181 // - Opposite of "gliftNrrdTileDataXYub"
00182 void gliftNrrdUntileXYub( const arrayw5ub& tiledData, arrayo3ub& untiledData )
00183 {
00184    vec2i numTiles( tiledData.dim(2), tiledData.dim(1) );
00185    vec2i tileSize( tiledData.dim(4), tiledData.dim(3) );
00186    vec3i untiledSize( numTiles.x * tileSize.x, numTiles.y * tileSize.y, tiledData.dim(0) );
00187 
00188    int e = 0;
00189    Nrrd* nIn = nrrdNew();
00190    Nrrd* nOut= nrrdNew();
00191 
00192    // Create Nrrd of: sx, sy, tx, ty, z
00193    nerr( nrrdWrap( nIn, (void*)tiledData.data(), nrrdTypeUChar, 5, 
00194       tiledData.dim(4), tiledData.dim(3), tiledData.dim(2), tiledData.dim(1), tiledData.dim(0) ), e );
00195 
00196    // Change to: sx, tx, sy, ty, z
00197    int axes[5] = {0, 2, 1, 3, 4};
00198    nerr( nrrdAxesPermute( nOut, nIn, axes ), e );
00199 
00200    // Reshape to: x, y, z where x = sx*tx and y = sy*ty
00201    nerr( nrrdReshape( nOut, nOut, 3, untiledSize.x, untiledSize.y, untiledSize.z ), e );
00202 
00203    if(e) {
00204       cerr << "gliftNrrdTileDataXYub(...) Nrrd Error:\n\t"
00205          << biffGetDone(NRRD) << endl;
00206       exit(1);
00207    }
00208 
00209    // Transfer ownership of untiled data to an arrayo3ub
00210    untiledData.transfer( untiledSize.z, untiledSize.y, untiledSize.x, (ubyte*)nOut->data, false); 
00211 
00212    nrrdNix(nIn);
00213    nrrdNix(nOut);
00214 }
00215 
00216 // Helper function for "resampleVolBoxXY"
00217 // - Private to this file
00218 // - Set 'rescale' to 1.0 if you do NOT want the axis resampled
00219 NrrdResampleInfo* f_buildResampleInfo( const vec3d& rescale, Nrrd* nIn )
00220 {
00221    // Setup the sampleInfo struct
00222    NrrdResampleInfo *info = nrrdResampleInfoNew();
00223 
00224    // 1) Set the number of samples on each axis
00225    // 2) Set the min/max for each Axis
00226    for(int d=0; d < 3; d++) {
00227 
00228       int numSamples = nIn->axis[d].size  * rescale[d];
00229       info->samples[d] = numSamples > 0 ? numSamples : 1;
00230       nrrdAxisMinMaxSet(nIn, d, nrrdDefCenter);
00231 
00232       // Resample with box filter unless numSamples==1 or rescale==1
00233       info->kernel[d] = ((info->samples[d] > 1) && (fabs(rescale[d] - 1.0) > 1e-6)) ? nrrdKernelBox : NULL;
00234       info->min[d] = nIn->axis[d].min;
00235       info->max[d] = nIn->axis[d].max;
00236    }
00237 
00238    // Output a float Nrrd
00239    //info->type = nrrdTypeFloat;
00240 
00241    return info;
00242 }
00243 
00244 // Downsample 'scalarVol' to 'resampledVol' with a box filter
00245 //              unu resample -k box -s x(rescale.x) x(rescale.y) x(rescale.z)
00246 //              - Set 'rescale' to 1.0 if you do NOT want the axis resampled
00247 void gliftNrrdResampleVolBoxf( const vec3d& rescale, const arrayw3f& scalarVol, arrayo3f& resampledVol)
00248 {
00249    int e = 0;           // Nrrd error accumulator
00250 
00251    // Turn scalarVol into a Nrrd
00252    Nrrd* nIn  = nrrdNew();
00253    nerr( nrrdWrap( nIn, (float*)scalarVol.data(), nrrdTypeFloat, 3, scalarVol.dim(2), scalarVol.dim(1), scalarVol.dim(0) ), e );
00254 
00255    // Build resample info structure
00256    // - Use box kernel on X and Y axes
00257    NrrdResampleInfo* info = f_buildResampleInfo( rescale, nIn );
00258 
00259    // Do the resampling
00260    Nrrd* nOut = nrrdNew();
00261    nIn->axis[0].center = nrrdCenterCell;
00262    nIn->axis[1].center = nrrdCenterCell;
00263    nIn->axis[2].center = nrrdCenterCell;
00264    nerr( nrrdSpatialResample( nOut, nIn, info ), e );
00265 
00266    // Check for Nrrd Errors
00267    if( e ) {
00268       char* err = biffGetDone(NRRD);
00269       cerr << (err ? err : "") << endl
00270          << "\agliftNrrdResampleVolBox() Error:\n";
00271       exit(1);
00272    }
00273 
00274    // Nuke contents of "resampled" and transfer downsampled data to "resampled"
00275    resampledVol.transfer( nOut->axis[2].size, nOut->axis[1].size, nOut->axis[0].size, (float*)nOut->data, false);
00276 
00277    // Clean up
00278    nrrdNix(  nIn );
00279    nrrdNix( nOut );
00280    nrrdResampleInfoNix( info );
00281 }
00282 
00283 // Downsample 'scalarVol' to 'resampledVol' with a box filter
00284 //              unu resample -k box -s x(rescale.x) x(rescale.y) x(rescale.z)
00285 //              - Set 'rescale' to 1.0 if you do NOT want the axis resampled
00286 void gliftNrrdResampleVolBoxub( const vec3d& rescale, const arrayw3ub& scalarVol, arrayo3ub& resampledVol)
00287 {
00288    int e = 0;           // Nrrd error accumulator
00289 
00290    // Turn scalarVol into a Nrrd
00291    Nrrd* nIn  = nrrdNew();
00292    nerr( nrrdWrap( nIn, (uchar*)scalarVol.data(), nrrdTypeUChar, 3, scalarVol.dim(2), scalarVol.dim(1), scalarVol.dim(0) ), e );
00293 
00294    // Build resample info structure
00295    // - Use box kernel on X and Y axes
00296    NrrdResampleInfo* info = f_buildResampleInfo( rescale, nIn );
00297 
00298    // Do the resampling
00299    Nrrd* nOut = nrrdNew();
00300    nIn->axis[0].center = nrrdCenterCell;
00301    nIn->axis[1].center = nrrdCenterCell;
00302    nIn->axis[2].center = nrrdCenterCell;
00303    nerr( nrrdSpatialResample( nOut, nIn, info ), e );
00304 
00305    // Check for Nrrd Errors
00306    if( e ) {
00307       char* err = biffGetDone(NRRD);
00308       cerr << (err ? err : "") << endl
00309          << "\agliftNrrdResampleVolBox() Error:\n";
00310       exit(1);
00311    }
00312 
00313    // Nuke contents of "resampled" and transfer downsampled data to "resampled"
00314    resampledVol.transfer( nOut->axis[2].size, nOut->axis[1].size, nOut->axis[0].size, (uchar*)nOut->data, false);
00315 
00316    // Clean up
00317    nrrdNix(  nIn );
00318    nrrdNix( nOut );
00319    nrrdResampleInfoNix( info );
00320 }
00321 
00322 
00323 #endif
00324 

Send questions, comments, and bug reports to:
jmk