00001
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
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 * , void * ) const
00127 {
00128
00129 return false;
00130 }
00131
00132 bool vil_viff_image::read_header()
00133 {
00134
00135 is_->seek(0L);
00136 start_of_data_ = VIFF_HEADERSIZE;
00137
00138
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
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;
00174
00175
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;
00226 }
00227
00228
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
00235 vcl_memcpy(&header_, imagep, sizeof(header_));
00236 start_of_data_ = sizeof(header_);
00237
00238
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_);
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 {
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
00365
00366
00367
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 }