00001
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
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 * , void * ) const
00125 {
00126
00127 return false;
00128 }
00129
00130 bool vil_viff_image::read_header()
00131 {
00132
00133 is_->seek(0L);
00134 start_of_data_ = VIFF_HEADERSIZE;
00135
00136
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
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;
00172
00173
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
00227 vil_viff_xvimage image(ni_, nj_, type, nplanes_);
00228
00229
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_);
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
00297 vil_image_view<vxl_byte> const& ibuf = reinterpret_cast<vil_image_view<vxl_byte> const&>(buf);
00298
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 {
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
00358
00359
00360
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 }