contrib/mul/vil3d/file_formats/vil3d_analyze_format.cxx
Go to the documentation of this file.
00001 // This is mul/vil3d/file_formats/vil3d_analyze_format.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \brief Reader/Writer for analyze format images.
00008 // \author Tim Cootes - Manchester
00009 // This file contains classes for reading and writing analyze format images
00010 // Three key components are
00011 //   vil3d_analyze_header: Structure to contain header information
00012 //   vil3d_analyze_image: Resource object which interfaces to the file,
00013 //                        allowing reading and writing via the get_copy_image()
00014 //                        and put_image() functions
00015 //   vil3d_analyze_format: Object to create an appropriate vil3d_analyze_image
00016 //
00017 //   The main work of loading and saving happens in vil3d_analyze_image
00018 
00019 #include "vil3d_analyze_format.h"
00020 #include <vcl_cstring.h> // for std::strcmp() and std::memset()
00021 #include <vcl_cstdio.h>  // for std::sprintf
00022 #include <vcl_cstddef.h>  // for std::size_t
00023 #include <vil/vil_stream_fstream.h>
00024 #include <vil3d/vil3d_image_view.h>
00025 #include <vil3d/vil3d_new.h>
00026 #include <vil3d/vil3d_copy.h>
00027 #include <vil3d/vil3d_property.h>
00028 #include <vil3d/vil3d_image_resource.h>
00029 #include <vsl/vsl_binary_explicit_io.h>
00030 #include <vsl/vsl_indent.h>
00031 
00032 // ---- Utility functions for dealing with byte ordering ----
00033 // (Note: The use of this is currently guessed - need to check format)
00034 inline void swap16_for_big_endian(char *a, unsigned n)
00035 {
00036   for (unsigned i = 0; i < n * 2; i += 2)
00037   {
00038     char c = a[i]; a[i] = a[i+1]; a[i+1] = c;
00039   }
00040 }
00041 
00042 inline void swap32_for_big_endian(char *a, unsigned n)
00043 {
00044   for (unsigned i = 0; i < n * 4; i += 4)
00045   {
00046     char c= a[i]; a[i] = a[i+3]; a[i+3] = c;
00047     c = a[i+1]; a[i+1] = a[i+2]; a[i+2] = c;
00048   }
00049 }
00050 
00051 inline void swap64_for_big_endian(char *a, unsigned n)
00052 {
00053   for (unsigned i = 0; i < n * 8; i += 8)
00054   {
00055     char c= a[i]; a[i] = a[i+7]; a[i+7] = c;
00056     c = a[i+1]; a[i+1] = a[i+6]; a[i+6] = c;
00057     c = a[i+2]; a[i+2] = a[i+5]; a[i+5] = c;
00058     c = a[i+3]; a[i+3] = a[i+4]; a[i+4] = c;
00059   }
00060 }
00061 
00062 /*=========== Analyze header stuff ==========*/
00063 #define RD_AH_MAXHEADERSIZE         0xFFFF
00064 
00065 const int ObligatorySize = sizeof(vil3d_analyze_header::Key) +
00066                            sizeof(vil3d_analyze_header::Dimensions),
00067           OptionalSize   = ObligatorySize +
00068                            sizeof(vil3d_analyze_header::History);
00069 
00070 
00071 void vil3d_analyze_header::Key::reset()
00072 {
00073   vcl_memset(this, (char)0, sizeof(*this));
00074 
00075   // obligatory fields
00076   sizeof_hdr = OptionalSize;
00077   extents = 16384;
00078   regular = 'r';
00079 }
00080 
00081 
00082 void vil3d_analyze_header::Dimensions::reset()
00083 {
00084   vcl_memset(this, (char)0, sizeof(*this));
00085 }
00086 
00087 
00088 void vil3d_analyze_header::History::reset()
00089 {
00090   vcl_memset(this, (char)0, sizeof(*this));
00091   vcl_sprintf(descrip," VXL generated file, some data fields may be missing");
00092 }
00093 
00094 
00095 void vil3d_analyze_header::reset()
00096 {
00097   key.reset();
00098   dim.reset();
00099   history.reset();
00100 }
00101 
00102 // This function centralises the compiler warning concerning "const cast":
00103 static inline void do_write(vcl_ofstream& bfs, const void* data, unsigned int sz)
00104 {
00105   bfs.write((char*)data, sz);
00106 }
00107 #define WRITE(X) do_write(bfs, &X, sizeof(X))
00108 
00109 bool vil3d_analyze_header::write_file(const vcl_string& path) const
00110 {
00111   vcl_ofstream bfs(path.c_str(),vcl_ios_binary);
00112   if (!bfs) return false;
00113 
00114   if (key.sizeof_hdr != OptionalSize)
00115   {
00116     vcl_cerr << "vil3d_analyze_header::write_file: Header file is not the correct size.\n";
00117     return false;
00118   }
00119   else
00120   {
00121     WRITE(key.sizeof_hdr);
00122     for (int i=0; i<10; ++i)
00123       WRITE(key.data_type[i]);
00124     for (int i=0; i<18; ++i)
00125       WRITE(key.db_name[i]);
00126     WRITE(key.extents);
00127     WRITE(key.session_error);
00128     WRITE(key.regular);
00129     WRITE(key.hkey_un0);
00130 
00131     for (int i=0; i<8; ++i)
00132       WRITE(dim.dim[i]);
00133     WRITE(dim.unused8);
00134     WRITE(dim.unused9);
00135     WRITE(dim.unused10);
00136     WRITE(dim.unused11);
00137     WRITE(dim.unused12);
00138     WRITE(dim.unused13);
00139     WRITE(dim.unused14);
00140     WRITE(dim.datatype);
00141     WRITE(dim.bitpix);
00142     WRITE(dim.dim_un0);
00143     for (int i=0; i<8; ++i)
00144       WRITE(dim.pixdim[i]);
00145     WRITE(dim.funused8);
00146     WRITE(dim.funused9);
00147     WRITE(dim.funused10);
00148     WRITE(dim.funused11);
00149     WRITE(dim.funused12);
00150     WRITE(dim.funused13);
00151     WRITE(dim.compressed);
00152     WRITE(dim.verified);
00153     WRITE(dim.glmax);
00154     WRITE(dim.glmin);
00155 
00156     for (int i=0; i<80; ++i)
00157       WRITE(history.descrip[i]);
00158     for (int i=0; i<24; ++i)
00159       WRITE(history.aux_file[i]);
00160     WRITE(history.orient);
00161     for (int i=0; i<10; ++i)
00162       WRITE(history.originator[i]);
00163     for (int i=0; i<10; ++i)
00164       WRITE(history.generated[i]);
00165     for (int i=0; i<10; ++i)
00166       WRITE(history.scannum[i]);
00167     for (int i=0; i<10; ++i)
00168       WRITE(history.patient_id[i]);
00169     for (int i=0; i<10; ++i)
00170       WRITE(history.exp_date[i]);
00171     for (int i=0; i<10; ++i)
00172       WRITE(history.exp_time[i]);
00173     for (int i=0; i<3; ++i)
00174       WRITE(history.hist_un0[i]);
00175     WRITE(history.views);
00176     WRITE(history.vols_added);
00177     WRITE(history.start_field);
00178     WRITE(history.field_skip);
00179     WRITE(history.omax);
00180     WRITE(history.omin);
00181     WRITE(history.smax);
00182     WRITE(history.smin);
00183   }
00184   return true;
00185 }
00186 
00187 bool vil3d_analyze_header::read_file(const vcl_string& path)
00188 {
00189   vcl_ifstream bfs(path.c_str(),vcl_ios_binary);
00190   if (!bfs) return false;
00191 
00192   bfs.read((char *)&key.sizeof_hdr, sizeof(key.sizeof_hdr));
00193 
00194   // Check if the bytes need swapping
00195   swap_bytes_ = (key.sizeof_hdr>RD_AH_MAXHEADERSIZE);
00196 
00197   swapBytes((char *)&key.sizeof_hdr, sizeof(key.sizeof_hdr));
00198 
00199   for (int i=0; i<10; ++i)
00200   {
00201     bfs.read((char *)&key.data_type[i],sizeof(key.data_type[i]));
00202     swapBytes((char *)&key.data_type[i],sizeof(key.data_type[i]));
00203   }
00204   for (int i=0; i<18; ++i)
00205   {
00206     bfs.read((char *)&key.db_name[i],sizeof(key.db_name[i]));
00207     swapBytes((char *)&key.db_name[i],sizeof(key.db_name[i]));
00208   }
00209 
00210   bfs.read((char *)&key.extents, sizeof(key.extents));
00211   swapBytes((char *)&key.extents,sizeof(key.extents));
00212   bfs.read((char *)&key.session_error,sizeof(key.session_error));
00213   swapBytes((char *)&key.session_error,sizeof(key.session_error));
00214   bfs.read((char *)&key.regular,sizeof(key.regular));
00215   swapBytes((char *)&key.regular,sizeof(key.regular));
00216   bfs.read((char *)&key.hkey_un0,sizeof(key.hkey_un0));
00217   swapBytes((char *)&key.hkey_un0,sizeof(key.hkey_un0));
00218 
00219   if (key.sizeof_hdr != ObligatorySize &&
00220       key.sizeof_hdr != OptionalSize)
00221   {
00222     vcl_cerr << "vil3d_analyze_header::load: Header file is not the correct size.\n";
00223     return false;
00224   }
00225   else
00226   {
00227     for (int i=0; i<8; ++i)
00228     {
00229       bfs.read((char *)&dim.dim[i],sizeof(dim.dim[i]));
00230       swapBytes((char *)&dim.dim[i],sizeof(dim.dim[i]));
00231     }
00232 
00233     bfs.read((char *)&dim.unused8,sizeof(dim.unused8));
00234     swapBytes((char *)&dim.unused8,sizeof(dim.unused8));
00235     bfs.read((char *)&dim.unused9,sizeof(dim.unused9));
00236     swapBytes((char *)&dim.unused9,sizeof(dim.unused9));
00237     bfs.read((char *)&dim.unused10,sizeof(dim.unused10));
00238     swapBytes((char *)&dim.unused10,sizeof(dim.unused10));
00239     bfs.read((char *)&dim.unused11,sizeof(dim.unused11));
00240     swapBytes((char *)&dim.unused11,sizeof(dim.unused11));
00241     bfs.read((char *)&dim.unused12,sizeof(dim.unused12));
00242     swapBytes((char *)&dim.unused12,sizeof(dim.unused12));
00243     bfs.read((char *)&dim.unused13,sizeof(dim.unused13));
00244     swapBytes((char *)&dim.unused14,sizeof(dim.unused13));
00245     bfs.read((char *)&dim.unused14,sizeof(dim.unused14));
00246     swapBytes((char *)&dim.unused14,sizeof(dim.unused14));
00247     bfs.read((char *)&dim.datatype,sizeof(dim.datatype));
00248     swapBytes((char *)&dim.datatype,sizeof(dim.datatype));
00249     bfs.read((char *)&dim.bitpix,sizeof(dim.bitpix));
00250     swapBytes((char *)&dim.bitpix,sizeof(dim.bitpix));
00251     bfs.read((char *)&dim.dim_un0,sizeof(dim.dim_un0));
00252     swapBytes((char *)&dim.dim_un0,sizeof(dim.dim_un0));
00253     for (int i=0; i<8; ++i)
00254     {
00255       bfs.read((char *)&dim.pixdim[i],sizeof(dim.pixdim[i]));
00256       swapBytes((char *)&dim.pixdim[i],sizeof(dim.pixdim[i]));
00257     }
00258     bfs.read((char *)&dim.funused8,sizeof(dim.funused8));
00259     swapBytes((char *)&dim.funused8,sizeof(dim.funused8));
00260     bfs.read((char *)&dim.funused9,sizeof(dim.funused9));
00261     swapBytes((char *)&dim.funused9,sizeof(dim.funused9));
00262     bfs.read((char *)&dim.funused10,sizeof(dim.funused10));
00263     swapBytes((char *)&dim.funused10,sizeof(dim.funused10));
00264     bfs.read((char *)&dim.funused11,sizeof(dim.funused11));
00265     swapBytes((char *)&dim.funused11,sizeof(dim.funused11));
00266     bfs.read((char *)&dim.funused12,sizeof(dim.funused12));
00267     swapBytes((char *)&dim.funused12,sizeof(dim.funused12));
00268     bfs.read((char *)&dim.funused13,sizeof(dim.funused13));
00269     swapBytes((char *)&dim.funused13,sizeof(dim.funused13));
00270     bfs.read((char *)&dim.compressed,sizeof(dim.compressed));
00271     swapBytes((char *)&dim.compressed,sizeof(dim.compressed));
00272     bfs.read((char *)&dim.verified,sizeof(dim.verified));
00273     swapBytes((char *)&dim.verified,sizeof(dim.verified));
00274     bfs.read((char *)&dim.glmax,sizeof(dim.glmax));
00275     swapBytes((char *)&dim.glmax,sizeof(dim.glmax));
00276     bfs.read((char *)&dim.glmin,sizeof(dim.glmin));
00277     swapBytes((char *)&dim.glmin,sizeof(dim.glmin));
00278 
00279     if (key.sizeof_hdr == OptionalSize)
00280     {
00281       for (int i=0; i<80; ++i)
00282       {
00283         bfs.read((char *)&history.descrip[i],
00284                  sizeof(history.descrip[i]));
00285         swapBytes((char *)&history.descrip[i],
00286                   sizeof(history.descrip[i]));
00287       }
00288       for (int i=0; i<24; ++i)
00289       {
00290         bfs.read((char *)&history.aux_file[i],
00291                  sizeof(history.aux_file[i]));
00292         swapBytes((char *)&history.aux_file[i],
00293                   sizeof(history.aux_file[i]));
00294       }
00295       bfs.read((char *)&history.orient, sizeof(history.orient));
00296       swapBytes((char *)&history.orient, sizeof(history.orient));
00297       for (int i=0; i<10; ++i)
00298       {
00299         bfs.read((char *)&history.originator[i],
00300                  sizeof(history.originator[i]));
00301         swapBytes((char *)&history.originator[i],
00302                   sizeof(history.originator[i]));
00303       }
00304       for (int i=0; i<10; ++i)
00305       {
00306         bfs.read((char *)&history.generated[i],
00307                  sizeof(history.generated[i]));
00308         swapBytes((char *)&history.generated[i],
00309                   sizeof(history.generated[i]));
00310       }
00311       for (int i=0; i<10; ++i)
00312       {
00313         bfs.read((char *)&history.scannum[i],
00314                  sizeof(history.scannum[i]));
00315         swapBytes((char *)&history.scannum[i],
00316                   sizeof(history.scannum[i]));
00317       }
00318       for (int i=0; i<10; ++i)
00319       {
00320         bfs.read((char *)&history.patient_id[i],
00321                  sizeof(history.patient_id[i]));
00322         swapBytes((char *)&history.patient_id[i],
00323                   sizeof(history.patient_id[i]));
00324       }
00325       for (int i=0; i<10; ++i)
00326       {
00327         bfs.read((char *)&history.exp_date[i],
00328                  sizeof(history.exp_date[i]));
00329         swapBytes((char *)&history.exp_date[i],
00330                   sizeof(history.exp_date[i]));
00331       }
00332       for (int i=0; i<10; ++i)
00333       {
00334         bfs.read((char *)&history.exp_time[i],
00335                  sizeof(history.exp_time[i]));
00336         swapBytes((char *)&history.exp_time[i],
00337                   sizeof(history.exp_time[i]));
00338       }
00339       for (int i=0; i<3; ++i)
00340       {
00341         bfs.read((char *)&history.hist_un0[i],
00342                  sizeof(history.hist_un0[i]));
00343         swapBytes((char *)&history.hist_un0[i],
00344                   sizeof(history.hist_un0[i]));
00345       }
00346 
00347       bfs.read((char *)&history.views,sizeof(history.views));
00348       swapBytes((char *)&history.views,sizeof(history.views));
00349       bfs.read((char *)&history.vols_added,sizeof(history.vols_added));
00350       swapBytes((char *)&history.vols_added,sizeof(history.vols_added));
00351       bfs.read((char *)&history.start_field,sizeof(history.start_field));
00352       swapBytes((char *)&history.start_field,sizeof(history.start_field));
00353       bfs.read((char *)&history.field_skip,sizeof(history.field_skip));
00354       swapBytes((char *)&history.field_skip,sizeof(history.field_skip));
00355       bfs.read((char *)&history.omax,sizeof(history.omax));
00356       swapBytes((char *)&history.omax,sizeof(history.omax));
00357       bfs.read((char *)&history.omin,sizeof(history.omin));
00358       swapBytes((char *)&history.omin,sizeof(history.omin));
00359       bfs.read((char *)&history.smax,sizeof(history.smax));
00360       swapBytes((char *)&history.smax,sizeof(history.smax));
00361       bfs.read((char *)&history.smin,sizeof(history.smin));
00362       swapBytes((char *)&history.smin,sizeof(history.smin));
00363     }
00364     else
00365       history.reset();
00366   }
00367   return true;
00368 }
00369 
00370 //: Define number of pixels in each dimension
00371 void vil3d_analyze_header::set_image_size(unsigned ni, unsigned nj,
00372                                           unsigned nk, unsigned np)
00373 {
00374   dim.dim[1]=(short int)(ni);
00375   dim.dim[2]=(short int)(nj);
00376   dim.dim[3]=(short int)(nk);
00377   dim.dim[4]=(short int)(np);
00378 }
00379 //: Define width of voxels in each dimension
00380 void vil3d_analyze_header::set_voxel_size(float si, float sj, float sk)
00381 {
00382   dim.pixdim[1]=si;
00383   dim.pixdim[2]=sj;
00384   dim.pixdim[3]=sk;
00385 }
00386 
00387 void vil3d_analyze_header::swapBytes(char *data, int size)
00388 {
00389   if (needSwap())
00390   {
00391     char *temp = new char[size];
00392     for (int i=0; i<size; i++)  temp[(size-i)-1] = data[i];
00393     for (int i=0; i<size; i++)  data[i] = temp[i];
00394     delete [] temp;
00395   }
00396 }
00397 
00398 //: Define format of pixels
00399 void vil3d_analyze_header::set_pixel_format(enum vil_pixel_format format)
00400 {
00401   switch (format)
00402   {
00403     case VIL_PIXEL_FORMAT_BYTE :   dim.datatype=2; break;
00404     case VIL_PIXEL_FORMAT_INT_16 : dim.datatype=4; break;
00405     case VIL_PIXEL_FORMAT_INT_32 : dim.datatype=8; break;
00406     case VIL_PIXEL_FORMAT_FLOAT :  dim.datatype=16; break;
00407     case VIL_PIXEL_FORMAT_DOUBLE : dim.datatype=64; break;
00408     default: dim.datatype=0;
00409   }
00410 }
00411 
00412 //: Define format of pixels
00413 enum vil_pixel_format vil3d_analyze_header::pixel_format() const
00414 {
00415   switch (dim.datatype)
00416   {
00417     case 2  : return VIL_PIXEL_FORMAT_BYTE;
00418     case 4  : return VIL_PIXEL_FORMAT_INT_16;
00419     case 8  : return VIL_PIXEL_FORMAT_INT_32;
00420     case 16 : return VIL_PIXEL_FORMAT_FLOAT;
00421     case 64 : return VIL_PIXEL_FORMAT_DOUBLE;
00422     default : return VIL_PIXEL_FORMAT_UNKNOWN;
00423   }
00424   return VIL_PIXEL_FORMAT_UNKNOWN; // dummy return, to avoid compiler warning
00425 }
00426 
00427 //: Print out some parts of header
00428 void vil3d_analyze_header::print_summary(vcl_ostream& os) const
00429 {
00430   os<<"vil3d_analyze_header:\n";
00431   vsl_indent_inc(os);
00432   os<<vsl_indent()<<"Size: "<<dim.dim[1]<<" x "<<dim.dim[2]<<" x "<<dim.dim[3]
00433     <<"  Voxel widths: ("<<dim.pixdim[1]<<" x "<<dim.pixdim[2]<<" x "<<dim.pixdim[3]
00434     <<") Voxel type: "<<pixel_format()<<" (Code="<<dim.datatype<<')';
00435   vsl_indent_dec(os);
00436 }
00437 
00438 //: Print out some parts of header
00439 vcl_ostream& operator<<(vcl_ostream& os, const vil3d_analyze_header& header)
00440 {
00441   header.print_summary(os);
00442   return os;
00443 }
00444 
00445 // ==================================================================
00446 // =================== vil3d_analyze_format =========================
00447 // ==================================================================
00448 
00449 vil3d_analyze_format::vil3d_analyze_format() {}
00450 
00451 // The destructor must be virtual so that the memory chunk is destroyed.
00452 vil3d_analyze_format::~vil3d_analyze_format()
00453 {
00454 }
00455 
00456 vil3d_image_resource_sptr vil3d_analyze_format::make_input_image(const char *filename1) const
00457 {
00458   vil3d_analyze_header header;
00459   vcl_string filename(filename1);
00460   vcl_string base_filename;
00461   vcl_size_t n=filename.size();
00462   if (n>=4 && (filename.substr(n-4,4)==".hdr" || filename.substr(n-4,4)==".img"))
00463     base_filename = filename.substr(0,n-4);
00464   else
00465     base_filename = filename;
00466 
00467   if (!header.read_file(vcl_string(base_filename)+".hdr")) return 0;
00468   vcl_cout<<"vil3d_analyze_format::make_input_image() Header: "<<header<<vcl_endl;
00469 
00470   return new vil3d_analyze_image(header,base_filename);
00471 }
00472 
00473 
00474 //: Make a "generic_image" on which put_section may be applied.
00475 // The file may be opened immediately for writing so that a header can be written.
00476 // The width/height etc are explicitly specified, so that file_format implementors
00477 // know what they need to do...
00478 vil3d_image_resource_sptr vil3d_analyze_format::make_output_image(const char* filename1,
00479                                                                   unsigned ni, unsigned nj,
00480                                                                   unsigned nk, unsigned nplanes,
00481                                                                   enum vil_pixel_format format) const
00482 {
00483   if (format != VIL_PIXEL_FORMAT_BYTE   &&
00484       format != VIL_PIXEL_FORMAT_INT_16 &&
00485       format != VIL_PIXEL_FORMAT_FLOAT  && format != VIL_PIXEL_FORMAT_DOUBLE &&
00486       format != VIL_PIXEL_FORMAT_INT_32 )
00487   {
00488     vcl_cerr << "vil3d_analyze_format::make_output_image() WARNING\n"
00489              << "  Unable to deal with pixel format : " << format << vcl_endl;
00490     return 0;
00491   }
00492 
00493   vil3d_analyze_header header;
00494   header.set_image_size(ni,nj,nk,nplanes);
00495   header.set_pixel_format(format);
00496   header.set_voxel_size(1.0f,1.0f,1.0f);
00497   header.set_pixel_format(format);
00498 
00499   vcl_string filename(filename1);
00500   vcl_string base_filename;
00501   vcl_size_t n=filename.size();
00502   if (n>=4 && (filename.substr(n-4,4)==".hdr" || filename.substr(n-4,4)==".img"))
00503     base_filename = filename.substr(0,n-4);
00504   else
00505     base_filename = filename;
00506   if (!header.write_file(vcl_string(base_filename)+".hdr")) return 0;
00507   return new vil3d_analyze_image(header,base_filename);
00508 }
00509 
00510 // ==================================================================
00511 // =================== vil3d_analyze_image ==========================
00512 // ==================================================================
00513 
00514 vil3d_analyze_image::vil3d_analyze_image(const vil3d_analyze_header& header,
00515                                          const vcl_string& base_path)
00516 {
00517   header_ = header;
00518   base_path_ = base_path;
00519 }
00520 
00521 vil3d_analyze_image::~vil3d_analyze_image()
00522 {
00523 }
00524 
00525 //: Number of planes (or time points in an image sequence).
00526 unsigned vil3d_analyze_image::nplanes() const
00527 {
00528   return header_.nplanes();
00529 }
00530 
00531 //: Dimensions:  nplanes x ni x nj x nk.
00532 // The number of pixels in each row.
00533 unsigned vil3d_analyze_image::ni() const
00534 {
00535   return header_.dim.dim[1];
00536 }
00537 
00538 //: Dimensions:  nplanes x ni x nj x nk.
00539 // The number of pixels in each column.
00540 unsigned vil3d_analyze_image::nj() const
00541 {
00542   return header_.dim.dim[2];
00543 }
00544 
00545 //: Dimensions:  nplanes x ni x nj x nk.
00546 // The number of slices per image.
00547 unsigned vil3d_analyze_image::nk() const
00548 {
00549   return header_.dim.dim[3];
00550 }
00551 
00552 //: Pixel Format.
00553 enum vil_pixel_format vil3d_analyze_image::pixel_format() const
00554 {
00555   return header_.pixel_format();
00556 }
00557 
00558 //: Get some or all of the volume.
00559 vil3d_image_view_base_sptr vil3d_analyze_image::get_copy_view(
00560                                unsigned i0, unsigned ni, unsigned j0, unsigned nj,
00561                                unsigned k0, unsigned nk) const
00562 {
00563   // Can only cope with loading whole image at present.
00564   if (i0!=0 || int(ni)!=header_.ni() ||
00565       j0!=0 || int(nj)!=header_.nj() ||
00566       k0!=0 || int(nk)!=header_.nk()   ) return 0;
00567 
00568   vcl_string image_data_path=base_path_+".img";
00569   vil_smart_ptr<vil_stream> is = new vil_stream_fstream(image_data_path.c_str(),"r");
00570   if (!is->ok()) return 0;
00571 
00572 // NOTE: See GIPL loader for more general data reading
00573 #define read_data_of_type(type) \
00574   vil3d_image_view< type > im = \
00575          vil3d_new_image_view_plane_k_j_i(ni, nj, nk, nplanes(), type()); \
00576   is->read(&im(0,0,0,0), ni * nj * nk * nplanes() * sizeof(type));
00577 
00578   switch (pixel_format())
00579   {
00580    case VIL_PIXEL_FORMAT_BYTE:
00581    {
00582     read_data_of_type(vxl_byte);
00583     return new vil3d_image_view<vxl_byte>(im);
00584    }
00585    case VIL_PIXEL_FORMAT_INT_16:
00586    {
00587     read_data_of_type(vxl_int_16);
00588     if (header_.needSwap())
00589       swap16_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00590     return new vil3d_image_view<vxl_int_16>(im);
00591    }
00592    case VIL_PIXEL_FORMAT_INT_32:
00593    {
00594     read_data_of_type(vxl_int_32);
00595     if (header_.needSwap())
00596       swap32_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00597     return new vil3d_image_view<vxl_int_32>(im);
00598    }
00599    case VIL_PIXEL_FORMAT_FLOAT:
00600    {
00601     read_data_of_type(float);
00602     if (header_.needSwap())
00603       swap32_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00604     return new vil3d_image_view<float>(im);
00605    }
00606    case VIL_PIXEL_FORMAT_DOUBLE:
00607    {
00608     read_data_of_type(double);
00609     if (header_.needSwap())
00610       swap64_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00611     return new vil3d_image_view<double>(im);
00612    }
00613    case VIL_PIXEL_FORMAT_BOOL:
00614     vcl_cout<<"ERROR: vil3d_analyze_format::get_copy_view()"
00615             <<pixel_format() << " pixel type not yet implemented\n";
00616     return 0;
00617    default:
00618     vcl_cout<<"ERROR: vil3d_analyze_format::get_copy_view()\n"
00619             <<"Can't deal with pixel type " << pixel_format() << vcl_endl;
00620     return 0;
00621   }
00622 }
00623 
00624 
00625 //: Get the properties (of the first slice)
00626 bool vil3d_analyze_image::get_property(char const *key, void * value) const
00627 {
00628   if (vcl_strcmp(vil3d_property_voxel_size, key)==0)
00629   {
00630     float* array = static_cast<float*>(value);
00631     // analyze stores data in mm
00632     array[0] = header_.voxel_width_i() / 1000.0f;
00633     array[1] = header_.voxel_width_j() / 1000.0f;
00634     array[2] = header_.voxel_width_k() / 1000.0f;
00635     return true;
00636   }
00637 
00638   if (vcl_strcmp(vil3d_property_origin_offset, key)==0)
00639   {
00640     // Don't know how to get origin offset from header yet!
00641     float* array = static_cast<float*>(value);
00642     array[0] = (float)(0);
00643     array[1] = (float)(0);
00644     array[2] = (float)(0);
00645     return true;
00646   }
00647 
00648   return false;
00649 }
00650 
00651 //: Set the contents of the volume.
00652 bool vil3d_analyze_image::put_view(const vil3d_image_view_base& view,
00653                                    unsigned i0=0, unsigned j0=0, unsigned k0=0)
00654 {
00655   if (!view_fits(view, i0, j0, k0))
00656   {
00657     vcl_cerr << "ERROR: " << __FILE__ << ":\n view does not fit\n";
00658     return false;
00659   }
00660   if (view.ni()!=ni() || view.nj()!=nj() || view.nk()!=nk())
00661   {
00662     vcl_cerr<<"Can only write whole image at once.\n";
00663     return false;
00664   }
00665 
00666   vcl_string image_data_path=base_path_+".img";
00667   vil_smart_ptr<vil_stream> os = new vil_stream_fstream(image_data_path.c_str(),"w");
00668   if (!os->ok()) return 0;
00669 
00670   switch (pixel_format())
00671   {
00672    case VIL_PIXEL_FORMAT_BYTE:
00673    {
00674     vil3d_image_view<vxl_byte> view_copy(ni(),nj(),nk(),nplanes());
00675     vil3d_copy_reformat(static_cast<const vil3d_image_view<vxl_byte>&>(view),view_copy);
00676     os->write(view_copy.origin_ptr(),ni()*nj()*nk()*nplanes());
00677     // Should check that write was successful
00678     return true;
00679    }
00680    case VIL_PIXEL_FORMAT_INT_16:
00681    {
00682     vil3d_image_view<vxl_int_16> view_copy(ni(),nj(),nk(),nplanes());
00683     vil3d_copy_reformat(static_cast<const vil3d_image_view<vxl_int_16>&>(view),view_copy);
00684     if (header_.needSwap())
00685       swap16_for_big_endian((char *)(view_copy.origin_ptr()), ni()*nj()*nk()*nplanes());
00686     os->write(view_copy.origin_ptr(),ni()*nj()*nk()*nplanes()*sizeof(vxl_int_16));
00687     // Should check that write was successful
00688     return true;
00689    }
00690    case VIL_PIXEL_FORMAT_INT_32:
00691    {
00692     vil3d_image_view<vxl_int_32> view_copy(ni(),nj(),nk(),nplanes());
00693     vil3d_copy_reformat(static_cast<const vil3d_image_view<vxl_int_32>&>(view),view_copy);
00694     if (header_.needSwap())
00695       swap32_for_big_endian((char *)(view_copy.origin_ptr()), ni()*nj()*nk()*nplanes());
00696     os->write(view_copy.origin_ptr(),ni()*nj()*nk()*nplanes()*sizeof(vxl_int_32));
00697     // Should check that write was successful
00698     return true;
00699    }
00700    case VIL_PIXEL_FORMAT_FLOAT:
00701    {
00702     vil3d_image_view<float> view_copy(ni(),nj(),nk(),nplanes());
00703     vil3d_copy_reformat(static_cast<const vil3d_image_view<float>&>(view),view_copy);
00704     if (header_.needSwap())
00705       swap32_for_big_endian((char *)(view_copy.origin_ptr()), ni()*nj()*nk()*nplanes());
00706     os->write(view_copy.origin_ptr(),ni()*nj()*nk()*nplanes()*sizeof(float));
00707     // Should check that write was successful
00708     return true;
00709    }
00710    case VIL_PIXEL_FORMAT_DOUBLE:
00711    {
00712      vil3d_image_view<double> view_copy(ni(),nj(),nk(),nplanes());
00713      vil3d_copy_reformat(static_cast<const vil3d_image_view<double>&>(view),view_copy);
00714      if (header_.needSwap())
00715        swap32_for_big_endian((char *)(view_copy.origin_ptr()), ni()*nj()*nk()*nplanes());
00716      os->write(view_copy.origin_ptr(),ni()*nj()*nk()*nplanes()*sizeof(double));
00717      // Should check that write was successful
00718      return true;
00719    }
00720    default:
00721     vcl_cout<<"ERROR: vil3d_analyze_format::put_view()\n"
00722             <<"Can't deal with pixel type " << pixel_format() << vcl_endl;
00723   }
00724 
00725   return false;
00726 }
00727 
00728 //: Set the size of the each voxel in the i,j,k directions.
00729 // You can get the voxel sizes via get_properties().
00730 // \return false if underlying image doesn't store pixel sizes.
00731 bool vil3d_analyze_image::set_voxel_size(float si,float sj,float sk)
00732 {
00733   header_.set_voxel_size(si,sj,sk);
00734   // Overwrite the header in the file
00735   if (!header_.write_file(base_path_+".hdr")) return false;
00736   return true;
00737 }
00738