contrib/mul/vil3d/file_formats/vil3d_gipl_format.cxx
Go to the documentation of this file.
00001 // This is mul/vil3d/file_formats/vil3d_gipl_format.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \brief Reader/Writer for GIPL format images.
00008 // \author Tim Cootes - Manchester
00009 
00010 #include "vil3d_gipl_format.h"
00011 #include <vcl_cstring.h> // for vcl_strcmp()
00012 #include <vil/vil_stream_read.h>
00013 #include <vil/vil_stream_fstream.h>
00014 #include <vil3d/vil3d_image_view.h>
00015 #include <vil3d/vil3d_new.h>
00016 #include <vil3d/vil3d_property.h>
00017 #include <vil3d/vil3d_image_resource.h>
00018 #include <vcl_vector.h>
00019 #include <vil/vil_open.h>
00020 #include <vsl/vsl_binary_explicit_io.h>
00021 #include <vcl_cassert.h>
00022 
00023 // GIPL magic number
00024 const unsigned GIPL_MAGIC1 = 719555000;
00025 const unsigned GIPL_MAGIC2 = 4026526128U;
00026 
00027 // GIPL header size
00028 #define GIPL_HEADERSIZE 256
00029 
00030 // GIPL filter types
00031 #define GIPL_BINARY       1
00032 #define GIPL_CHAR         7
00033 #define GIPL_U_CHAR       8
00034 #define GIPL_U_SHORT     15
00035 #define GIPL_SHORT       16
00036 #define GIPL_U_INT       31
00037 #define GIPL_INT         32
00038 #define GIPL_FLOAT       64
00039 #define GIPL_DOUBLE      65
00040 #define GIPL_C_SHORT    144
00041 #define GIPL_C_INT      160
00042 #define GIPL_C_FLOAT    192
00043 #define GIPL_C_DOUBLE   193
00044 
00045 // ORIENTATION DEFINITIONS (flag1)
00046 #define GIPL_UNDEFINED_ORIENTATION   0
00047 #define GIPL_UNDEFINED_PROJECTION    1
00048 #define GIPL_AP_PROJECTION           2
00049 #define GIPL_LATERAL_PROJECTION      3
00050 #define GIPL_OBLIQUE_PROJECTION      4
00051 #define GIPL_UNDEFINED_TOMO          8
00052 #define GIPL_AXIAL                   9
00053 #define GIPL_CORONAL                10
00054 #define GIPL_SAGITTAL               11
00055 #define GIPL_OBLIQUE_TOMO           12
00056 
00057 
00058 #if VXL_LITTLE_ENDIAN
00059 inline void swap16_for_big_endian(char *a, unsigned n)
00060 {
00061   for (unsigned i = 0; i < n * 2; i += 2)
00062   {
00063     char c = a[i]; a[i] = a[i+1]; a[i+1] = c;
00064   }
00065 }
00066 
00067 inline void swap32_for_big_endian(char *a, unsigned n)
00068 {
00069   for (unsigned i = 0; i < n * 4; i += 4)
00070   {
00071     char c= a[i]; a[i] = a[i+3]; a[i+3] = c;
00072     c = a[i+1]; a[i+1] = a[i+2]; a[i+2] = c;
00073   }
00074 }
00075 
00076 inline void swap64_for_big_endian(char *a, unsigned n)
00077 {
00078   for (unsigned i = 0; i < n * 8; i += 8)
00079   {
00080     char c= a[i]; a[i] = a[i+7]; a[i+7] = c;
00081     c = a[i+1]; a[i+1] = a[i+6]; a[i+6] = c;
00082     c = a[i+2]; a[i+2] = a[i+5]; a[i+5] = c;
00083     c = a[i+3]; a[i+3] = a[i+4]; a[i+4] = c;
00084   }
00085 }
00086 #endif //VXL_LITTLE_ENDIAN
00087 
00088 
00089 vil3d_gipl_format::vil3d_gipl_format() {}
00090 
00091 // The destructor must be virtual so that the memory chunk is destroyed.
00092 vil3d_gipl_format::~vil3d_gipl_format()
00093 {
00094 }
00095 
00096 
00097 vil3d_image_resource_sptr vil3d_gipl_format::make_input_image(const char *filename) const
00098 {
00099   vil_smart_ptr<vil_stream> is = new vil_stream_fstream(filename,"r");
00100   if (!is->ok()) return 0;
00101 
00102   is->seek(252);
00103   unsigned magic_number = vil_stream_read_big_endian_uint_32(is.as_pointer());
00104   if (magic_number!=GIPL_MAGIC1 && magic_number!=GIPL_MAGIC2) return 0;
00105   else return new vil3d_gipl_image(is.as_pointer());
00106 }
00107 
00108 
00109 //: Make a "generic_image" on which put_section may be applied.
00110 // The file may be opened immediately for writing so that a header can be written.
00111 // The width/height etc are explicitly specified, so that file_format implementors
00112 // know what they need to do...
00113 vil3d_image_resource_sptr vil3d_gipl_format::make_output_image(const char* filename,
00114                                                                unsigned ni, unsigned nj,
00115                                                                unsigned nk, unsigned nplanes,
00116                                                                enum vil_pixel_format format) const
00117 {
00118   if (format != VIL_PIXEL_FORMAT_BOOL   && format != VIL_PIXEL_FORMAT_SBYTE &&
00119       format != VIL_PIXEL_FORMAT_BYTE   && format != VIL_PIXEL_FORMAT_UINT_16 &&
00120       format != VIL_PIXEL_FORMAT_INT_16 && format != VIL_PIXEL_FORMAT_UINT_32 &&
00121       format != VIL_PIXEL_FORMAT_FLOAT  && format != VIL_PIXEL_FORMAT_DOUBLE &&
00122       format != VIL_PIXEL_FORMAT_INT_32 )
00123   {
00124     vcl_cerr << "vil3d_gipl_format::make_output_image() WARNING\n"
00125              << "  Unable to deal with file format : " << format << vcl_endl;
00126     return 0;
00127   }
00128 
00129   // vil_smart_ptr<vil_stream> os = new vil_stream_fstream(filename,"w");
00130 
00131   vil_stream* os = vil_open(filename, "w");
00132   if (!os || !os->ok()) {
00133     vcl_cerr << __FILE__ ": Invalid stream for \"" << filename << "\"\n";
00134     return 0;
00135   }
00136 
00137   if (!os->ok()) return 0;
00138 
00139   return new vil3d_gipl_image(os, ni, nj, nk, nplanes, format);
00140 }
00141 
00142 
00143 vil3d_gipl_image::vil3d_gipl_image(vil_stream *is): is_(is)
00144 {
00145   read_header(is);
00146   os_ = 0;
00147 }
00148 
00149 vil3d_gipl_image::~vil3d_gipl_image()
00150 {
00151   // delete os_
00152   if (os_)
00153     os_->unref();
00154 }
00155 
00156 //: Dimensions:  nplanes x ni x nj x nk.
00157 // This concept is treated as a synonym to components.
00158 unsigned vil3d_gipl_image::nplanes() const
00159 {
00160   return 1;
00161 }
00162 
00163 //: Dimensions:  nplanes x ni x nj x nk.
00164 // The number of pixels in each row.
00165 unsigned vil3d_gipl_image::ni() const
00166 {
00167   return dim1_;
00168 }
00169 
00170 //: Dimensions:  nplanes x ni x nj x nk.
00171 // The number of pixels in each column.
00172 unsigned vil3d_gipl_image::nj() const
00173 {
00174   return dim2_;
00175 }
00176 
00177 //: Dimensions:  nplanes x ni x nj x nk.
00178 // The number of slices per image.
00179 unsigned vil3d_gipl_image::nk() const
00180 {
00181   return dim3_;
00182 }
00183 
00184 //: Pixel Format.
00185 enum vil_pixel_format vil3d_gipl_image::pixel_format() const
00186 {
00187   return pixel_format_;
00188 }
00189 
00190 
00191 //: Read header from given stream if possible
00192 bool vil3d_gipl_image::read_header(vil_stream *is)
00193 {
00194   // Return to start
00195   is->seek(0);
00196   dim1_ = vil_stream_read_big_endian_uint_16(is);
00197   dim2_ = vil_stream_read_big_endian_uint_16(is);
00198   dim3_ = vil_stream_read_big_endian_uint_16(is);
00199 
00200   is->seek(8);
00201 
00202   unsigned short gipl_pixel_type = vil_stream_read_big_endian_uint_16(is);
00203 
00204   switch (gipl_pixel_type)
00205   {
00206   case 1  : pixel_format_ = VIL_PIXEL_FORMAT_BOOL;    break;
00207   case 7  : pixel_format_ = VIL_PIXEL_FORMAT_SBYTE;   break;
00208   case 8  : pixel_format_ = VIL_PIXEL_FORMAT_BYTE;    break;
00209   case 15 : pixel_format_ = VIL_PIXEL_FORMAT_UINT_16; break;
00210   case 16 : pixel_format_ = VIL_PIXEL_FORMAT_INT_16;  break;
00211   case 31 : pixel_format_ = VIL_PIXEL_FORMAT_UINT_32; break;
00212   case 32 : pixel_format_ = VIL_PIXEL_FORMAT_INT_32;  break;
00213   case 64 : pixel_format_ = VIL_PIXEL_FORMAT_FLOAT;   break;
00214   case 65 : pixel_format_ = VIL_PIXEL_FORMAT_DOUBLE;  break;
00215   case 144: // C.Short I don't want to support complex types.
00216   case 160: // C.Int   Could maybe reimplement them as a 2-plane image
00217   case 192: // C.Float
00218   case 193: // C.Double
00219   default : pixel_format_ = VIL_PIXEL_FORMAT_UNKNOWN;
00220   }
00221 
00222   vox_width1_ = vil_stream_read_big_endian_float(is);
00223   vox_width2_ = vil_stream_read_big_endian_float(is);
00224   vox_width3_ = vil_stream_read_big_endian_float(is);
00225   // vcl_cout<<"Voxel widths: "<<vox_width1<<" x "<<vox_width2<<" x "<<vox_width3<<vcl_endl;
00226 
00227   return pixel_format_ != VIL_PIXEL_FORMAT_UNKNOWN;
00228 }
00229 
00230 
00231 //: Get some or all of the volume.
00232 vil3d_image_view_base_sptr vil3d_gipl_image::get_copy_view(
00233                                unsigned i0, unsigned ni, unsigned j0, unsigned nj,
00234                                unsigned k0, unsigned nk) const
00235 {
00236   if (i0+ni > this->ni() || j0+nj > this->nj() || k0+nk > this->nk()) return 0;
00237 
00238 #define macro(type) \
00239   vil3d_image_view< type > im = \
00240     vil3d_new_image_view_plane_k_j_i(ni, nj, nk, 1, type()); \
00241   for (unsigned k=0; k<nk; ++k) \
00242   { \
00243     if (ni == this->ni()) \
00244     { \
00245       is_->seek(GIPL_HEADERSIZE + ((k+k0)*this->nj()*ni + j0*ni) * sizeof(type)); \
00246       is_->read(&im(0,0,k), nj*ni * sizeof(type)); \
00247     } \
00248     else \
00249       for (unsigned j=0; j<nj; ++j) \
00250       { \
00251         is_->seek(GIPL_HEADERSIZE + ((k+k0)*this->nj()*this->ni() + (j+j0)*this->ni() + i0) * sizeof(type)); \
00252         is_->read(&im(0,j,k), ni * sizeof(type)); \
00253       } \
00254   }
00255 
00256 
00257   switch (pixel_format())
00258   {
00259     case VIL_PIXEL_FORMAT_SBYTE:
00260     {
00261       macro(vxl_sbyte);
00262       return new vil3d_image_view<vxl_sbyte>(im);
00263     }
00264     case VIL_PIXEL_FORMAT_BYTE:
00265     {
00266       macro(vxl_byte);
00267       return new vil3d_image_view<vxl_byte>(im);
00268     }
00269     case VIL_PIXEL_FORMAT_INT_16:
00270     {
00271       macro(vxl_int_16);
00272 #if VXL_LITTLE_ENDIAN
00273       swap16_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00274 #endif //VXL_LITTLE_ENDIAN
00275       return new vil3d_image_view<vxl_int_16>(im);
00276     }
00277     case VIL_PIXEL_FORMAT_UINT_16:
00278     {
00279       macro(vxl_uint_16);
00280 #if VXL_LITTLE_ENDIAN
00281       swap16_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00282 #endif //VXL_LITTLE_ENDIAN
00283       return new vil3d_image_view<vxl_uint_16>(im);
00284     }
00285     case VIL_PIXEL_FORMAT_UINT_32:
00286     {
00287       macro(vxl_uint_32);
00288 #if VXL_LITTLE_ENDIAN
00289       swap32_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00290 #endif //VXL_LITTLE_ENDIAN
00291       return new vil3d_image_view<vxl_uint_32>(im);
00292     }
00293     case VIL_PIXEL_FORMAT_INT_32:
00294     {
00295       macro(vxl_int_32);
00296 #if VXL_LITTLE_ENDIAN
00297       swap32_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00298 #endif //VXL_LITTLE_ENDIAN
00299       return new vil3d_image_view<vxl_int_32>(im);
00300     }
00301     case VIL_PIXEL_FORMAT_FLOAT:
00302     {
00303       macro(float);
00304 #if VXL_LITTLE_ENDIAN
00305       swap32_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00306 #endif //VXL_LITTLE_ENDIAN
00307       return new vil3d_image_view<float>(im);
00308     }
00309     case VIL_PIXEL_FORMAT_DOUBLE:
00310     {
00311       macro(double);
00312 #if VXL_LITTLE_ENDIAN
00313       swap64_for_big_endian((char *)(im.origin_ptr()), ni*nj*nk);
00314 #endif //VXL_LITTLE_ENDIAN
00315       return new vil3d_image_view<double>(im);
00316     }
00317     case VIL_PIXEL_FORMAT_BOOL:
00318     vcl_cout<<"ERROR: vil3d_gipl_format::get_image_data()"
00319             <<pixel_format() << " pixel type not yet implemented\n";
00320     return 0;
00321     default:
00322     vcl_cout<<"ERROR: vil3d_gipl_format::get_image_data()\n"
00323             <<"Can't deal with pixel type " << pixel_format() << vcl_endl;
00324     return 0;
00325   }
00326 }
00327 
00328 
00329 //: Get the properties (of the first slice)
00330 bool vil3d_gipl_image::get_property(char const *key, void * value) const
00331 {
00332   if (vcl_strcmp(vil3d_property_voxel_size, key)==0)
00333   {
00334     float* array = static_cast<float*>(value);
00335     // gipl stores data in mm
00336     array[0] = vox_width1_ / 1000.0f;
00337     array[1] = vox_width2_ / 1000.0f;
00338     array[2] = vox_width3_ / 1000.0f;
00339     return true;
00340   }
00341 
00342   if (vcl_strcmp(vil3d_property_origin_offset, key)==0)
00343   {
00344     float* array = static_cast<float*>(value);
00345     array[0] = (float)(dim1_ * 0.5);
00346     array[1] = (float)(dim2_ * 0.5);
00347     array[2] = (float)(dim3_ * 0.5);
00348     return true;
00349   }
00350 
00351   return false;
00352 }
00353 
00354 vil3d_gipl_image::vil3d_gipl_image(vil_stream* os,
00355                                    unsigned ni,
00356                                    unsigned nj,
00357                                    unsigned nk,
00358                                    unsigned nplanes,
00359                                    enum vil_pixel_format format,
00360                                    float vox_width1,
00361                                    float vox_width2,
00362                                    float vox_width3,
00363                                    char orientation_flag,
00364                                    double min_val,
00365                                    double max_val,
00366                                    double origin1,
00367                                    double origin2,
00368                                    double origin3,
00369                                    float interslice_gap)
00370 : os_(os), dim1_(ni), dim2_(nj), dim3_(nk), nplanes_(nplanes),
00371   vox_width1_(vox_width1), vox_width2_(vox_width2), vox_width3_(vox_width3),
00372   pixel_format_(format), orientation_flag_(orientation_flag),
00373   min_val_(min_val), max_val_(max_val),
00374   origin1_(origin1), origin2_(origin2), origin3_(origin3),
00375   interslice_gap_(interslice_gap)
00376 {
00377   os_->ref();
00378 
00379   write_header();
00380 }
00381 
00382 #if 0
00383 vil3d_gipl_image::vil3d_gipl_image(vil_stream* os,
00384                                    unsigned ni,
00385                                    unsigned nj,
00386                                    unsigned nk,
00387                                    unsigned nplanes,
00388                                    enum vil_pixel_format format) : os_(os)
00389 {
00390   os_->ref();
00391   dim1_ = ni;
00392   dim2_ = nj;
00393   dim3_ = nk;
00394   vox_width1_ = vox_width2_ = vox_width3_ = 1;
00395   pixel_format_ = format;
00396   write_header();
00397 }
00398 #endif // 0
00399 
00400 // need to write out as big endian
00401 inline void ConvertHostToMSB(char * ptr, int nbyte, int nelem=1)
00402 {
00403   char temp;
00404   char *ptr1, *ptr2;
00405 
00406   int nbyte2 = nbyte/2;
00407   for (int n = 0; n < nelem; n++ ) {
00408     ptr1 = ptr;
00409     ptr2 = ptr1 + nbyte - 1;
00410     for (int i = 0; i < nbyte2; i++ ) {
00411       temp = *ptr1;
00412       *ptr1++ = *ptr2;
00413       *ptr2-- = temp;
00414     }
00415     ptr += nbyte;
00416   }
00417 }
00418 
00419 
00420 bool vil3d_gipl_image::write_header(void)
00421 {
00422   os_->seek(0L);
00423   char buf[GIPL_HEADERSIZE];
00424   int temp;
00425 
00426   // image dimensions X Y Z T - 8 bytes (0 - 7)
00427   if (VXL_BIG_ENDIAN)
00428   {
00429     os_->write((char*)&dim1_,sizeof(vxl_uint_16));
00430     os_->write((char*)&dim2_,sizeof(vxl_uint_16));
00431     os_->write((char*)&dim3_,sizeof(vxl_uint_16));
00432     os_->write((char*)&nplanes_,sizeof(vxl_uint_16));
00433   }
00434   else
00435   {
00436     vcl_vector<vxl_byte> tempbuf(sizeof(vxl_uint_16));
00437 
00438     vcl_memcpy(&tempbuf[0], &dim1_, sizeof(vxl_uint_16));
00439     ConvertHostToMSB((char*)&tempbuf[0],sizeof(vxl_uint_16));
00440     os_->write((char*)&tempbuf[0],sizeof(vxl_uint_16));
00441 
00442     vcl_memcpy(&tempbuf[0], &dim2_, sizeof(vxl_uint_16));
00443     ConvertHostToMSB((char*)&tempbuf[0],sizeof(vxl_uint_16));
00444     os_->write((char*)&tempbuf[0],sizeof(vxl_uint_16));
00445 
00446     vcl_memcpy(&tempbuf[0], &dim3_, sizeof(vxl_uint_16));
00447     ConvertHostToMSB((char*)&tempbuf[0],sizeof(vxl_uint_16));
00448     os_->write((char*)&tempbuf[0],sizeof(vxl_uint_16));
00449 
00450     vcl_memcpy(&tempbuf[0], &nplanes_, sizeof(vxl_uint_16));
00451     ConvertHostToMSB((char*)&tempbuf[0],sizeof(vxl_uint_16));
00452     os_->write((char*)&tempbuf[0],sizeof(vxl_uint_16));
00453   }
00454 
00455   // file format - 2 bytes (8 - 9)
00456   switch (pixel_format_)
00457   {
00458   case VIL_PIXEL_FORMAT_BOOL   : temp = GIPL_BINARY;  break;
00459   case VIL_PIXEL_FORMAT_SBYTE  : temp = GIPL_CHAR;    break;
00460   case VIL_PIXEL_FORMAT_BYTE   : temp = GIPL_U_CHAR;  break;
00461   case VIL_PIXEL_FORMAT_UINT_16: temp = GIPL_U_SHORT; break;
00462   case VIL_PIXEL_FORMAT_INT_16 : temp = GIPL_SHORT;   break;
00463   case VIL_PIXEL_FORMAT_UINT_32: temp = GIPL_U_INT;   break;
00464   case VIL_PIXEL_FORMAT_INT_32 : temp = GIPL_INT;     break;
00465   case VIL_PIXEL_FORMAT_FLOAT  : temp = GIPL_FLOAT;   break;
00466   case VIL_PIXEL_FORMAT_DOUBLE : temp = GIPL_DOUBLE;  break;
00467   // We don't want to support complex types.
00468   // Could maybe reimplement them as a 2-plane image
00469   case VIL_PIXEL_FORMAT_COMPLEX_FLOAT  /* temp = 192 */:
00470   case VIL_PIXEL_FORMAT_COMPLEX_DOUBLE /* temp = 193 */:
00471   /* case COMPLEX_SHORT: temp = 144 */
00472   /* case COMPLEX_INT:   temp = 160 */
00473   default :
00474     vcl_cerr << "vil3d_gipl_format::write_header() WARNING\n"
00475              << "  Unable to deal with file format : " << pixel_format_ << vcl_endl;
00476     return false;
00477   }
00478   if (VXL_BIG_ENDIAN)
00479     os_->write((char*)&temp,sizeof(vxl_uint_16));
00480   else
00481   {
00482     vcl_vector<vxl_byte> tempbuf(sizeof(vxl_uint_16));
00483 
00484     vcl_memcpy(&tempbuf[0], &temp, sizeof(vxl_uint_16));
00485     ConvertHostToMSB((char*)&tempbuf[0],sizeof(vxl_uint_16));
00486     os_->write((char*)&tempbuf[0],sizeof(vxl_uint_16));
00487   }
00488 
00489   // voxel dimensions X Y Z T - default to x,y,z=1,t=0. 16 bytes (10 - 25)
00490   if (VXL_BIG_ENDIAN)
00491   {
00492     os_->write((char*)&vox_width1_,sizeof(float));
00493     os_->write((char*)&vox_width2_,sizeof(float));
00494     os_->write((char*)&vox_width3_,sizeof(float));
00495   }
00496   else
00497   {
00498     vcl_vector<float> tempbuf(sizeof(float));
00499 
00500     vcl_memcpy(&tempbuf[0],&vox_width1_,sizeof(float));
00501     ConvertHostToMSB((char*)&tempbuf[0],sizeof(float));
00502     os_->write((char*)&tempbuf[0],sizeof(float));
00503 
00504     vcl_memcpy(&tempbuf[0],&vox_width2_,sizeof(float));
00505     ConvertHostToMSB((char*)&tempbuf[0],sizeof(float));
00506     os_->write((char*)&tempbuf[0],sizeof(float));
00507 
00508     vcl_memcpy(&tempbuf[0],&vox_width3_,sizeof(float));
00509     ConvertHostToMSB((char*)&tempbuf[0],sizeof(float));
00510     os_->write((char*)&tempbuf[0],sizeof(float));
00511   }
00512   float temp_float = 0.0;
00513   os_->write((char*)&temp_float,sizeof(float)); // write out 0 for size in t dimension
00514 
00515   // Patient/Text field next 80 characters - 80 bytes (26 - 105)
00516   int i;
00517   for (i=0;i<80;i++)
00518     buf[i]=' ';
00519   os_->write((char*)&buf,80);
00520 
00521   // float matrix[20]. No description. 80 bytes (106 - 185)
00522   for (i=0;i<20;i++)
00523     os_->write((char*)&temp_float,sizeof(float));
00524 
00525   // orientation flag (below). 1 byte (186)
00526   if (VXL_BIG_ENDIAN)
00527     os_->write((char*)&orientation_flag_,sizeof(vxl_byte));
00528   else
00529   {
00530     vcl_vector<vxl_byte> tempbuf(sizeof(vxl_byte));
00531     vcl_memcpy(&tempbuf[0],&orientation_flag_,sizeof(vxl_byte));
00532     ConvertHostToMSB((char*)&tempbuf[0],sizeof(vxl_byte));
00533     os_->write(&tempbuf[0],sizeof(vxl_byte));
00534   }
00535 
00536   // flag2. No description. 1 byte (187)
00537   temp = 0; os_->write((char*)&temp,sizeof(vxl_byte));
00538 
00539   // min. 8 bytes (188 - 195)
00540   if (VXL_BIG_ENDIAN)
00541     os_->write((char*)&min_val_,sizeof(double));
00542   else
00543   {
00544     vcl_vector<double> tempbuf(sizeof(double));
00545     vcl_memcpy(&tempbuf[0],&min_val_,sizeof(double));
00546     ConvertHostToMSB((char*)&tempbuf[0],sizeof(double));
00547     os_->write((char*)&tempbuf[0],sizeof(double));
00548   }
00549 
00550 
00551   // max. 8 bytes (196 - 203)
00552   if (VXL_BIG_ENDIAN)
00553     os_->write((char*)&max_val_,sizeof(double));
00554   else
00555   {
00556     vcl_vector<double> tempbuf(sizeof(double));
00557     vcl_memcpy(&tempbuf[0],&max_val_,sizeof(double));
00558     ConvertHostToMSB((char*)&tempbuf[0],sizeof(double));
00559     os_->write((char*)&tempbuf[0],sizeof(double));
00560   }
00561 
00562   if (VXL_BIG_ENDIAN)
00563   {
00564     // Origin offsets for X Y Z T from top left. 32 bytes (204 - 235)
00565     os_->write((char*)&origin1_,sizeof(double));
00566     os_->write((char*)&origin2_,sizeof(double));
00567     os_->write((char*)&origin3_,sizeof(double));
00568   }
00569   else
00570   {
00571     vcl_vector<double> tempbuf(sizeof(double));
00572 
00573     vcl_memcpy(&tempbuf[0],&origin1_,sizeof(double));
00574     ConvertHostToMSB((char*)&tempbuf[0],sizeof(double));
00575     os_->write((char*)&tempbuf[0],sizeof(double));
00576 
00577     vcl_memcpy(&tempbuf[0],&origin2_,sizeof(double));
00578     ConvertHostToMSB((char*)&tempbuf[0],sizeof(double));
00579     os_->write((char*)&tempbuf[0],sizeof(double));
00580 
00581     vcl_memcpy(&tempbuf[0],&origin3_,sizeof(double));
00582     ConvertHostToMSB((char*)&tempbuf[0],sizeof(double));
00583     os_->write((char*)&tempbuf[0],sizeof(double));
00584   }
00585   double temp_double = 0.0;
00586   os_->write((char*)&temp_double,sizeof(double)); // origin for t dimension is always 0
00587 
00588   // pixval_offset. 4 bytes (236 - 239)
00589   temp_float = 0.0;
00590   os_->write((char*)&temp_float,sizeof(float));
00591 
00592   // pixval_cal. 4 bytes (240 - 243)
00593   os_->write((char*)&temp_float,sizeof(float));
00594 
00595   // Inter-slice gap 4 bytes (244 - 247)
00596   if (VXL_BIG_ENDIAN)
00597     os_->write((char*)&interslice_gap_,sizeof(float));
00598   else
00599   {
00600     vcl_vector<float> tempbuf(sizeof(float));
00601     vcl_memcpy(&tempbuf[0],&interslice_gap_,sizeof(float));
00602     ConvertHostToMSB((char*)&tempbuf[0],sizeof(float));
00603     os_->write(&tempbuf[0],sizeof(float));
00604   }
00605 
00606   // User defined field. 4 bytes (248 - 251)
00607   temp_float = 0.0;
00608   os_->write((char*)&temp_float,sizeof(float));
00609 
00610   // Magic number. 4 bytes (252 - 255)
00611   vxl_uint_32 temp_magic1 = GIPL_MAGIC1;
00612 
00613   if (VXL_BIG_ENDIAN)
00614     os_->write((char*)&temp_magic1,sizeof(vxl_uint_32));
00615   else
00616   {
00617     ConvertHostToMSB((char*)&temp_magic1,sizeof(vxl_uint_32));
00618     os_->write((char*)&temp_magic1,sizeof(vxl_uint_32));
00619   }
00620 
00621   start_of_data_ = os_->tell();
00622   return true;
00623 }
00624 
00625 
00626 //: Set the size of the each voxel in the i,j,k directions.
00627 // You can get the voxel sizes via get_properties().
00628 //
00629 bool vil3d_gipl_image::set_voxel_size(float i,float j,float k)
00630 {
00631   vox_width1_=i;
00632   vox_width2_=j;
00633   vox_width3_=k;
00634 
00635   write_header();
00636 
00637   return true;
00638 }
00639 
00640 //: Set the contents of the volume.
00641 bool vil3d_gipl_image::put_view(const vil3d_image_view_base& view,
00642                                 unsigned i0=0, unsigned j0=0, unsigned k0=0)
00643 {
00644   if (!view_fits(view, i0, j0, k0))
00645   {
00646     vcl_cerr << "ERROR: " << __FILE__ << ":\n view does not fit\n";
00647     return false;
00648   }
00649 
00650 //const vil3d_image_view<bool>* bool_im=0;
00651   const vil3d_image_view<vxl_sbyte>* sbyte_im=0;
00652   const vil3d_image_view<vxl_byte>* byte_im=0;
00653   const vil3d_image_view<vxl_uint_16>* uint_16_im=0;
00654   const vil3d_image_view<vxl_int_16>* int_16_im=0;
00655   const vil3d_image_view<vxl_uint_32>* uint_32_im=0;
00656   const vil3d_image_view<vxl_int_32>* int_32_im=0;
00657   const vil3d_image_view<float>* float_im=0;
00658   const vil3d_image_view<double>* double_im=0;
00659 
00660   unsigned bytes_per_pixel=0;
00661 
00662 //if (view.pixel_format() == VIL_PIXEL_FORMAT_BOOL)
00663 //  bool_im = &static_cast<const vil3d_image_view<bool>& >(view);
00664 //else
00665   if (view.pixel_format() == VIL_PIXEL_FORMAT_SBYTE)
00666   {
00667     sbyte_im = &static_cast<const vil3d_image_view<vxl_sbyte>& >(view);
00668     bytes_per_pixel=sizeof(vxl_sbyte);
00669   }
00670   else if (view.pixel_format() == VIL_PIXEL_FORMAT_BYTE)
00671   {
00672     byte_im = &static_cast<const vil3d_image_view<vxl_byte>& >(view);
00673     bytes_per_pixel=sizeof(vxl_byte);
00674   }
00675   else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_16)
00676   {
00677     uint_16_im = &static_cast<const vil3d_image_view<vxl_uint_16>& >(view);
00678     bytes_per_pixel=sizeof(vxl_uint_16);
00679   }
00680   else if (view.pixel_format() == VIL_PIXEL_FORMAT_INT_16)
00681   {
00682     int_16_im = &static_cast<const vil3d_image_view<vxl_int_16>& >(view);
00683     bytes_per_pixel=sizeof(vxl_int_16);
00684   }
00685   else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_32)
00686   {
00687     uint_32_im = &static_cast<const vil3d_image_view<vxl_uint_32>& >(view);
00688     bytes_per_pixel=sizeof(vxl_uint_32);
00689   }
00690   else if (view.pixel_format() == VIL_PIXEL_FORMAT_INT_32)
00691   {
00692     int_32_im = &static_cast<const vil3d_image_view<vxl_int_32>& >(view);
00693     bytes_per_pixel=sizeof(vxl_int_32);
00694   }
00695   else if (view.pixel_format() == VIL_PIXEL_FORMAT_FLOAT)
00696   {
00697     float_im = &static_cast<const vil3d_image_view<float>& >(view);
00698     bytes_per_pixel=sizeof(float);
00699   }
00700   else if (view.pixel_format() == VIL_PIXEL_FORMAT_DOUBLE)
00701   {
00702     double_im = &static_cast<const vil3d_image_view<double>& >(view);
00703     bytes_per_pixel=sizeof(double);
00704   }
00705   else
00706   {
00707     vcl_cerr << "ERROR: " << __FILE__ << ":\n Do not support putting "
00708              << view.is_a() << " views into gipl image_resource objects\n";
00709     return false;
00710   }
00711 
00712   // write out actual image
00713   vil_streampos byte_start = start_of_data_ + (k0*dim2_ + j0 * dim1_ + i0) * bytes_per_pixel;
00714   //unsigned byte_width = dim1_ * bytes_per_pixel;
00715   unsigned byte_out_width = view.ni() * bytes_per_pixel;
00716 
00717   if (view.pixel_format() == VIL_PIXEL_FORMAT_BOOL)
00718   {
00719     vcl_cerr << "GIPL writer for bool format is not yet implemented" ;
00720     return false;
00721   }
00722 
00723   else if (view.pixel_format() == VIL_PIXEL_FORMAT_SBYTE)
00724   {
00725     assert(sbyte_im!=0);
00726       os_->seek(byte_start);
00727       for (unsigned k = 0; k < view.nk(); ++k)
00728       {
00729         for (unsigned j = 0; j < view.nj(); ++j)
00730         {
00731           os_->write(sbyte_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00732           //byte_start += byte_width;
00733           //os_->seek(byte_start);
00734         }
00735       }
00736     return true;
00737   }
00738 
00739   else if (view.pixel_format() == VIL_PIXEL_FORMAT_BYTE)
00740   {
00741     assert(byte_im!=0);
00742     os_->seek(byte_start);
00743     for (unsigned k = 0; k < view.nk(); ++k)
00744     {
00745       for (unsigned j = 0; j < view.nj(); ++j)
00746       {
00747         os_->write(byte_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00748         //byte_start += byte_width;
00749         //os_->seek(byte_start);
00750       }
00751     }
00752     return true;
00753   }
00754 
00755   else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_16)
00756   {
00757     if (VXL_BIG_ENDIAN)
00758     {
00759       assert(uint_16_im!=0);
00760       os_->seek(byte_start);
00761       for (unsigned k = 0; k < view.nk(); ++k)
00762       {
00763         for (unsigned j = 0; j < view.nj(); ++j)
00764         {
00765           os_->write(uint_16_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00766           //byte_start += byte_width;
00767           //os_->seek(byte_start);
00768         }
00769       }
00770     }
00771     else
00772     {
00773       // Little endian host; must convert words to have MSB first.
00774       //
00775       // Convert line by line to avoid duplicating a potentially large image.
00776       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00777       assert(uint_16_im!=0);
00778       os_->seek(byte_start);
00779       for (unsigned k = 0; k < view.nk(); ++k)
00780       {
00781         for (unsigned j = 0; j < view.nj(); ++j)
00782         {
00783           vcl_memcpy(&tempbuf[0], uint_16_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00784           ConvertHostToMSB((char*)&tempbuf[0], sizeof(vxl_uint_16), view.ni());
00785           os_->write(&tempbuf[0], byte_out_width);
00786           //byte_start += byte_width;
00787           //os_->seek(byte_start);
00788         }
00789       }
00790     }
00791 
00792     return true;
00793   }
00794 
00795   else if (view.pixel_format() == VIL_PIXEL_FORMAT_INT_16)
00796   {
00797     if (VXL_BIG_ENDIAN)
00798     {
00799       assert(int_16_im!=0);
00800       os_->seek(byte_start);
00801       for (unsigned k = 0; k < view.nk(); ++k)
00802       {
00803         for (unsigned j = 0; j < view.nj(); ++j)
00804         {
00805           os_->write(int_16_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00806           //byte_start += byte_width;
00807           //os_->seek(byte_start);
00808         }
00809       }
00810     }
00811     else
00812     {
00813       // Little endian host; must convert words to have MSB first.
00814       //
00815       // Convert line by line to avoid duplicating a potentially large image.
00816       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00817       assert(int_16_im!=0);
00818       os_->seek(byte_start);
00819       for (unsigned k = 0; k < view.nk(); ++k)
00820       {
00821         for (unsigned j = 0; j < view.nj(); ++j)
00822         {
00823           vcl_memcpy(&tempbuf[0], int_16_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00824           ConvertHostToMSB((char*)&tempbuf[0], sizeof(vxl_int_16), view.ni());
00825           os_->write(&tempbuf[0], byte_out_width);
00826           //byte_start += byte_width;
00827           //os_->seek(byte_start);
00828         }
00829       }
00830     }
00831 
00832     return true;
00833   }
00834 
00835   else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_32)
00836   {
00837     if (VXL_BIG_ENDIAN)
00838     {
00839       assert(uint_32_im!=0);
00840       os_->seek(byte_start);
00841       for (unsigned k = 0; k < view.nk(); ++k)
00842       {
00843         for (unsigned j = 0; j < view.nj(); ++j)
00844         {
00845           os_->write(uint_32_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00846           //byte_start += byte_width;
00847           //os_->seek(byte_start);
00848         }
00849       }
00850     }
00851     else
00852     {
00853       // Little endian host; must convert words to have MSB first.
00854       //
00855       // Convert line by line to avoid duplicating a potentially large image.
00856       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00857       assert(uint_32_im!=0);
00858       os_->seek(byte_start);
00859       for (unsigned k = 0; k < view.nk(); ++k)
00860       {
00861         for (unsigned j = 0; j < view.nj(); ++j)
00862         {
00863           vcl_memcpy(&tempbuf[0], uint_32_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00864           ConvertHostToMSB((char*)&tempbuf[0], sizeof(vxl_uint_32), view.ni());
00865           os_->write(&tempbuf[0], byte_out_width);
00866           //byte_start += byte_width;
00867           //os_->seek(byte_start);
00868         }
00869       }
00870     }
00871 
00872     return true;
00873   }
00874 
00875   else if (view.pixel_format() == VIL_PIXEL_FORMAT_INT_32)
00876   {
00877     if (VXL_BIG_ENDIAN)
00878     {
00879       assert(int_32_im!=0);
00880       os_->seek(byte_start);
00881       for (unsigned k = 0; k < view.nk(); ++k)
00882       {
00883         for (unsigned j = 0; j < view.nj(); ++j)
00884         {
00885           os_->write(int_32_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00886           //byte_start += byte_width;
00887           //os_->seek(byte_start);
00888         }
00889       }
00890     }
00891     else
00892     {
00893       // Little endian host; must convert words to have MSB first.
00894       //
00895       // Convert line by line to avoid duplicating a potentially large image.
00896       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00897       assert(int_32_im!=0);
00898       os_->seek(byte_start);
00899       for (unsigned k = 0; k < view.nk(); ++k)
00900       {
00901         for (unsigned j = 0; j < view.nj(); ++j)
00902         {
00903           vcl_memcpy(&tempbuf[0], int_32_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00904           ConvertHostToMSB((char*)&tempbuf[0], sizeof(vxl_int_32), view.ni());
00905           os_->write(&tempbuf[0], byte_out_width);
00906           //byte_start += byte_width;
00907           //os_->seek(byte_start);
00908         }
00909       }
00910     }
00911 
00912     return true;
00913   }
00914 
00915   else if (view.pixel_format() == VIL_PIXEL_FORMAT_FLOAT)
00916   {
00917     if (VXL_BIG_ENDIAN)
00918     {
00919       assert(float_im!=0);
00920       os_->seek(byte_start);
00921       for (unsigned k = 0; k < view.nk(); ++k)
00922       {
00923         for (unsigned j = 0; j < view.nj(); ++j)
00924         {
00925           os_->write(float_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00926           //byte_start += byte_width;
00927           //os_->seek(byte_start);
00928         }
00929       }
00930     }
00931     else
00932     {
00933       // Little endian host; must convert words to have MSB first.
00934       //
00935       // Convert line by line to avoid duplicating a potentially large image.
00936       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00937       assert(float_im!=0);
00938       os_->seek(byte_start);
00939       for (unsigned k = 0; k < view.nk(); ++k)
00940       {
00941         for (unsigned j = 0; j < view.nj(); ++j)
00942         {
00943           vcl_memcpy(&tempbuf[0], float_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00944           ConvertHostToMSB((char*)&tempbuf[0], sizeof(float), view.ni());
00945           os_->write(&tempbuf[0], byte_out_width);
00946           //byte_start += byte_width;
00947           //os_->seek(byte_start);
00948         }
00949       }
00950     }
00951 
00952     return true;
00953   }
00954 
00955   else if (view.pixel_format() == VIL_PIXEL_FORMAT_DOUBLE)
00956   {
00957     if (VXL_BIG_ENDIAN)
00958     {
00959       assert(double_im!=0);
00960       os_->seek(byte_start);
00961       for (unsigned k = 0; k < view.nk(); ++k)
00962       {
00963         for (unsigned j = 0; j < view.nj(); ++j)
00964         {
00965           os_->write(double_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00966           //byte_start += byte_width;
00967           //os_->seek(byte_start);
00968         }
00969       }
00970     }
00971     else
00972     {
00973       // Little endian host; must convert words to have MSB first.
00974       //
00975       // Convert line by line to avoid duplicating a potentially large image.
00976       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00977       assert(double_im!=0);
00978       os_->seek(byte_start);
00979       for (unsigned k = 0; k < view.nk(); ++k)
00980       {
00981         for (unsigned j = 0; j < view.nj(); ++j)
00982         {
00983           vcl_memcpy(&tempbuf[0], double_im->origin_ptr()+(k*view.nj()*view.ni())+ (j * view.ni()), byte_out_width);
00984           ConvertHostToMSB((char*)&tempbuf[0], sizeof(double), view.ni());
00985           os_->write(&tempbuf[0], byte_out_width);
00986           //byte_start += byte_width;
00987           //os_->seek(byte_start);
00988         }
00989       }
00990     }
00991 
00992     return true;
00993   }
00994   else
00995   {
00996     vcl_cerr << "ERROR: " << __FILE__ << ":\n Do not support putting "
00997              << view.is_a() << " views into gipl image_resource objects\n";
00998     return false;
00999   }
01000 }