core/vil/file_formats/vil_dicom.cxx
Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_dicom.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include <vil/vil_config.h>
00009 #if HAS_DCMTK
00010 
00011 #include "vil_dicom.h"
00012 
00013 #include <vcl_cassert.h>
00014 #include <vcl_iostream.h>
00015 #include <vcl_sstream.h>
00016 #include <vcl_cstring.h>
00017 #include <vcl_cstdlib.h>
00018 #include <vcl_vector.h>
00019 
00020 #include <vxl_config.h> // for vxl_byte and such
00021 
00022 #include <vil/vil_property.h>
00023 #include <vil/vil_stream.h>
00024 #include <vil/vil_image_resource.h>
00025 #include <vil/vil_new.h>
00026 #include <vil/vil_image_view.h>
00027 #include <vil/vil_pixel_format.h>
00028 #include <vil/vil_exception.h>
00029 #ifdef __BORLANDC__
00030 // We do not want to fix small problems in external maintained code.
00031 # pragma warn -8004 // 'smask' is assigned a value that is never used in function
00032 #endif
00033 
00034 #include <dcfilefo.h>
00035 #include <dcmetinf.h>
00036 #include <dcdatset.h>
00037 #include <dctagkey.h>
00038 #include <dcdeftag.h>
00039 #include <dcstack.h>
00040 #include <diinpxt.h>
00041 
00042 #include "vil_dicom_stream.h"
00043 //
00044 //Believe it or not some dicom images have a mixed endian encoding.
00045 // e.g. mixed (7fe0,0010) OW 30f8 vs unmixed (7fe0,0010) OW f830
00046 //The header is little endian and the data is big endian!! There doesn't
00047 //seem to be a way of telling that this is the case. The DCM library
00048 //reports that the  TransferSyntax is "LittleEndianImplicit", which isn't helpful.
00049 // This is a hack to be able to read such files
00050 //#define MIXED_ENDIAN
00051 // Another hack to remove the offset of -1024 needed to calibrate HU. Otherwise
00052 // this reader converts the image to floating point, which may not be desired.
00053 //#define NO_OFFSET
00054 
00055 char const* vil_dicom_format_tag = "dicom";
00056 
00057 
00058 vil_image_resource_sptr vil_dicom_file_format::make_input_image(vil_stream* vs)
00059 {
00060   bool is_dicom = false;
00061 
00062   char magic[ DCM_MagicLen ];
00063   vs->seek( DCM_PreambleLen );
00064   if ( vs->read( magic, DCM_MagicLen ) == DCM_MagicLen ) {
00065     if ( vcl_strncmp( magic, DCM_Magic, DCM_MagicLen ) == 0 ) {
00066       is_dicom = true;
00067     }
00068   }
00069 
00070   if ( is_dicom )
00071     return new vil_dicom_image( vs );
00072   else
00073     return 0;
00074 }
00075 
00076 vil_image_resource_sptr vil_dicom_file_format::make_output_image(vil_stream* /*vs*/,
00077                                                                  unsigned /*ni*/,
00078                                                                  unsigned /*nj*/,
00079                                                                  unsigned /*nplanes*/,
00080                                                                  vil_pixel_format)
00081 {
00082   vcl_cerr << "ERROR: vil_dicom_file doesn't support output yet\n";
00083   return 0;
00084 #if 0
00085 
00086   if (nplanes != 1 || format != VIL_PIXEL_FORMAT_INT_32)
00087   {
00088     vcl_cerr << "ERROR: vil_dicom_file_format::make_output_image\n"
00089              << "       Can only create DICOM images with a single plane\n"
00090              << "       and 32-bit integer pixels\n";
00091     return 0;
00092   }
00093   return new vil_dicom_image(vs, ni, nj, nplanes, format);
00094 #endif
00095 }
00096 
00097 char const* vil_dicom_file_format::tag() const
00098 {
00099   return vil_dicom_format_tag;
00100 }
00101 
00102 
00103 // ===========================================================================
00104 // helper routines defined at end
00105 
00106 static
00107 void
00108 read_header( DcmObject* dataset, vil_dicom_header_info& i );
00109 
00110 static
00111 void
00112 read_pixels_into_buffer(DcmPixelData* pixels,
00113                         unsigned num_samples,
00114                         Uint16 alloc,
00115                         Uint16 stored,
00116                         Uint16 high,
00117                         Uint16 rep,
00118                         Float64 slope,
00119                         Float64 intercept,
00120                         vil_memory_chunk_sptr& out_buf,
00121                         vil_pixel_format& out_format);
00122 
00123 
00124 vil_dicom_image::vil_dicom_image(vil_stream* vs)
00125   : pixels_( 0 )
00126 {
00127   vil_dicom_header_info_clear( header_ );
00128 
00129   vil_dicom_stream_input dcis( vs );
00130 
00131   DcmFileFormat ffmt;
00132   ffmt.transferInit();
00133   OFCondition cond = ffmt.read( dcis );
00134   ffmt.transferEnd();
00135 
00136   if ( cond != EC_Normal ) {
00137     vcl_cerr << "vil_dicom ERROR: could not read file (" << cond.text() << ")\n"
00138              << "And the error code is: " << cond.code() << vcl_endl;
00139     //if (cond.code() != 4)
00140       return;
00141   }
00142 
00143   DcmDataset& dset = *ffmt.getDataset();
00144   read_header( &dset, header_ );
00145 
00146   //correct known manufacturers' drop-offs in header data!
00147   correct_manufacturer_discrepancies();
00148 
00149   // I don't know (yet) how to deal with look up tables. (Without the
00150   // tables, the pixel values represent actual measurements.)
00151   //
00152   if ( dset.tagExists( DCM_ModalityLUTSequence ) ) {
00153     vcl_cerr << "vil_dicom ERROR: don't know (yet) how to handle modality LUTs\n";
00154     return;
00155   }
00156 
00157   // If no ModalityLUT is present, I think the slope and intercept are
00158   // required. However, it seems that some DICOM images don't, so
00159   // assume the identity relationship.
00160   //
00161   Float64 slope, intercept;
00162   if ( dset.findAndGetFloat64( DCM_RescaleSlope, slope ) != EC_Normal )
00163     slope = 1;
00164   if ( dset.findAndGetFloat64( DCM_RescaleIntercept, intercept ) != EC_Normal )
00165     intercept = 0;
00166 
00167   // Gather the storage format info
00168 
00169 #define Stringify( v ) #v
00170 #define MustRead( func, key, var )                                                     \
00171   do {                                                                                 \
00172     if ( dset. func( key, var ) != EC_Normal ) {                                       \
00173       vcl_cerr << "vil_dicom ERROR: couldn't read " Stringify(key) "; can't handle\n"; \
00174       return;                                                                          \
00175   }} while (false)
00176 
00177   Uint16 bits_alloc, bits_stored, high_bit, pixel_rep;
00178 
00179   MustRead( findAndGetUint16, DCM_BitsAllocated, bits_alloc );
00180   MustRead( findAndGetUint16, DCM_BitsStored, bits_stored );
00181   MustRead( findAndGetUint16, DCM_HighBit, high_bit );
00182   MustRead( findAndGetUint16, DCM_PixelRepresentation, pixel_rep );
00183 
00184 #undef MustRead
00185 #undef Stringify
00186 
00187   // The pixels buffer will eventually be assigned to pixel_buf, and
00188   // the pixel format written into pixel_format.
00189   //
00190   vil_memory_chunk_sptr pixel_buf;
00191   vil_pixel_format pixel_format = VIL_PIXEL_FORMAT_UNKNOWN;
00192 
00193   // First, read in the bytes and interpret them appropriately
00194   //
00195   {
00196     DcmPixelData* pixels = 0;
00197     DcmStack stack;
00198     if ( dset.search( DCM_PixelData, stack, ESM_fromHere, true ) == EC_Normal )
00199     {
00200       if ( stack.card() == 0 ) {
00201         vcl_cerr << "vil_dicom ERROR: no pixel data found\n";
00202         return;
00203       }
00204       else {
00205         assert( stack.top()->ident() == EVR_PixelData );
00206         pixels = static_cast<DcmPixelData*>(stack.top());
00207       }
00208     }
00209     unsigned num_samples = ni() * nj() * nplanes();
00210     read_pixels_into_buffer(pixels, num_samples,
00211                             bits_alloc, bits_stored, high_bit, pixel_rep,
00212                             slope, intercept,
00213                             pixel_buf, pixel_format);
00214   }
00215 
00216   // Create an image resource to manage the pixel buffer
00217   //
00218 #define DOCASE( fmt )                                                \
00219       case fmt: {                                                    \
00220         typedef vil_pixel_format_type_of<fmt>::component_type T;     \
00221         pixels_ = vil_new_image_resource_of_view(                    \
00222                     vil_image_view<T>(pixel_buf,                     \
00223                                       (T*)pixel_buf->data(),         \
00224                                       ni(), nj(), nplanes(),         \
00225                                       nplanes(), ni()*nplanes(), 1));\
00226       } break
00227 
00228   switch ( pixel_format ) {
00229     DOCASE( VIL_PIXEL_FORMAT_UINT_16 );
00230     DOCASE( VIL_PIXEL_FORMAT_INT_16 );
00231     DOCASE( VIL_PIXEL_FORMAT_BYTE );
00232     DOCASE( VIL_PIXEL_FORMAT_SBYTE );
00233     DOCASE( VIL_PIXEL_FORMAT_FLOAT );
00234     default: vcl_cerr << "vil_dicom ERROR: unexpected pixel format\n";
00235   }
00236 #undef DOCASE
00237 }
00238 
00239 
00240 bool vil_dicom_image::get_property(char const* tag, void* value) const
00241 {
00242   if (vcl_strcmp(vil_property_quantisation_depth, tag)==0)
00243   {
00244     if (value)
00245       *static_cast<unsigned int*>(value) = header_.stored_bits_;
00246     return true;
00247   }
00248 
00249   if (vcl_strcmp(vil_property_pixel_size, tag)==0 && value!=0)
00250   {
00251     float *pixel_size = static_cast<float*>(value);
00252     pixel_size[0] = header_.spacing_x_ / 1000.0f;
00253     pixel_size[1] = header_.spacing_y_ / 1000.0f;
00254     return true;
00255   }
00256 
00257   // Need to write lots of access code for the dicom header.
00258   return false;
00259 }
00260 
00261 char const* vil_dicom_image::file_format() const
00262 {
00263   return vil_dicom_format_tag;
00264 }
00265 
00266 vil_dicom_image::vil_dicom_image(vil_stream* /*vs*/, unsigned ni, unsigned nj,
00267                                  unsigned nplanes, vil_pixel_format format)
00268 {
00269   assert(!"vil_dicom_image doesn't yet support output");
00270 
00271   assert(nplanes == 1 && format == VIL_PIXEL_FORMAT_INT_32);
00272   header_.size_x_ = ni;
00273   header_.size_y_ = nj;
00274   header_.size_z_ = 1;
00275 }
00276 
00277 vil_dicom_image::~vil_dicom_image()
00278 {
00279 }
00280 
00281 unsigned vil_dicom_image::nplanes() const
00282 {
00283   return header_.pix_samps_;
00284 }
00285 
00286 unsigned vil_dicom_image::ni() const
00287 {
00288   return header_.size_x_;
00289 }
00290 
00291 unsigned vil_dicom_image::nj() const
00292 {
00293   return header_.size_y_;
00294 }
00295 
00296 enum vil_pixel_format vil_dicom_image::pixel_format() const
00297 {
00298   return pixels_ ? pixels_->pixel_format() : VIL_PIXEL_FORMAT_UNKNOWN;
00299 }
00300 
00301 vil_image_view_base_sptr vil_dicom_image::get_copy_view(
00302   unsigned x0, unsigned nx, unsigned y0, unsigned ny) const
00303 {
00304   return pixels_ ? pixels_->get_copy_view( x0, nx, y0, ny ) : 0;
00305 }
00306 
00307 vil_image_view_base_sptr vil_dicom_image::get_view(
00308   unsigned x0, unsigned nx, unsigned y0, unsigned ny) const
00309 {
00310   return pixels_ ? pixels_->get_view( x0, nx, y0, ny ) : 0;
00311 }
00312 
00313 bool vil_dicom_image::put_view(const vil_image_view_base& view,
00314                                unsigned x0, unsigned y0)
00315 {
00316   assert(!"vil_dicom_image doesn't yet support output yet");
00317 
00318   if (!view_fits(view, x0, y0))
00319   {
00320     vil_exception_warning(vil_exception_out_of_bounds("vil_dicom_image::put_view"));
00321     return false;
00322   }
00323 
00324   return false;
00325 }
00326 
00327 // ===========================================================================
00328 //MANUFACTURER SPECIFIC TWEAKS
00329 //--- Add any further manufacturer specific tweaks in this section,
00330 // but if it all gets out of hand, then we will need some derived classes which should attempt to read first
00331 // ===========================================================================
00332 
00333 //:correct known manufacturers drop-offs in header data!
00334 //For example Hologic encode pixel-size in the imageComment!
00335 //NB if this section starts bloating, use derived classes which override correct_manufacturer_discrepancies
00336 void vil_dicom_image::correct_manufacturer_discrepancies()
00337 {
00338     //If manufacturer is Hologic and it's a QDR or Discovery model DXA scanner...
00339   if ( ( (header_.manufacturer_ == "HOLOGIC") || (header_.manufacturer_ == "Hologic") ) &&
00340        ( (header_.model_name_.find("QDR") != header_.model_name_.npos ) ||
00341          (header_.model_name_.find("Discovery") != header_.model_name_.npos )         ) )
00342   {
00343     //Hologic QDR Bone Densitometry source - set (default) pixel spacing from private format image comments
00344     float xPixelSize=1.0;
00345     float yPixelSize=1.0;
00346     if (interpret_hologic_header(xPixelSize,yPixelSize))
00347     {
00348       header_.spacing_x_ = xPixelSize;
00349       header_.spacing_y_ = yPixelSize;
00350     }
00351   }
00352 }
00353 
00354 //:try and interpret the Hologic comments section to extract pixel size
00355 bool vil_dicom_image::interpret_hologic_header(float& xpixSize, float& ypixSize)
00356 {
00357   //The magic internal Hologic tags used within their vast "Image Comments"
00358   //which is used as a cop-out from sensible DICOM conformance
00359   static const vcl_string HOLOGIC_PixelXSizeMM = "<PixelXSizeMM>";
00360   static const vcl_string HOLOGIC_PixelXSizeMM_END = "</PixelXSizeMM>";
00361   static const vcl_string HOLOGIC_PixelYSizeMM = "<PixelYSizeMM>";
00362   static const vcl_string HOLOGIC_PixelYSizeMM_END = "</PixelYSizeMM>";
00363 
00364   vcl_string src = header_.image_comments_;
00365   //Find start of x pixel size sub-text
00366   vcl_size_t ipxStart = src.find(HOLOGIC_PixelXSizeMM);
00367   if (ipxStart==src.npos) return false;
00368 
00369   //Find end of x pixel size sub-text
00370   vcl_size_t ipxEnd = src.find(HOLOGIC_PixelXSizeMM_END,ipxStart);
00371   if (ipxEnd==src.npos) return false;
00372 
00373   //Extract just the numerical part of the text
00374   vcl_string strPixelXSizeMM="";
00375   ipxStart+= HOLOGIC_PixelXSizeMM.size();
00376   strPixelXSizeMM.append(src,ipxStart, ipxEnd-ipxStart);
00377 
00378   if (strPixelXSizeMM.size()>0)
00379   {
00380     //Translate string to number
00381     vcl_stringstream translate_is(strPixelXSizeMM,vcl_stringstream::in);
00382     translate_is>>xpixSize;
00383     if (!translate_is) return false;
00384     if (xpixSize<=0.0 || xpixSize>=1.0E6)
00385       return false; //Don't believe crazy values
00386   }
00387   else
00388   {
00389     return false; //No x pixel value present between the tags
00390   }
00391 
00392   //Find start of y pixel size sub-text
00393   vcl_size_t ipyStart = src.find(HOLOGIC_PixelYSizeMM);
00394   if (ipyStart==src.npos) return false;
00395 
00396   //Find end of y pixel size sub-text
00397   vcl_size_t ipyEnd = src.find(HOLOGIC_PixelYSizeMM_END,ipyStart);
00398   if (ipyEnd==src.npos) return false;
00399 
00400   //Extract just the numerical part of the text
00401   vcl_string strPixelYSizeMM="";
00402   ipyStart+= HOLOGIC_PixelYSizeMM.size();
00403   strPixelYSizeMM.append(src,ipyStart, ipyEnd-ipyStart);
00404 
00405   if (strPixelYSizeMM.size()>0)
00406   {
00407     //Translate string to number
00408     vcl_stringstream translate_is(strPixelYSizeMM,vcl_stringstream::in);
00409     translate_is>>ypixSize;
00410     if (!translate_is) return false;
00411     if (ypixSize<=0.0 || ypixSize>=1.0E6)
00412       return false; //Don't believe crazy values
00413   }
00414   else
00415   {
00416     return false; //No y pixel value present between the tags
00417   }
00418 
00419   return true;    //It all worked
00420 }
00421 
00422 
00423 // ===========================================================================
00424 //                                                             HELPER ROUTINES
00425 // ===========================================================================
00426 
00427 
00428 static
00429 DcmElement*
00430 find_element( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element )
00431 {
00432   DcmElement* result = 0;
00433   DcmTagKey key( group, element );
00434   DcmStack stack;
00435   if ( dset->search( key, stack, ESM_fromHere, true ) == EC_Normal )
00436   {
00437     if ( stack.card() == 0 ) {
00438       vcl_cerr << "vil_dicom ERROR: no results on stack\n";
00439     }
00440     else {
00441       result = static_cast<DcmElement*>(stack.top());
00442       if ( result->getVM() == 0 ) {
00443         // header present, but has no value == header not present
00444         result = 0;
00445       }
00446     }
00447   }
00448 
00449   return result;
00450 }
00451 
00452 // anonymous namespace for helper routines
00453 namespace
00454 {
00455   // Specializations of this template contains code to convert from the
00456   // given VR type (template parameter) to the given C++ type (4th
00457   // parameter of the function "proc").
00458   //
00459   template <int T /*vil_dicom_header_vr_type*/>
00460   struct try_set;
00461 
00462   // A general proc implementation that returns a string representation
00463   // of any VR.
00464   //
00465   struct try_set_to_string
00466   {
00467     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vcl_string& value ) {
00468       DcmElement* e = find_element( dset, group, element );
00469       if ( e )
00470       {
00471         OFString str;
00472         if ( e->getOFString( str, 0 ) != EC_Normal ) {
00473           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not string\n";
00474         }
00475         else {
00476           value = str.c_str();
00477         }
00478       }
00479     }
00480   };
00481 
00482   VCL_DEFINE_SPECIALIZATION
00483   struct try_set< vil_dicom_header_AE >
00484     : public try_set_to_string
00485   {
00486   };
00487 
00488   VCL_DEFINE_SPECIALIZATION
00489   struct try_set< vil_dicom_header_AS >
00490     : public try_set_to_string
00491   {
00492   };
00493 
00494   VCL_DEFINE_SPECIALIZATION
00495   struct try_set< vil_dicom_header_AT >
00496     : public try_set_to_string
00497   {
00498   };
00499 
00500   VCL_DEFINE_SPECIALIZATION
00501   struct try_set< vil_dicom_header_CS >
00502     : public try_set_to_string
00503   {
00504   };
00505 
00506   VCL_DEFINE_SPECIALIZATION
00507   struct try_set< vil_dicom_header_DA >
00508   {
00509     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, long& value ) {
00510       DcmElement* e = find_element( dset, group, element );
00511       if ( e )
00512       {
00513         OFString str;
00514         if ( e->getOFString( str, 0 ) != EC_Normal ) {
00515           vcl_cerr << "Warning: value of ("<<group<<','<<element<<") is not string\n";
00516         }
00517         else {
00518           value = vcl_atol( str.c_str() );
00519         }
00520       }
00521     }
00522   };
00523 
00524   VCL_DEFINE_SPECIALIZATION
00525   struct try_set< vil_dicom_header_DS >
00526   {
00527     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, float& value ) {
00528       DcmElement* e = find_element( dset, group, element );
00529       if ( e )
00530       {
00531         OFString str;
00532         if ( e->getOFString( str, 0 ) != EC_Normal ) {
00533           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not string\n";
00534         }
00535         else {
00536           value = static_cast<float>( vcl_atof( str.c_str() ) );
00537         }
00538       }
00539     }
00540 
00541     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vcl_vector<float>& value ) {
00542       DcmElement* e = find_element( dset, group, element );
00543       if ( e ) {
00544         for ( unsigned pos = 0; pos < e->getVM(); ++pos )
00545         {
00546           OFString str;
00547           if ( e->getOFString( str, pos ) != EC_Normal ) {
00548             vcl_cerr << "Warning: value of ("<<group<<','<<element<<") at " << pos << " is not string\n";
00549           }
00550           else {
00551             value.push_back( static_cast<float>( vcl_atof( str.c_str() ) ) );
00552           }
00553         }
00554       }
00555     }
00556   };
00557 
00558   VCL_DEFINE_SPECIALIZATION
00559   struct try_set< vil_dicom_header_FD >
00560   {
00561     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vxl_ieee_64& value ) {
00562       DcmElement* e = find_element( dset, group, element );
00563       if ( e ) {
00564         if ( e->getFloat64( value ) != EC_Normal ) {
00565           vcl_cerr << "Warning: value of ("<<group<<','<<element<<") is not Float64\n";
00566         }
00567       }
00568     }
00569   };
00570 
00571   VCL_DEFINE_SPECIALIZATION
00572   struct try_set< vil_dicom_header_FL >
00573   {
00574     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vxl_ieee_32& value ) {
00575       DcmElement* e = find_element( dset, group, element );
00576       if ( e ) {
00577         if ( e->getFloat32( value ) != EC_Normal ) {
00578           vcl_cerr << "Warning: value of ("<<group<<','<<element<<") is not Float32\n";
00579         }
00580       }
00581     }
00582   };
00583 
00584   VCL_DEFINE_SPECIALIZATION
00585   struct try_set< vil_dicom_header_IS >
00586   {
00587     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, long& value ) {
00588       DcmElement* e = find_element( dset, group, element );
00589       if ( e )
00590       {
00591         OFString str;
00592         if ( e->getOFString( str, 0 ) != EC_Normal ) {
00593           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not string\n";
00594         }
00595         else {
00596           value = vcl_atol( str.c_str() );
00597         }
00598       }
00599     }
00600   };
00601 
00602   VCL_DEFINE_SPECIALIZATION
00603   struct try_set< vil_dicom_header_LO >
00604     : public try_set_to_string
00605   {
00606   };
00607 
00608   VCL_DEFINE_SPECIALIZATION
00609   struct try_set< vil_dicom_header_LT >
00610     : public try_set_to_string
00611   {
00612   };
00613 
00614   VCL_DEFINE_SPECIALIZATION
00615   struct try_set< vil_dicom_header_OB >
00616     : public try_set_to_string
00617   {
00618   };
00619 
00620   VCL_DEFINE_SPECIALIZATION
00621   struct try_set< vil_dicom_header_OW >
00622     : public try_set_to_string
00623   {
00624   };
00625 
00626   VCL_DEFINE_SPECIALIZATION
00627   struct try_set< vil_dicom_header_PN >
00628     : public try_set_to_string
00629   {
00630   };
00631 
00632   VCL_DEFINE_SPECIALIZATION
00633   struct try_set< vil_dicom_header_SH >
00634     : public try_set_to_string
00635   {
00636   };
00637 
00638   VCL_DEFINE_SPECIALIZATION
00639   struct try_set< vil_dicom_header_SL >
00640   {
00641     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vxl_sint_32& value ) {
00642       DcmElement* e = find_element( dset, group, element );
00643       if ( e ) {
00644         if ( e->getSint32( reinterpret_cast<Sint32&>(value) ) != EC_Normal ) {
00645           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not Sint32\n";
00646         }
00647       }
00648     }
00649   };
00650 
00651   VCL_DEFINE_SPECIALIZATION
00652   struct try_set< vil_dicom_header_SQ >
00653     : public try_set_to_string
00654   {
00655   };
00656 
00657   VCL_DEFINE_SPECIALIZATION
00658   struct try_set< vil_dicom_header_SS >
00659   {
00660     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vxl_sint_16& value ) {
00661       DcmElement* e = find_element( dset, group, element );
00662       if ( e ) {
00663         if ( e->getSint16( reinterpret_cast<Sint16&>(value) ) != EC_Normal ) {
00664           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not Sint16\n";
00665         }
00666       }
00667     }
00668   };
00669 
00670   VCL_DEFINE_SPECIALIZATION
00671   struct try_set< vil_dicom_header_ST >
00672     : public try_set_to_string
00673   {
00674   };
00675 
00676   VCL_DEFINE_SPECIALIZATION
00677   struct try_set< vil_dicom_header_TM >
00678   {
00679     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, float& value ) {
00680       DcmElement* e = find_element( dset, group, element );
00681       if ( e )
00682       {
00683         OFString str;
00684         if ( e->getOFString( str, 0 ) != EC_Normal ) {
00685           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not string\n";
00686         }
00687         else {
00688           value = static_cast<float>( vcl_atof( str.c_str() ) );
00689         }
00690       }
00691     }
00692   };
00693 
00694   VCL_DEFINE_SPECIALIZATION
00695   struct try_set< vil_dicom_header_UI >
00696     : public try_set_to_string
00697   {
00698   };
00699 
00700   VCL_DEFINE_SPECIALIZATION
00701   struct try_set< vil_dicom_header_UL >
00702   {
00703     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vxl_uint_32& value ) {
00704       DcmElement* e = find_element( dset, group, element );
00705       if ( e ) {
00706         if ( e->getUint32( reinterpret_cast<Uint32&>(value) ) != EC_Normal ) {
00707           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not Uint32\n";
00708         }
00709       }
00710     }
00711   };
00712 
00713   VCL_DEFINE_SPECIALIZATION
00714   struct try_set< vil_dicom_header_UN >
00715     : public try_set_to_string
00716   {
00717   };
00718 
00719   VCL_DEFINE_SPECIALIZATION
00720   struct try_set< vil_dicom_header_US >
00721   {
00722     static void proc( DcmObject* dset, vxl_uint_16 group, vxl_uint_16 element, vxl_uint_16& value ) {
00723       DcmElement* e = find_element( dset, group, element );
00724       if ( e ) {
00725         if ( e->getUint16( value ) != EC_Normal ) {
00726           vcl_cerr << "vil_dicom Warning: value of ("<<group<<','<<element<<") is not Uint16\n";
00727         }
00728       }
00729     }
00730   };
00731 
00732   VCL_DEFINE_SPECIALIZATION
00733   struct try_set< vil_dicom_header_UT >
00734     : public try_set_to_string
00735   {
00736   };
00737 } // end anonymous namespace
00738 
00739 static
00740 void
00741 read_header( DcmObject* f, vil_dicom_header_info& i )
00742 {
00743   vxl_uint_16 group;
00744 
00745 #define ap_join(A,B) A ## B
00746 #define ap_type(X) ap_join( vil_dicom_header_, X )
00747 #define ap_el(X) ap_join( VIL_DICOM_HEADER_, X )
00748 
00749   group = VIL_DICOM_HEADER_IDENTIFYINGGROUP;
00750   try_set< ap_type(CS) >::proc( f, group, ap_el(IDIMAGETYPE),         i.image_id_type_ ); // It's the image type
00751   try_set< ap_type(UI) >::proc( f, group, ap_el(IDSOPCLASSID),        i.sop_cl_uid_ ); // It's the SOP class ID
00752   try_set< ap_type(UI) >::proc( f, group, ap_el(IDSOPINSTANCEID),     i.sop_in_uid_ ); // It's the SOP instance ID
00753   try_set< ap_type(DA) >::proc( f, group, ap_el(IDSTUDYDATE),         i.study_date_ ); // It's the study date
00754   try_set< ap_type(DA) >::proc( f, group, ap_el(IDSERIESDATE),        i.series_date_ ); // It's the series date
00755   try_set< ap_type(DA) >::proc( f, group, ap_el(IDACQUISITIONDATE),   i.acquisition_date_ ); // It's the acquisition date
00756   try_set< ap_type(DA) >::proc( f, group, ap_el(IDIMAGEDATE),         i.image_date_ ); // It's the image date
00757   try_set< ap_type(TM) >::proc( f, group, ap_el(IDSTUDYTIME),         i.study_time_ ); // It's the study time
00758   try_set< ap_type(TM) >::proc( f, group, ap_el(IDSERIESTIME),        i.series_time_ ); // It's the series time
00759   try_set< ap_type(TM) >::proc( f, group, ap_el(IDACQUISITIONTIME),   i.acquisition_time_ ); // It's the acquisition time
00760   try_set< ap_type(TM) >::proc( f, group, ap_el(IDIMAGETIME),         i.image_time_ ); // It's the image time
00761   try_set< ap_type(SH) >::proc( f, group, ap_el(IDACCESSIONNUMBER),   i.accession_number_ ); // It's the accession number
00762   try_set< ap_type(CS) >::proc( f, group, ap_el(IDMODALITY),          i.modality_ ); // It's the imaging modality
00763   try_set< ap_type(LO) >::proc( f, group, ap_el(IDMANUFACTURER),      i.manufacturer_ ); // It's the manufacturer name
00764   try_set< ap_type(LO) >::proc( f, group, ap_el(IDINSTITUTIONNAME),   i.institution_name_ ); // It's the institution name
00765   try_set< ap_type(ST) >::proc( f, group, ap_el(IDINSTITUTIONADDRESS),i.institution_addr_ ); // It's the institution address
00766   try_set< ap_type(PN) >::proc( f, group, ap_el(IDREFERRINGPHYSICIAN),i.ref_phys_name_ ); // It's the referring physician's name
00767   try_set< ap_type(SH) >::proc( f, group, ap_el(IDSTATIONNAME),       i.station_name_ ); // It's the imaging station name
00768   try_set< ap_type(LO) >::proc( f, group, ap_el(IDSTUDYDESCRIPTION),  i.study_desc_ ); // It's the study description
00769   try_set< ap_type(LO) >::proc( f, group, ap_el(IDSERIESDESCRIPTION), i.series_desc_ ); // It's the series description
00770   try_set< ap_type(PN) >::proc( f, group, ap_el(IDATTENDINGPHYSICIAN),i.att_phys_name_); // It's the name of the attending physician
00771   try_set< ap_type(PN) >::proc( f, group, ap_el(IDOPERATORNAME),      i.operator_name_ ); // It's the name of the scanner operator
00772   try_set< ap_type(LO) >::proc( f, group, ap_el(IDMANUFACTURERMODEL), i.model_name_ ); // It's the scanner model
00773 
00774   group = VIL_DICOM_HEADER_PATIENTINFOGROUP;
00775   try_set< ap_type(PN) >::proc( f, group, ap_el(PIPATIENTNAME),     i.patient_name_ ); // It's the patient's name
00776   try_set< ap_type(LO) >::proc( f, group, ap_el(PIPATIENTID),       i.patient_id_ ); // It's the patient's id
00777   try_set< ap_type(DA) >::proc( f, group, ap_el(PIPATIENTBIRTHDATE),i.patient_dob_ ); // It's the patient's date of birth
00778   try_set< ap_type(CS) >::proc( f, group, ap_el(PIPATIENTSEX),      i.patient_sex_ ); // It's the patient's sex
00779   try_set< ap_type(AS) >::proc( f, group, ap_el(PIPATIENTAGE),      i.patient_age_ ); // It's the patient's age
00780   try_set< ap_type(DS) >::proc( f, group, ap_el(PIPATIENTWEIGHT),   i.patient_weight_ ); // It's the patient's weight
00781   try_set< ap_type(LT) >::proc( f, group, ap_el(PIPATIENTHISTORY),  i.patient_hist_ ); // It's the patient's history
00782 
00783   group = VIL_DICOM_HEADER_ACQUISITIONGROUP;
00784   try_set< ap_type(CS) >::proc( f, group, ap_el(AQSCANNINGSEQUENCE),      i.scanning_seq_ ); // It's the scanning sequence
00785   try_set< ap_type(CS) >::proc( f, group, ap_el(AQSEQUENCEVARIANT),       i.sequence_var_ ); // It's the sequence variant
00786   try_set< ap_type(CS) >::proc( f, group, ap_el(AQSCANOPTIONS),           i.scan_options_ ); // It's the scan options
00787   try_set< ap_type(CS) >::proc( f, group, ap_el(AQMRACQUISITIONTYPE),     i.mr_acq_type_ ); // It's the MR acquisition type
00788   try_set< ap_type(SH) >::proc( f, group, ap_el(AQSEQUENCENAME),          i.sequence_name_ ); // It's the sequence name
00789   try_set< ap_type(CS) >::proc( f, group, ap_el(AQANGIOFLAG),             i.angio_flag_ ); // It's the angio flag
00790   try_set< ap_type(DS) >::proc( f, group, ap_el(AQSLICETHICKNESS),        i.slice_thickness_ ); // It's the slice thickness
00791   try_set< ap_type(DS) >::proc( f, group, ap_el(AQREPETITIONTIME),        i.repetition_time_ ); // It's the repetition time
00792   try_set< ap_type(DS) >::proc( f, group, ap_el(AQECHOTIME),              i.echo_time_ ); // It's the echo time
00793   try_set< ap_type(DS) >::proc( f, group, ap_el(AQINVERSIONTIME),         i.inversion_time_ ); // It's the inversion time
00794   try_set< ap_type(DS) >::proc( f, group, ap_el(AQNUMBEROFAVERAGES),      i.number_of_averages_ ); // It's the number of averages
00795   try_set< ap_type(IS) >::proc( f, group, ap_el(AQECHONUMBERS),           i.echo_numbers_ ); // It's the echo numbers
00796   try_set< ap_type(DS) >::proc( f, group, ap_el(AQMAGNETICFIELDSTRENGTH), i.mag_field_strength_);// It's the magnetic field strength
00797   try_set< ap_type(DS) >::proc( f, group, ap_el(AQSLICESPACING),          i.spacing_slice_ ); // It's the slice spacing
00798   try_set< ap_type(IS) >::proc( f, group, ap_el(AQECHOTRAINLENGTH),       i.echo_train_length_ ); // It's the echo train length
00799   try_set< ap_type(DS) >::proc( f, group, ap_el(AQPIXELBANDWIDTH),        i.pixel_bandwidth_ ); // It's the pixel bandwidth
00800   try_set< ap_type(LO) >::proc( f, group, ap_el(AQSOFTWAREVERSION),       i.software_vers_ ); // It's the scanner software version
00801   try_set< ap_type(LO) >::proc( f, group, ap_el(AQPROTOCOLNAME),          i.protocol_name_ ); // It's the protocol name
00802   try_set< ap_type(IS) >::proc( f, group, ap_el(AQHEARTRATE),             i.heart_rate_ ); // It's the heart rate
00803   try_set< ap_type(IS) >::proc( f, group, ap_el(AQCARDIACNUMBEROFIMAGES), i.card_num_images_ ); // It's the cardiac number of images
00804   try_set< ap_type(IS) >::proc( f, group, ap_el(AQTRIGGERWINDOW),         i.trigger_window_ ); // It's the trigger window
00805   try_set< ap_type(DS) >::proc( f, group, ap_el(AQRECONTRUCTIONDIAMETER), i.reconst_diameter_ ); // It's the reconstruction diameter
00806   try_set< ap_type(SH) >::proc( f, group, ap_el(AQRECEIVINGCOIL),         i.receiving_coil_ ); // It's the receiving coil
00807   try_set< ap_type(CS) >::proc( f, group, ap_el(AQPHASEENCODINGDIRECTION),i.phase_enc_dir_ ); // It's the phase encoding direction
00808   try_set< ap_type(DS) >::proc( f, group, ap_el(AQFLIPANGLE),             i.flip_angle_ ); // It's the flip angle
00809   try_set< ap_type(DS) >::proc( f, group, ap_el(AQSAR),                   i.sar_ ); // It's the sar
00810   try_set< ap_type(CS) >::proc( f, group, ap_el(AQPATIENTPOSITION),       i.patient_pos_ ); // It's the patient position
00811 
00812   group = VIL_DICOM_HEADER_RELATIONSHIPGROUP;
00813   try_set< ap_type(UI) >::proc( f, group, ap_el(RSSTUDYINSTANCEUID),   i.stud_ins_uid_ ); // It's the study instance id
00814   try_set< ap_type(UI) >::proc( f, group, ap_el(RSSERIESINSTANCEUID),  i.ser_ins_uid_ ); // It's the series instance id
00815   try_set< ap_type(SH) >::proc( f, group, ap_el(RSSTUDYID),            i.study_id_ ); // It's the study id
00816   try_set< ap_type(IS) >::proc( f, group, ap_el(RSSERIESNUMBER),       i.series_number_ ); // It's the series number
00817   try_set< ap_type(IS) >::proc( f, group, ap_el(RSAQUISITIONNUMBER),   i.acquisition_number_ ); // It's the acqusition number
00818   try_set< ap_type(IS) >::proc( f, group, ap_el(RSIMAGENUMBER),        i.image_number_ ); // It's the image number
00819   try_set< ap_type(CS) >::proc( f, group, ap_el(RSPATIENTORIENTATION), i.pat_orient_ ); // It's the patient orientation
00820   try_set< ap_type(DS) >::proc( f, group, ap_el(RSIMAGEPOSITION),      i.image_pos_ ); // It's the image position
00821   try_set< ap_type(DS) >::proc( f, group, ap_el(RSIMAGEORIENTATION),   i.image_orient_ ); // It's the image orientation
00822   try_set< ap_type(UI) >::proc( f, group, ap_el(RSFRAMEOFREFERENCEUID),i.frame_of_ref_ ); // It's the frame of reference uid
00823   try_set< ap_type(IS) >::proc( f, group, ap_el(RSIMAGESINACQUISITION),i.images_in_acq_); // the number of images in the acquisition
00824   try_set< ap_type(LO) >::proc( f, group, ap_el(RSPOSITIONREFERENCE),  i.pos_ref_ind_ ); // It's the position reference
00825   try_set< ap_type(LT) >::proc( f, group, ap_el(RSIMAGECOMMENTS),      i.image_comments_ ); // It's the image comments
00826 
00827   group = VIL_DICOM_HEADER_IMAGEGROUP;
00828   try_set< ap_type(US) >::proc( f, group, ap_el(IMSAMPLESPERPIXEL),    i.pix_samps_ ); // It's the samples per pixel
00829   try_set< ap_type(CS) >::proc( f, group, ap_el(IMPHOTOMETRICINTERP),  i.photo_interp_ ); // It's the photometric interpretation
00830   try_set< ap_type(US) >::proc( f, group, ap_el(IMROWS),               i.size_y_ ); // It's the rows
00831   try_set< ap_type(US) >::proc( f, group, ap_el(IMCOLUMNS),            i.size_x_ ); // It's the columns
00832   try_set< ap_type(US) >::proc( f, group, ap_el(IMPLANES),             i.size_z_ ); // It's the planes
00833   try_set< ap_type(US) >::proc( f, group, ap_el(IMBITSALLOCATED),      i.allocated_bits_ ); // It's the allocated bits
00834   try_set< ap_type(US) >::proc( f, group, ap_el(IMBITSSTORED),         i.stored_bits_ ); // It's the stored bits info
00835   try_set< ap_type(US) >::proc( f, group, ap_el(IMHIGHBIT),            i.high_bit_ ); // It's the high bit
00836   try_set< ap_type(US) >::proc( f, group, ap_el(IMPIXELREPRESENTATION),i.pix_rep_ ); // It's the pixel representation
00837   try_set< ap_type(US) >::proc( f, group, ap_el(IMSMALLIMPIXELVALUE),  i.small_im_pix_val_ ); // It's the smallest image pixel value
00838   try_set< ap_type(US) >::proc( f, group, ap_el(IMLARGEIMPIXELVALUE),  i.large_im_pix_val_ ); // It's the largest image pixel value
00839   try_set< ap_type(US) >::proc( f, group, ap_el(IMPIXELPADDINGVALUE),  i.pixel_padding_val_ ); // It's the pixel padding value
00840   try_set< ap_type(DS) >::proc( f, group, ap_el(IMWINDOWCENTER),       i.window_centre_ ); // It's the window centre
00841   try_set< ap_type(DS) >::proc( f, group, ap_el(IMWINDOWWIDTH),        i.window_width_ ); // It's the window width
00842   try_set< ap_type(DS) >::proc( f, group, ap_el(IMRESCALEINTERCEPT),   i.res_intercept_ ); // It's the rescale intercept
00843   try_set< ap_type(DS) >::proc( f, group, ap_el(IMRESCALESLOPE),       i.res_slope_ ); // It's the rescale slope
00844 
00845   typedef vil_dicom_header_type_of<vil_dicom_header_DS>::type DS_type;
00846   vcl_vector<DS_type> ps;
00847   try_set< ap_type(DS) >::proc( f, group, ap_el(IMPIXELSPACING), ps );
00848   if ( ps.size() > 0 )
00849     i.spacing_x_ = ps[0];
00850   else
00851     i.spacing_x_ = 0;
00852   if ( ps.size() > 1 )
00853     i.spacing_y_ = ps[1];
00854   else
00855     i.spacing_y_ = i.spacing_x_;
00856 
00857   i.header_valid_ = true;
00858 
00859 #undef ap_join
00860 #undef ap_type
00861 #undef ap_el
00862 }
00863 
00864 
00865 // start anonymous namespace for helpers
00866 namespace
00867 {
00868   template<class InT>
00869   void
00870   convert_src_type( InT const*,
00871                     DcmPixelData* pixels,
00872                     unsigned num_samples,
00873                     Uint16 alloc,
00874                     Uint16 stored,
00875                     Uint16 high,
00876                     Uint16 rep,
00877                     DiInputPixel*& pixel_data,
00878                     vil_pixel_format& act_format )
00879   {
00880     if ( rep == 0 && stored <= 8 ) {
00881       act_format = VIL_PIXEL_FORMAT_BYTE;
00882       pixel_data = new DiInputPixelTemplate<InT,Uint8>( pixels, alloc, stored, high, 0, num_samples );
00883     }
00884     else if ( rep == 0 && stored <= 16 ) {
00885       act_format = VIL_PIXEL_FORMAT_UINT_16;
00886       pixel_data = new DiInputPixelTemplate<InT,Uint16>( pixels, alloc, stored, high, 0, num_samples );
00887     }
00888     else if ( rep == 1 && stored <= 8 ) {
00889       act_format = VIL_PIXEL_FORMAT_SBYTE;
00890       pixel_data = new DiInputPixelTemplate<InT,Sint8>( pixels, alloc, stored, high, 0, num_samples );
00891     }
00892     else if ( rep == 1 && stored <= 16 ) {
00893       act_format = VIL_PIXEL_FORMAT_INT_16;
00894       pixel_data = new DiInputPixelTemplate<InT,Sint16>( pixels, alloc, stored, high, 0, num_samples );
00895     }
00896   }
00897 
00898   template<class IntType, class OutType>
00899   void
00900   rescale_values( IntType const* int_begin,
00901                   unsigned num_samples,
00902                   OutType* float_begin,
00903                   Float64 slope, Float64 intercept )
00904   {
00905     IntType const* const int_end = int_begin + num_samples;
00906     for ( ; int_begin != int_end; ++int_begin, ++float_begin ) {
00907       *float_begin = static_cast<OutType>( *int_begin * slope + intercept );
00908     }
00909   }
00910 } // anonymous namespace
00911 #ifdef MIXED_ENDIAN
00912 static  unsigned short swap_short(unsigned short v)
00913 {
00914   return (v << 8)
00915        | (v >> 8);
00916 }
00917 
00918 static void swap_shorts(unsigned short *ip, unsigned short *op, int count)
00919 {
00920   while (count)
00921   {
00922     *op++ = swap_short(*ip++);
00923     count--;
00924   }
00925 }
00926 #endif //MIXED_ENDIAN
00927 static
00928 void
00929 read_pixels_into_buffer(DcmPixelData* pixels,
00930                         unsigned num_samples,
00931                         Uint16 alloc,
00932                         Uint16 stored,
00933                         Uint16 high,
00934                         Uint16 rep,
00935                         Float64 slope,
00936                         Float64 intercept,
00937                         vil_memory_chunk_sptr& out_buf,
00938                         vil_pixel_format& out_format)
00939 {
00940   // This will be the "true" pixel buffer type after the overlay
00941   // planes are removed and the pixel bits shifted to the lowest bits
00942   // of the bytes.
00943   //
00944   vil_pixel_format act_format = VIL_PIXEL_FORMAT_UNKNOWN;
00945 
00946   // First convert from the stored src pixels to the actual
00947   // pixels. This is an integral type to integral type conversion.
00948   // Make sure pixel_data is deleted before this function exits!
00949   //
00950   DiInputPixel* pixel_data = 0;
00951   if ( pixels->getVR() == EVR_OW ) {
00952     convert_src_type( (Uint16*)0, pixels, num_samples, alloc, stored, high, rep, pixel_data, act_format );
00953   }
00954   else {
00955     convert_src_type( (Uint8*)0, pixels, num_samples, alloc, stored, high, rep, pixel_data, act_format );
00956   }
00957 #ifdef MIXED_ENDIAN
00958 #ifdef NO_OFFSET
00959   slope = 1; intercept = 0;
00960   if (act_format == VIL_PIXEL_FORMAT_SBYTE)
00961     act_format = VIL_PIXEL_FORMAT_BYTE;
00962   if (act_format == VIL_PIXEL_FORMAT_INT_16)
00963     act_format = VIL_PIXEL_FORMAT_UINT_16;
00964 #endif //NO_OFFSET
00965   bool swap_data = false;
00966   unsigned short* temp1 = new unsigned short[num_samples];
00967   unsigned short* temp2 =
00968     reinterpret_cast<unsigned short*>(pixel_data->getData());
00969   swap_shorts(temp2, temp1, num_samples);
00970   vxl_byte* temp3 = reinterpret_cast<vxl_byte*>(temp1);
00971 #endif //MIXED_ENDIAN
00972   // On error, return without doing anything
00973   if ( pixel_data == 0 ) {
00974     return;
00975   }
00976 
00977   // The data has been copied and converted. Release the source.
00978   pixels->clear();
00979 
00980   // Now, the actual buffer is good, or else we need to rescale
00981   //
00982   if ( slope == 1 && intercept == 0 ) {
00983     out_format = act_format;
00984 
00985     // There isn't an easy way to wrap a vil_memory_chunk around the
00986     // converted pixel data, since we don't know the array type. If we
00987     // could pass a void* to vil_memory_chunk, it will call the delete
00988     // the buffer assuming a char[] array, which it may not be. This
00989     // causes undefined behaviour. For the moment, we take the hit and
00990     // do a memcpy.
00991     //
00992     out_buf = new vil_memory_chunk( num_samples * ((stored+7)/8), VIL_PIXEL_FORMAT_BYTE );
00993 #ifdef MIXED_ENDIAN
00994     vcl_memcpy( out_buf->data(), temp3, out_buf->size() );
00995 #else
00996     vcl_memcpy( out_buf->data(), pixel_data->getData(), out_buf->size() );
00997 #endif //MIXED_ENDIAN
00998   }
00999   else {
01000     out_buf = new vil_memory_chunk( num_samples * sizeof(float), VIL_PIXEL_FORMAT_FLOAT );
01001     out_format = VIL_PIXEL_FORMAT_FLOAT;
01002 #ifdef MIXED_ENDIAN
01003     void* in_begin = reinterpret_cast<void*>(temp1);
01004 #else
01005     void* in_begin = const_cast<void*>(pixel_data->getData());
01006 #endif //MIXED_ENDIAN
01007     float* out_begin = static_cast<float*>( out_buf->data() );
01008 
01009     switch ( act_format )
01010     {
01011      case VIL_PIXEL_FORMAT_BYTE:
01012       rescale_values( (vxl_byte*)in_begin, num_samples, out_begin, slope, intercept );
01013       break;
01014      case VIL_PIXEL_FORMAT_SBYTE:
01015       rescale_values( (vxl_sbyte*)in_begin, num_samples, out_begin, slope, intercept );
01016       break;
01017      case VIL_PIXEL_FORMAT_UINT_16:
01018       rescale_values( (vxl_uint_16*)in_begin, num_samples, out_begin, slope, intercept );
01019       break;
01020      case VIL_PIXEL_FORMAT_INT_16:
01021       rescale_values( (vxl_sint_16*)in_begin, num_samples, out_begin, slope, intercept );
01022       break;
01023      default:
01024       vcl_cerr << "vil_dicom ERROR: unexpected internal pixel format\n";
01025     }
01026   }
01027 
01028 #ifdef MIXED_ENDIAN
01029     delete [] temp1;
01030 #endif //MIXED_ENDIAN
01031 
01032   delete pixel_data;
01033 }
01034 
01035 #endif // HAS_DCMTK