core/vil1/file_formats/vil1_viff.cxx

Go to the documentation of this file.
00001 // This is core/vil1/file_formats/vil1_viff.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "vil1_viff.h"
00007 extern "C" {
00008 #include "vil1_viff_support.h"
00009 }
00010 #include <vcl_cassert.h>
00011 
00012 char const* vil1_viff_format_tag = "viff";
00013 
00014 #include <vcl_iostream.h>
00015 #include <vcl_cstring.h>
00016 
00017 #include <vil1/vil1_stream.h>
00018 #include <vil1/vil1_image_impl.h>
00019 #include <vil1/vil1_image.h>
00020 #include <vil1/vil1_property.h>
00021 
00022 static inline void swap(void* p,int length)
00023 {
00024   char* t = (char*)p;
00025 #ifdef DEBUG
00026   if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00027     vcl_cerr << "Swapping " << *(vxl_uint_32*)p;
00028     if (length == sizeof(float))
00029       vcl_cerr << " (or " << *(float*)p << ')';
00030   }
00031 #endif
00032   for (int j=0;2*j<length;++j)
00033   {
00034     char c = t[j];
00035     t[j] = t[length-j-1];
00036     t[length-j-1] = c;
00037   }
00038 #ifdef DEBUG
00039   if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00040     vcl_cerr << " to " << *(vxl_uint_32*)p;
00041     if (length == sizeof(float))
00042       vcl_cerr << " (or " << *(float*)p << ')';
00043     vcl_cerr << '\n';
00044   }
00045 #endif
00046 }
00047 
00048 vil1_image_impl* vil1_viff_file_format::make_input_image(vil1_stream* is)
00049 {
00050   // Attempt to read header
00051   if (!is) return 0;
00052   is->seek(0L);
00053   vil1_viff_xvimage header;
00054   if (VIFF_HEADERSIZE != is->read((void*)(&header),VIFF_HEADERSIZE))
00055     return 0;
00056 
00057   if (header.identifier != (char)XV_FILE_MAGIC_NUM ||
00058       header.file_type != (char)XV_FILE_TYPE_XVIFF)
00059     return 0;
00060 
00061   vxl_uint_32 dst = header.data_storage_type;
00062   if ((dst & 0xff) == 0)
00063     swap(&dst,sizeof(dst));
00064   switch (dst)
00065   {
00066     case VFF_TYP_BIT:
00067     case VFF_TYP_1_BYTE:
00068     case VFF_TYP_2_BYTE:
00069     case VFF_TYP_4_BYTE:
00070     case VFF_TYP_FLOAT:
00071     case VFF_TYP_DOUBLE:
00072     case VFF_TYP_COMPLEX:
00073     case VFF_TYP_DCOMPLEX:
00074       return new vil1_viff_generic_image(is);
00075     default:
00076       vcl_cout << "vil1_viff: non supported data type: VFF_TYP "
00077                << header.data_storage_type << vcl_endl;
00078       return 0;
00079   }
00080 }
00081 
00082 vil1_image_impl* vil1_viff_file_format::make_output_image(vil1_stream* is, int planes,
00083                                                           int width,
00084                                                           int height,
00085                                                           int components,
00086                                                           int bits_per_component,
00087                                                           vil1_component_format format)
00088 {
00089   return new vil1_viff_generic_image(is, planes, width, height, components, bits_per_component, format);
00090 }
00091 
00092 char const* vil1_viff_file_format::tag() const
00093 {
00094   return vil1_viff_format_tag;
00095 }
00096 
00097 /////////////////////////////////////////////////////////////////////////////
00098 
00099 vil1_viff_generic_image::vil1_viff_generic_image(vil1_stream* is)
00100   : is_(is)
00101 {
00102   is_->ref();
00103   if (!read_header())
00104   {
00105     vcl_cerr << "vil1_viff: cannot read file header; creating dummy 0x0 image\n";
00106     start_of_data_ = VIFF_HEADERSIZE; endian_consistent_ = true;
00107     width_ = height_ = 0; planes_ = 1; maxval_ = 255;
00108     bits_per_component_ = 8; format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00109   }
00110 }
00111 
00112 bool vil1_viff_generic_image::get_property(char const *tag, void *prop) const
00113 {
00114   if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00115     return prop ? (*(bool*)prop) = true : true;
00116 
00117   if (0==vcl_strcmp(tag, vil1_property_left_first))
00118     return prop ? (*(bool*)prop) = true : true;
00119 
00120   return false;
00121 }
00122 
00123 char const* vil1_viff_generic_image::file_format() const
00124 {
00125   return vil1_viff_format_tag;
00126 }
00127 
00128 vil1_viff_generic_image::vil1_viff_generic_image(vil1_stream* is, int planes,
00129                                                  int width,
00130                                                  int height,
00131                                                  int /*components*/,
00132                                                  int bits_per_component,
00133                                                  vil1_component_format format)
00134   : is_(is), width_(width), height_(height),
00135     maxval_(255), planes_(planes), start_of_data_(VIFF_HEADERSIZE),
00136     bits_per_component_(bits_per_component),
00137     format_(format), endian_consistent_(true)
00138 {
00139   is_->ref();
00140   write_header();
00141 }
00142 
00143 vil1_viff_generic_image::~vil1_viff_generic_image()
00144 {
00145   is_->unref();
00146 }
00147 
00148 bool vil1_viff_generic_image::read_header()
00149 {
00150   // Go to start
00151   is_->seek(0L);
00152   start_of_data_ = VIFF_HEADERSIZE;
00153 
00154   // Read header
00155   if (VIFF_HEADERSIZE != is_->read((void*)(&header_),VIFF_HEADERSIZE))
00156     return false;
00157 
00158   if (header_.identifier != (char)XV_FILE_MAGIC_NUM ||
00159       header_.file_type != (char)XV_FILE_TYPE_XVIFF)
00160     return false;
00161 
00162   check_endian();
00163 
00164   //Copy width and height from header
00165   maxval_ = 0;
00166 
00167   vxl_uint_32 rs = header_.row_size;
00168   vxl_uint_32 cs = header_.col_size;
00169   vxl_uint_32 dst = header_.data_storage_type;
00170   vxl_uint_32 ndb = header_.num_data_bands;
00171 
00172   vxl_uint_32 ispare1 = header_.ispare1;
00173   vxl_uint_32 ispare2 = header_.ispare2;
00174   float fspare1 = header_.fspare1;
00175   float fspare2 = header_.fspare2;
00176 
00177   if (!endian_consistent_)
00178   {
00179     swap(&rs,sizeof(rs));
00180     swap(&cs,sizeof(cs));
00181     swap(&dst,sizeof(dst));
00182     swap(&ndb,sizeof(ndb));
00183     swap(&ispare1,sizeof(ispare1));
00184     swap(&ispare2,sizeof(ispare2));
00185     swap(&fspare1,sizeof(fspare1));
00186     swap(&fspare2,sizeof(fspare2));
00187   }
00188 
00189   width_ = rs;
00190   height_ = cs;
00191   planes_ = (int)ndb; // number of colour bands
00192 
00193   // decide on data storage type
00194   switch (dst)
00195   {
00196     case VFF_TYP_BIT:
00197       format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00198       bits_per_component_ = 1;
00199       break;
00200     case VFF_TYP_1_BYTE:
00201       format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00202       bits_per_component_ = 8;
00203       break;
00204     case VFF_TYP_2_BYTE:
00205       format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00206       bits_per_component_ = 16;
00207       break;
00208     case VFF_TYP_4_BYTE:
00209       format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00210       bits_per_component_ = 32;
00211       break;
00212     case VFF_TYP_FLOAT:
00213       format_ = VIL1_COMPONENT_FORMAT_IEEE_FLOAT;
00214       bits_per_component_ = 32;
00215       break;
00216     case VFF_TYP_DOUBLE:
00217       format_ = VIL1_COMPONENT_FORMAT_IEEE_FLOAT;
00218       bits_per_component_ = 64;
00219       break;
00220     case VFF_TYP_COMPLEX:
00221       format_ = VIL1_COMPONENT_FORMAT_COMPLEX;
00222       bits_per_component_ = 64;
00223       break;
00224     case VFF_TYP_DCOMPLEX:
00225       format_ = VIL1_COMPONENT_FORMAT_COMPLEX;
00226       bits_per_component_ = 128;
00227       break;
00228     default:
00229       vcl_cout << "vil1_viff: non supported data type: VFF_TYP "
00230                <<   header_.data_storage_type << vcl_endl;
00231       format_ = VIL1_COMPONENT_FORMAT_UNKNOWN;
00232       return false;
00233   }
00234 
00235   return true;
00236 }
00237 
00238 bool vil1_viff_generic_image::write_header()
00239 {
00240   is_->seek(0L);
00241   int type;
00242   if (bits_per_component_ > 1)
00243     bits_per_component_ = 8*((bits_per_component_+7)/8); // round to next 8-tuple
00244 
00245   if (component_format()==VIL1_COMPONENT_FORMAT_SIGNED_INT ||
00246       component_format()==VIL1_COMPONENT_FORMAT_UNSIGNED_INT)
00247   {
00248     switch (bits_per_component_)
00249     {
00250       case 1: type=VFF_TYP_BIT; break;
00251       case 8: type=VFF_TYP_1_BYTE; break;
00252       case 16: type=VFF_TYP_2_BYTE; break;
00253       case 32: type=VFF_TYP_4_BYTE; break;
00254       default:
00255         vcl_cerr << "vil1_viff: non supported data type: " << bits_per_component_ << " bit pixels\n";
00256         return false;
00257     }
00258   }
00259   else if (component_format()==VIL1_COMPONENT_FORMAT_IEEE_FLOAT)
00260   {
00261     switch (bits_per_component_)
00262     {
00263       case 32: type=VFF_TYP_FLOAT; break;
00264       case 64: type=VFF_TYP_DOUBLE; break;
00265       default:
00266         vcl_cerr << "vil1_viff: non supported data type: " << bits_per_component_ << " bit float pixels\n";
00267         return false;
00268     }
00269   }
00270   else if (component_format()==VIL1_COMPONENT_FORMAT_COMPLEX)
00271   {
00272     switch (bits_per_component_)
00273     {
00274       case 64: type=VFF_TYP_COMPLEX; break;
00275       case 128: type=VFF_TYP_DCOMPLEX; break;
00276       default:
00277         vcl_cerr << "vil1_viff: non supported data type: " << bits_per_component_ << " bit complex pixels\n";
00278         return false;
00279     }
00280   }
00281   else
00282   {
00283     vcl_cout << "vil1_viff: non supported data type: " << (short)component_format() << vcl_endl;
00284     return false;
00285   }
00286 
00287   //create header
00288   vil1_viff_xvimage *imagep = vil1_viff_createimage(height_, width_,
00289                                                     type, 1, planes_,
00290                                                     "vil1_viff image writer output",0,0,
00291                                                     VFF_MS_NONE,VFF_MAPTYP_NONE,VFF_LOC_IMPLICIT,0);
00292 
00293   //make local copy of header
00294   vcl_memcpy(&header_, imagep, sizeof(header_));
00295   start_of_data_ = sizeof(header_);
00296 
00297   // release xv header from createimage
00298   vil1_viff_freeimage(imagep);
00299 
00300   is_->write((void*)(&header_), start_of_data_);
00301   start_of_data_ = is_->tell();
00302   return true;
00303 }
00304 
00305 bool vil1_viff_generic_image::get_section(void* buf, int x0, int y0, int xs, int ys) const
00306 {
00307   assert(x0>=0); assert(y0>=0);
00308   assert((x0+xs)<=width_);
00309   assert((y0+ys)<=height_);
00310   if (!buf) return false; // no storage location given
00311   unsigned char* ib = (unsigned char*) buf;
00312   if ((x0*bits_per_component_)%8 != 0)
00313     vcl_cerr << "vil1_viff_generic_image::get_section(): Warning: x0 should be a multiple of 8 for this type of image\n";
00314 
00315   vxl_uint_32 rowsize = (bits_per_component_*xs+7)/8;
00316   vxl_uint_32 tbytes = rowsize*ys*planes_;
00317   for (int p = 0; p<planes_; ++p) {
00318     for (int y = y0; y < y0+ys; ++y) {
00319       is_->seek(start_of_data_ + p*height_*((width_*bits_per_component_+7)/8)
00320                                + y*((width_*bits_per_component_+7)/8)
00321                                + x0*bits_per_component_/8);
00322       is_->read(ib, rowsize);
00323       ib += rowsize;
00324     }
00325   }
00326   if (!endian_consistent_) {
00327     ib = (unsigned char*) buf;
00328     for (unsigned int i=0;i<tbytes;i+=bits_per_component_/8)
00329       swap(ib+i,bits_per_component_/8);
00330   }
00331 
00332   return true;
00333 }
00334 
00335 bool vil1_viff_generic_image::put_section(void const* buf, int x0, int y0, int xs, int ys)
00336 {
00337   assert(x0>=0); assert(y0>=0);
00338   assert((x0+xs)<=width_);
00339   assert((y0+ys)<=height_);
00340   if (!buf) return false; // no storage location given
00341   unsigned char const* ob = (unsigned char const*) buf;
00342   if ((x0*bits_per_component_)%8 != 0)
00343     vcl_cerr << "vil1_viff_generic_image::put_section(): Warning: x0 should be a multiple of 8 for this type of image\n";
00344 
00345   vxl_uint_32 rowsize = (bits_per_component_*xs+7)/8;
00346   if (endian_consistent_)
00347     for (int p = 0; p<planes_; ++p)
00348       for (int y = y0; y < y0+ys; ++y) {
00349         is_->seek(start_of_data_ + p*height_*((width_*bits_per_component_+7)/8)
00350                                  + y*((width_*bits_per_component_+7)/8)
00351                                  + x0*bits_per_component_/8);
00352         is_->write(ob, rowsize);
00353         ob += rowsize;
00354       }
00355   else {
00356     unsigned char* tempbuf = new unsigned char[rowsize];
00357     for (int p = 0; p<planes_; ++p)
00358       for (int y = y0; y < y0+ys; ++y) {
00359         vcl_memcpy(tempbuf, ob, rowsize);
00360         for (unsigned int i=0; i<rowsize; i+=bits_per_component_/8)
00361           swap(tempbuf+i,bits_per_component_/8);
00362         is_->seek(start_of_data_ + p*width_*height_*bits_per_component_/8 + bits_per_component_*(y*width_+x0)/8);
00363         is_->write(tempbuf, rowsize);
00364         ob += rowsize;
00365       }
00366     delete[] tempbuf;
00367   }
00368   return true;
00369 }
00370 
00371 bool vil1_viff_generic_image::check_endian()
00372 {
00373   // check if format is consistent
00374   // Check the data_storage_type in the header
00375   // If it is between 1 and 255, the "Endian" is consistent with the system
00376   // if not, we swap and check again
00377 
00378   vxl_uint_32 dst = header_.data_storage_type;
00379 
00380   endian_consistent_ = ((dst & 0xff) != 0);
00381 #ifdef DEBUG
00382   if (endian_consistent_)
00383     vcl_cerr << "Endian is Consistent\n";
00384   else
00385     vcl_cerr << "Endian is NOT Consistent\n";
00386 #endif
00387   return endian_consistent_;
00388 }
00389 
00390 vil1_image vil1_viff_generic_image::get_plane(unsigned int plane) const
00391 {
00392   assert((int)plane < planes_);
00393   vcl_cerr << "FIXME: this should be an adapter that shifts to the plane asked for\n";
00394   return const_cast<vil1_viff_generic_image*>(this);
00395 }
00396 
00397 bool vil1_viff_generic_image::get_section_rgb_byte(void* /*buf*/, int /*x0*/, int /*y0*/, int /*width*/, int /*height*/) const
00398 {
00399   vcl_cerr << "FIXME: vil1_viff_generic_image::get_section_rgb_byte() not yet implemented\n";
00400   return false;
00401 }
00402 
00403 bool vil1_viff_generic_image::get_section_float(void* buf, int x0, int y0, int width, int height) const
00404 {
00405   if (component_format()!=VIL1_COMPONENT_FORMAT_IEEE_FLOAT || bits_per_component_ != 32)
00406     return false;
00407   return get_section(buf,x0,y0,width,height);
00408 }
00409 
00410 bool vil1_viff_generic_image::get_section_byte(void* buf, int x0, int y0, int width, int height) const
00411 {
00412   if (component_format()!=VIL1_COMPONENT_FORMAT_UNSIGNED_INT || bits_per_component_ != 8)
00413     return false;
00414   return get_section(buf,x0,y0,width,height);
00415 }
00416 
00417 void vil1_viff_generic_image::set_ispare1(vxl_uint_32 ispare1)
00418 {
00419   header_.ispare1 = ispare1;
00420   int longsize = sizeof(vxl_uint_32);
00421   unsigned char* bytes = new unsigned char[longsize];
00422   vcl_memcpy(bytes,&ispare1,longsize);
00423   if (!endian_consistent_)
00424     swap(bytes,longsize);
00425 
00426   is_->seek((int)((unsigned char*)&header_.ispare1 - (unsigned char*)&header_));
00427   is_->write(bytes, longsize);
00428   delete[] bytes;
00429 }
00430 
00431 void vil1_viff_generic_image::set_ispare2(vxl_uint_32 ispare2)
00432 {
00433   header_.ispare2 = ispare2;
00434   int longsize = sizeof(vxl_uint_32);
00435   unsigned char* bytes = new unsigned char[longsize];
00436   vcl_memcpy(bytes,&ispare2,longsize);
00437   if (!endian_consistent_)
00438     swap(bytes,longsize);
00439 
00440   is_->seek((int)((unsigned char*)&header_.ispare2 - (unsigned char*)&header_));
00441   is_->write(bytes, longsize);
00442   delete[] bytes;
00443 }
00444 
00445 void vil1_viff_generic_image::set_fspare1(float fspare1)
00446 {
00447   header_.fspare1 = fspare1;
00448   int floatsize = sizeof(float);
00449   unsigned char* bytes = new unsigned char[floatsize];
00450   vcl_memcpy(bytes,&fspare1,floatsize);
00451   if (!endian_consistent_)
00452     swap(bytes,floatsize);
00453 
00454   is_->seek((int)((unsigned char*)&header_.fspare1 - (unsigned char*)&header_));
00455   is_->write(bytes, floatsize);
00456 
00457   delete[] bytes;
00458 }
00459 
00460 void vil1_viff_generic_image::set_fspare2(float fspare2)
00461 {
00462   header_.fspare2 = fspare2;
00463   int floatsize = sizeof(float);
00464   unsigned char* bytes = new unsigned char[floatsize];
00465   vcl_memcpy(bytes,&fspare2,floatsize);
00466   if (!endian_consistent_)
00467     swap(bytes,floatsize);
00468 
00469   is_->seek((int)((unsigned char*)&header_.fspare2 - (unsigned char*)&header_));
00470   is_->write(bytes, floatsize);
00471   delete[] bytes;
00472 }

Generated on Sat Nov 22 05:08:29 2008 for core/vil1 by  doxygen 1.5.1