core/vil/file_formats/vil_viff.cxx
Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_viff.cxx
00002 #include "vil_viff.h"
00003 #include <vcl_cassert.h>
00004 #include <vcl_complex.h>
00005 
00006 static char const* vil_viff_format_tag = "viff";
00007 
00008 #include <vcl_iostream.h>
00009 #include <vcl_cstring.h>
00010 
00011 #include <vil/vil_stream.h>
00012 #include <vil/vil_image_resource.h>
00013 #include <vil/vil_image_view.h>
00014 #include <vil/vil_exception.h>
00015 
00016 static inline void swap(void* p,int length)
00017 {
00018   char* t = (char*)p;
00019 #ifdef DEBUG
00020   if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00021     vcl_cerr << "Swapping " << *(vxl_uint_32*)p;
00022     if (length == sizeof(float))
00023       vcl_cerr << " (or " << *(float*)p << ')';
00024   }
00025 #endif
00026   for (int j=0;2*j<length;++j)
00027   {
00028     char c = t[j];
00029     t[j] = t[length-j-1];
00030     t[length-j-1] = c;
00031   }
00032 #ifdef DEBUG
00033   if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00034     vcl_cerr << " to " << *(vxl_uint_32*)p;
00035     if (length == sizeof(float))
00036       vcl_cerr << " (or " << *(float*)p << ')';
00037     vcl_cerr << '\n';
00038   }
00039 #endif
00040 }
00041 
00042 vil_image_resource_sptr vil_viff_file_format::make_input_image(vil_stream* is)
00043 {
00044   // Attempt to read header
00045   if (!is) return 0;
00046   is->seek(0L);
00047   vil_viff_xvimage header;
00048   if (VIFF_HEADERSIZE != is->read((void*)(&header),VIFF_HEADERSIZE))
00049     return 0;
00050 
00051   if (header.identifier != (char)XV_FILE_MAGIC_NUM ||
00052       header.file_type != (char)XV_FILE_TYPE_XVIFF)
00053     return 0;
00054 
00055   vxl_uint_32 dst = header.data_storage_type;
00056   if ((dst & 0xff) == 0)
00057     swap(&dst,sizeof(dst));
00058   switch (dst)
00059   {
00060     case VFF_TYP_BIT:
00061     case VFF_TYP_1_BYTE:
00062     case VFF_TYP_2_BYTE:
00063     case VFF_TYP_4_BYTE:
00064     case VFF_TYP_FLOAT:
00065     case VFF_TYP_DOUBLE:
00066     case VFF_TYP_COMPLEX:
00067     case VFF_TYP_DCOMPLEX:
00068       return new vil_viff_image(is);
00069     default:
00070       vcl_cout << "vil_viff: non supported data type: VFF_TYP "
00071                << header.data_storage_type << vcl_endl;
00072       return 0;
00073   }
00074 }
00075 
00076 vil_image_resource_sptr vil_viff_file_format::make_output_image(vil_stream* is,
00077                                                                 unsigned int ni, unsigned int nj, unsigned int nplanes,
00078                                                                 vil_pixel_format format)
00079 {
00080   return new vil_viff_image(is, ni, nj, nplanes, format);
00081 }
00082 
00083 char const* vil_viff_file_format::tag() const
00084 {
00085   return vil_viff_format_tag;
00086 }
00087 
00088 /////////////////////////////////////////////////////////////////////////////
00089 
00090 vil_viff_image::vil_viff_image(vil_stream* is)
00091   : is_(is)
00092 {
00093   is_->ref();
00094   if (!read_header())
00095   {
00096     vcl_cerr << "vil_viff: cannot read file header; creating dummy 0x0 image\n";
00097     start_of_data_ = VIFF_HEADERSIZE; endian_consistent_ = true;
00098     ni_ = nj_ = 0; nplanes_ = 1;
00099     format_ = VIL_PIXEL_FORMAT_BYTE;
00100   }
00101 }
00102 
00103 char const* vil_viff_image::file_format() const
00104 {
00105   return vil_viff_format_tag;
00106 }
00107 
00108 vil_viff_image::vil_viff_image(vil_stream* is,
00109                                unsigned int ni, unsigned int nj, unsigned int nplanes,
00110                                vil_pixel_format format)
00111   : is_(is), ni_(ni), nj_(nj),
00112     nplanes_(nplanes), start_of_data_(VIFF_HEADERSIZE),
00113     format_(format), endian_consistent_(true)
00114 {
00115   is_->ref();
00116   write_header();
00117 }
00118 
00119 vil_viff_image::~vil_viff_image()
00120 {
00121   is_->unref();
00122 }
00123 
00124 bool vil_viff_image::get_property(char const * /*tag*/, void * /*prop*/) const
00125 {
00126   // This is not an in-memory image type, nor is it read-only:
00127   return false;
00128 }
00129 
00130 bool vil_viff_image::read_header()
00131 {
00132   // Go to start
00133   is_->seek(0L);
00134   start_of_data_ = VIFF_HEADERSIZE;
00135 
00136   // Read header
00137   if (VIFF_HEADERSIZE != is_->read((void*)(&header_),VIFF_HEADERSIZE))
00138     return false;
00139 
00140   if (header_.identifier != (char)XV_FILE_MAGIC_NUM ||
00141       header_.file_type != (char)XV_FILE_TYPE_XVIFF)
00142     return false;
00143 
00144   check_endian();
00145 
00146   //Copy ni and nj from header
00147   vxl_uint_32 rs = header_.row_size;
00148   vxl_uint_32 cs = header_.col_size;
00149   vxl_uint_32 dst = header_.data_storage_type;
00150   vxl_uint_32 ndb = header_.num_data_bands;
00151 
00152   vxl_uint_32 ispare1 = header_.ispare1;
00153   vxl_uint_32 ispare2 = header_.ispare2;
00154   float fspare1 = header_.fspare1;
00155   float fspare2 = header_.fspare2;
00156 
00157   if (!endian_consistent_)
00158   {
00159     swap(&rs,sizeof(rs));
00160     swap(&cs,sizeof(cs));
00161     swap(&dst,sizeof(dst));
00162     swap(&ndb,sizeof(ndb));
00163     swap(&ispare1,sizeof(ispare1));
00164     swap(&ispare2,sizeof(ispare2));
00165     swap(&fspare1,sizeof(fspare1));
00166     swap(&fspare2,sizeof(fspare2));
00167   }
00168 
00169   ni_ = rs;
00170   nj_ = cs;
00171   nplanes_ = (int)ndb; // number of colour bands
00172 
00173   // decide on data storage type
00174   format_ = VIL_PIXEL_FORMAT_UNKNOWN;
00175   if (dst == VFF_TYP_BIT)
00176     format_ = VIL_PIXEL_FORMAT_BOOL;
00177   else if (dst == VFF_TYP_1_BYTE)
00178     format_ = VIL_PIXEL_FORMAT_BYTE;
00179   else if (dst == VFF_TYP_2_BYTE)
00180     format_ = VIL_PIXEL_FORMAT_UINT_16;
00181   else if (dst == VFF_TYP_4_BYTE)
00182     format_ = VIL_PIXEL_FORMAT_UINT_32;
00183   else if (dst == VFF_TYP_FLOAT)
00184     format_ = VIL_PIXEL_FORMAT_FLOAT;
00185   else if (dst == VFF_TYP_DOUBLE)
00186     format_ = VIL_PIXEL_FORMAT_DOUBLE;
00187   else if (dst == VFF_TYP_COMPLEX)
00188     format_ = VIL_PIXEL_FORMAT_COMPLEX_FLOAT;
00189   else if (dst == VFF_TYP_DCOMPLEX)
00190     format_ = VIL_PIXEL_FORMAT_COMPLEX_DOUBLE;
00191   else
00192     vcl_cout << "vil_viff: non supported data type: VFF_TYP " << dst << '\n';
00193   return format_ != VIL_PIXEL_FORMAT_UNKNOWN;
00194 }
00195 
00196 bool vil_viff_image::write_header()
00197 {
00198   is_->seek(0L);
00199   vil_viff_data_storage type;
00200 
00201   if (format_==VIL_PIXEL_FORMAT_UINT_32 ||
00202       format_==VIL_PIXEL_FORMAT_INT_32)
00203     type=VFF_TYP_4_BYTE;
00204   else if (format_==VIL_PIXEL_FORMAT_UINT_16 ||
00205            format_==VIL_PIXEL_FORMAT_INT_16)
00206     type=VFF_TYP_2_BYTE;
00207   else if (format_==VIL_PIXEL_FORMAT_BYTE ||
00208            format_==VIL_PIXEL_FORMAT_SBYTE)
00209     type=VFF_TYP_1_BYTE;
00210   else if (format_==VIL_PIXEL_FORMAT_BOOL)
00211     type=VFF_TYP_BIT;
00212   else if (format_==VIL_PIXEL_FORMAT_FLOAT)
00213     type=VFF_TYP_FLOAT;
00214   else if (format_==VIL_PIXEL_FORMAT_DOUBLE)
00215     type=VFF_TYP_DOUBLE;
00216   else if (format_==VIL_PIXEL_FORMAT_COMPLEX_FLOAT)
00217     type=VFF_TYP_COMPLEX;
00218   else if (format_==VIL_PIXEL_FORMAT_COMPLEX_DOUBLE)
00219     type=VFF_TYP_DCOMPLEX;
00220   else
00221   {
00222     vcl_cout << "vil_viff: non supported data type: " << (short)format_ << '\n';
00223     return false;
00224   }
00225 
00226   //create header
00227   vil_viff_xvimage image(ni_, nj_, type, nplanes_);
00228 
00229   //make local copy of header
00230   vcl_memcpy(&header_, &image, sizeof(header_));
00231   start_of_data_ = sizeof(header_);
00232 
00233 
00234   is_->write((void*)(&header_), start_of_data_);
00235   start_of_data_ = is_->tell();
00236   return true;
00237 }
00238 
00239 vil_image_view_base_sptr vil_viff_image::get_copy_view(unsigned int x0, unsigned int xs,
00240                                                        unsigned int y0, unsigned int ys) const
00241 {
00242   assert(x0+xs<=ni_);
00243   assert(y0+ys<=nj_);
00244   unsigned int pix_size = 8*vil_pixel_format_sizeof_components(format_);
00245   if (format_==VIL_PIXEL_FORMAT_BOOL) pix_size = 1;
00246   if (format_==VIL_PIXEL_FORMAT_BOOL && x0%8 != 0)
00247     vcl_cerr << "vil_viff_image::get_copy_view(): Warning: x0 should be a multiple of 8 for this type of image\n";
00248 
00249   vxl_uint_32 rowsize = (pix_size*xs+7)/8;
00250   vxl_uint_32 tbytes = rowsize*ys*nplanes_;
00251   vil_memory_chunk_sptr buf = new vil_memory_chunk(tbytes,format_);
00252   vxl_byte* ib = reinterpret_cast<vxl_byte*>(buf->data());
00253   for (unsigned int p = 0; p<nplanes_; ++p) {
00254     for (unsigned int y = y0; y < y0+ys; ++y) {
00255       is_->seek(start_of_data_ + p*nj_*((ni_*pix_size+7)/8)
00256                                + y*((ni_*pix_size+7)/8)
00257                                + x0*pix_size/8);
00258       is_->read(ib, rowsize);
00259       ib += rowsize;
00260     }
00261   }
00262   if (!endian_consistent_) {
00263     ib = reinterpret_cast<vxl_byte*>(buf->data());
00264     for (unsigned int i=0;i<tbytes;i+=(pix_size+7)/8)
00265       swap(ib+i,(pix_size+7)/8);
00266   }
00267 
00268 #define ARGS(T) buf, reinterpret_cast<T*>(buf->data()), xs,ys,nplanes_, 1,xs,xs*ys
00269   if (format_ == VIL_PIXEL_FORMAT_BOOL)                return new vil_image_view<bool>                (ARGS(bool));
00270   else if (format_ == VIL_PIXEL_FORMAT_BYTE)           return new vil_image_view<vxl_byte>            (ARGS(vxl_byte));
00271   else if (format_ == VIL_PIXEL_FORMAT_UINT_16)        return new vil_image_view<vxl_uint_16>         (ARGS(vxl_uint_16));
00272   else if (format_ == VIL_PIXEL_FORMAT_UINT_32)        return new vil_image_view<vxl_uint_32>         (ARGS(vxl_uint_32));
00273   else if (format_ == VIL_PIXEL_FORMAT_FLOAT)          return new vil_image_view<float>               (ARGS(float));
00274   else if (format_ == VIL_PIXEL_FORMAT_DOUBLE)         return new vil_image_view<double>              (ARGS(double));
00275   else if (format_ == VIL_PIXEL_FORMAT_COMPLEX_FLOAT)  return new vil_image_view<vcl_complex<float> > (ARGS(vcl_complex<float>));
00276   else if (format_ == VIL_PIXEL_FORMAT_COMPLEX_DOUBLE) return new vil_image_view<vcl_complex<double> >(ARGS(vcl_complex<double>));
00277   else return 0;
00278 #undef ARGS
00279 }
00280 
00281 bool vil_viff_image::put_view(vil_image_view_base const& buf, unsigned int x0, unsigned int y0)
00282 {
00283   assert(buf.pixel_format() == format_); // pixel formats of image and buffer must match
00284   if (!view_fits(buf, x0, y0) || buf.nplanes() != nplanes())
00285   {
00286     vil_exception_warning(vil_exception_out_of_bounds("vil_viff_image::put_view"));
00287     return false;
00288   }
00289   unsigned int ni = buf.ni();
00290   unsigned int nj = buf.nj();
00291 #ifdef DEBUG
00292   vcl_cerr << "vil_viff_image::put_view() : buf="
00293            << ni<<'x'<<nj<<'x'<< buf.nplanes()<<'p'
00294            << " at ("<<x0<<','<<y0<<")\n";
00295 #endif
00296   //vcl_cout << "buf=" << buf << '\n';
00297   vil_image_view<vxl_byte> const& ibuf = reinterpret_cast<vil_image_view<vxl_byte> const&>(buf);
00298   //vcl_cout << "ibuf=" << ibuf << '\n';
00299   if (ibuf.istep() != 1 || ibuf.jstep() != int(ni) ||
00300       (ibuf.planestep() != int(ni*nj) && nplanes() != 1))
00301   {
00302     vcl_cerr << "ERROR: " << __FILE__ << ":\n"
00303              << " view does not fit: istep="<<ibuf.istep()
00304              << ", jstep="<<ibuf.jstep()
00305              << ", planestep="<<ibuf.planestep()
00306              << " instead of 1,"<<ni<<','<<ni*nj<<'\n';
00307     return false;
00308   }
00309   const vxl_byte* ob = ibuf.top_left_ptr();
00310   unsigned int pix_size = 8*vil_pixel_format_sizeof_components(format_);
00311   if (format_==VIL_PIXEL_FORMAT_BOOL) pix_size = 1;
00312   if (format_==VIL_PIXEL_FORMAT_BOOL && x0%8 != 0)
00313     vcl_cerr << "vil_viff_image::put_view(): Warning: x0 should be a multiple of 8 for this type of image\n";
00314 
00315   vxl_uint_32 rowsize = (pix_size*ni+7)/8;
00316   if (endian_consistent_ || pix_size <= 8)
00317     for (unsigned int p = 0; p<nplanes_; ++p)
00318       for (unsigned int y = y0; y < y0+nj; ++y) {
00319         is_->seek(start_of_data_ + p*nj_*((ni_*pix_size+7)/8)
00320                                  + y*((ni_*pix_size+7)/8)
00321                                  + x0*pix_size/8);
00322         if ((vil_streampos)rowsize != is_->write(ob, rowsize))
00323           vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00324                    << " could not write "<<rowsize<<" EC bytes to stream;\n"
00325                    << " p="<<p<<", y="<<y<<'\n';
00326 #ifdef DEBUG
00327         else
00328           vcl_cerr << "written "<<rowsize<<" EC bytes to stream; p="<<p<<", y="<<y<<'\n';
00329 #endif
00330         ob += rowsize;
00331       }
00332   else { // !endian_consistent_ ==> must swap bytes
00333     vxl_byte* tempbuf = new vxl_byte[rowsize];
00334     for (unsigned int p = 0; p<nplanes_; ++p)
00335       for (unsigned int y = y0; y < y0+nj; ++y) {
00336         vcl_memcpy(tempbuf, ob, rowsize);
00337         for (unsigned int i=0; i<rowsize; i+=pix_size/8)
00338           swap(tempbuf+i,pix_size/8);
00339         is_->seek(start_of_data_ + p*ni_*nj_*pix_size/8 + pix_size*(y*ni_+x0)/8);
00340         if ((vil_streampos)rowsize != is_->write(tempbuf, rowsize))
00341           vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00342                    << " could not write "<<rowsize<<" NEC bytes to stream;\n"
00343                    << " p="<<p<<", y="<<y<<'\n';
00344 #ifdef DEBUG
00345         else
00346           vcl_cerr << "written "<<rowsize<<" NEC bytes to stream; p="<<p<<", y="<<y<<'\n';
00347 #endif
00348         ob += rowsize;
00349       }
00350     delete[] tempbuf;
00351   }
00352   return true;
00353 }
00354 
00355 bool vil_viff_image::check_endian()
00356 {
00357   // check if format is consistent
00358   // Check the data_storage_type in the header
00359   // If it is between 1 and 255, the "Endian" is consistent with the system
00360   // if not, we swap and check again
00361 
00362   vxl_uint_32 dst = header_.data_storage_type;
00363 
00364   endian_consistent_ = ((dst & 0xff) != 0);
00365 #ifdef DEBUG
00366   if (endian_consistent_)
00367     vcl_cerr << "Endian is Consistent\n";
00368   else
00369     vcl_cerr << "Endian is NOT Consistent\n";
00370 #endif
00371   return endian_consistent_;
00372 }
00373 
00374 void vil_viff_image::set_ispare1(vxl_uint_32 ispare1)
00375 {
00376   header_.ispare1 = ispare1;
00377   int longsize = sizeof(vxl_uint_32);
00378   vxl_byte* bytes = new vxl_byte[longsize];
00379   vcl_memcpy(bytes,&ispare1,longsize);
00380   if (!endian_consistent_)
00381     swap(bytes,longsize);
00382 
00383   is_->seek((int)((vxl_byte*)&header_.ispare1 - (vxl_byte*)&header_));
00384   is_->write(bytes, longsize);
00385   delete[] bytes;
00386 }
00387 
00388 void vil_viff_image::set_ispare2(vxl_uint_32 ispare2)
00389 {
00390   header_.ispare2 = ispare2;
00391   int longsize = sizeof(vxl_uint_32);
00392   vxl_byte* bytes = new vxl_byte[longsize];
00393   vcl_memcpy(bytes,&ispare2,longsize);
00394   if (!endian_consistent_)
00395     swap(bytes,longsize);
00396 
00397   is_->seek((int)((vxl_byte*)&header_.ispare2 - (vxl_byte*)&header_));
00398   is_->write(bytes, longsize);
00399   delete[] bytes;
00400 }
00401 
00402 void vil_viff_image::set_fspare1(float fspare1)
00403 {
00404   header_.fspare1 = fspare1;
00405   int floatsize = sizeof(float);
00406   vxl_byte* bytes = new vxl_byte[floatsize];
00407   vcl_memcpy(bytes,&fspare1,floatsize);
00408   if (!endian_consistent_)
00409     swap(bytes,floatsize);
00410 
00411   is_->seek((int)((vxl_byte*)&header_.fspare1 - (vxl_byte*)&header_));
00412   is_->write(bytes, floatsize);
00413 
00414   delete[] bytes;
00415 }
00416 
00417 void vil_viff_image::set_fspare2(float fspare2)
00418 {
00419   header_.fspare2 = fspare2;
00420   int floatsize = sizeof(float);
00421   vxl_byte* bytes = new vxl_byte[floatsize];
00422   vcl_memcpy(bytes,&fspare2,floatsize);
00423   if (!endian_consistent_)
00424     swap(bytes,floatsize);
00425 
00426   is_->seek((int)((vxl_byte*)&header_.fspare2 - (vxl_byte*)&header_));
00427   is_->write(bytes, floatsize);
00428   delete[] bytes;
00429 }