Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

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

Generated on Thu Jan 10 14:40:00 2008 for core/vil by  doxygen 1.4.4