cmtkVolumeFromFileBioRad.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2398 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkVolumeFromFile.h"
00034 
00035 #include <System/cmtkConsole.h>
00036 #include <System/cmtkCompressedStream.h>
00037 
00038 #include <Base/cmtkTypes.h>
00039 
00040 #include <stdio.h>
00041 
00042 namespace
00043 cmtk
00044 {
00045 
00048 
00050 typedef struct
00051 {
00052   unsigned short nx, ny;    //  0   2*2     image width and height in pixels
00053   short npic;               //  4   2       number of images in file
00054   short ramp1_min;          //  6   2*2     LUT1 ramp min. and max.
00055   short ramp1_max;
00056   int notes;                // 10   4       no notes=0; has notes=non zero
00057   short byte_format;        // 14   2       bytes=TRUE(1); words=FALSE(0)
00058   unsigned short n;         // 16   2       image number within file
00059   char name[32];            // 18   32      file name
00060   short merged;             // 50   2       merged format
00061   unsigned short color1;    // 52   2       LUT1 color status
00062   unsigned short file_id;   // 54   2       valid .PIC file=12345
00063   short ramp2_min;          // 56   2*2     LUT2 ramp min. and max.
00064   short ramp2_max;
00065   unsigned short color2;    // 60   2       LUT2 color status
00066   short edited;             // 62   2       image has been edited=TRUE(1)
00067   short lens;               // 64   2       Integer part of lens magnification
00068   float mag_factor;         // 66   4       4 byte real mag. factor (old ver.)
00069   unsigned short dummy[3];  // 70   6       NOT USED (old ver.=real lens mag.)
00070 } FileHeaderBioRad;
00071 
00072 const UniformVolume::SmartPtr
00073 VolumeFromFile::ReadBioRad( const char* path )
00074 {
00075   CompressedStream stream( path );
00076 
00077   // Biorad header is 76 bytes
00078   char buffer[76];
00079   if ( 1 != stream.Read( &buffer, sizeof(buffer), 1 ) ) 
00080     {
00081     StdErr << "ERROR: cannot read header from BioRad file " << path << ". Bailing out.\n";
00082     return UniformVolume::SmartPtr( NULL );
00083     }
00084   
00085   FileHeaderBioRad header;
00086   memcpy( &header.nx, buffer+0, sizeof( header.nx ) );
00087   memcpy( &header.ny, buffer+2, sizeof( header.ny ) );
00088   memcpy( &header.npic, buffer+4, sizeof( header.npic ) );
00089 
00090   memcpy( &header.notes, buffer+10, sizeof( header.notes ) );
00091   memcpy( &header.byte_format, buffer+14, sizeof( header.byte_format ) );
00092   memcpy( &header.file_id, buffer+54, sizeof( header.file_id ) );
00093 
00094   // check MagicNumber
00095 #ifdef WORDS_BIGENDIAN    
00096   if ( Memory::ByteSwap( header.file_id ) != 12345 ) 
00097     {
00098     StdErr << "ERROR: BioRad file " << path << " has invalid magic number. Bailing out.\n";
00099     return UniformVolume::SmartPtr( NULL );
00100     }
00101 #else
00102   if ( header.file_id != 12345 ) 
00103     {
00104     StdErr << "ERROR: BioRad file " << path << " has invalid magic number. Bailing out.\n";
00105     return UniformVolume::SmartPtr( NULL );
00106     }
00107 #endif
00108 
00109 #ifdef WORDS_BIGENDIAN    
00110   int dims[3] = { Memory::ByteSwap( header.nx ), Memory::ByteSwap( header.ny ), Memory::ByteSwap( header.npic ) };
00111 #else
00112   int dims[3] = { header.nx, header.ny, header.npic };
00113 #endif
00114   int numPixels = dims[0] * dims[1] * dims[2];
00115   
00116   TypedArray::SmartPtr dataArray;
00117   if ( header.byte_format ) 
00118     {
00119     dataArray = TypedArray::SmartPtr( TypedArray::Create( TYPE_BYTE, numPixels ) );
00120     } 
00121   else
00122     {
00123     dataArray = TypedArray::SmartPtr( TypedArray::Create( TYPE_USHORT, numPixels ) );    
00124     }
00125   
00126   stream.Read( dataArray->GetDataPtr(), dataArray->GetItemSize(), dataArray->GetDataSize() );
00127   
00128   double pixelsizeX = 1, pixelsizeY = 1, pixelsizeZ = 1;
00129   bool flipX = false, flipY = false, flipZ = false;;
00130   
00131   while ( ! stream.Feof() ) 
00132     {
00133     char lineheader[16], line[80];
00134     stream.Read( lineheader, sizeof( lineheader ), 1 );
00135     stream.Read( line, sizeof( line ), 1 );
00136     
00137     //      StdErr.printf( "%s\n->%s\n", lineheader, line );
00138     
00139     double d1, d2, d3;
00140     if ( 3 == sscanf( line, "AXIS_2 %lf %lf %lf", &d1, &d2, &d3 ) ) 
00141       {
00142       pixelsizeX = fabs( d3 );
00143       flipX = (d3 < 0 );
00144       }
00145     if ( 3 == sscanf( line, "AXIS_3 %lf %lf %lf", &d1, &d2, &d3 ) ) 
00146       {
00147       pixelsizeY = fabs( d3 );
00148       flipY = (d3 < 0 );
00149       }
00150     if ( 3 == sscanf( line, "AXIS_4 %lf %lf %lf", &d1, &d2, &d3 ) ) 
00151       {
00152       pixelsizeZ = fabs( d3 );
00153       flipZ = (d3 < 0 );
00154       }
00155     }
00156   
00157 #ifdef WORDS_BIGENDIAN
00158   Types::Coordinate lensScale = 1; //Memory::ByteSwap( header.lens );
00159 #else
00160   Types::Coordinate lensScale = 1; //header.lens;
00161 #endif
00162   
00163 // GJ I think this was backwards - want to swap if we ARE on big endian
00164 // since Biorad is always little endian
00165 //#ifndef WORDS_BIGENDIAN
00166 #ifdef WORDS_BIGENDIAN
00167   // change endianness from Sun to whatever we're currently on.
00168   dataArray->ChangeEndianness();
00169 #endif
00170   
00171   const Types::Coordinate volSize[3] = { (dims[0] - 1) * lensScale * pixelsizeX, (dims[1] - 1) * lensScale * pixelsizeY, (dims[2] - 1) * pixelsizeZ };
00172   
00173   UniformVolume::SmartPtr volume( new UniformVolume( DataGrid::IndexType( dims ), UniformVolume::CoordinateVectorType( volSize ), dataArray ) );
00174 
00175   if ( flipX )
00176     {
00177     StdErr << "WARNING: x pixel spacing is negative. Resulting volume will be mirrored accordingly.\n";
00178     volume->ApplyMirrorPlane( AXIS_X );
00179     }
00180   if ( flipY )
00181     {
00182     StdErr << "WARNING: y pixel spacing is negative. Resulting volume will be mirrored accordingly.\n";
00183     volume->ApplyMirrorPlane( AXIS_Y );
00184     }
00185   if ( flipZ )
00186     {
00187     StdErr << "WARNING: z pixel spacing is negative. Resulting volume will be mirrored accordingly.\n";
00188     volume->ApplyMirrorPlane( AXIS_Z );
00189     }
00190 
00191   return volume;
00192 }
00193 
00194 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines