00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010 #include "vimt3d_vil3d_v3m.h"
00011
00012 #include <vcl_cstdlib.h>
00013 #include <vcl_cstring.h>
00014 #include <vcl_sstream.h>
00015 #include <vcl_cassert.h>
00016 #include <vcl_ios.h>
00017 #include <vcl_algorithm.h>
00018 #include <vsl/vsl_binary_loader.h>
00019 #include <vsl/vsl_block_binary_rle.h>
00020 #include <vgl/vgl_point_3d.h>
00021 #include <vgl/vgl_vector_3d.h>
00022 #include <vil3d/vil3d_image_view.h>
00023 #include <vil3d/vil3d_copy.h>
00024 #include <vil3d/vil3d_property.h>
00025 #include <vimt3d/vimt3d_image_3d_of.h>
00026 #include <vil/vil_exception.h>
00027
00028
00029 unsigned vimt3d_vil3d_v3m_format::magic_number()
00030 {
00031 return 987123875U;
00032 }
00033
00034 vil3d_image_resource_sptr vimt3d_vil3d_v3m_format::make_input_image(const char *filename) const
00035 {
00036 vcl_auto_ptr<vcl_fstream> file(new vcl_fstream(filename, vcl_ios_in | vcl_ios_binary ));
00037 if (!file.get() || !file->is_open())
00038 return 0;
00039
00040
00041 {
00042 vsl_b_istream is(file.get());
00043 if (!is) return 0;
00044 unsigned magic;
00045 vsl_b_read(is, magic);
00046 if (magic != vimt3d_vil3d_v3m_format::magic_number()) return 0;
00047 }
00048 return new vimt3d_vil3d_v3m_image(file);
00049 }
00050
00051
00052
00053
00054
00055
00056 vil3d_image_resource_sptr vimt3d_vil3d_v3m_format::make_output_image
00057 (const char* filename, unsigned ni, unsigned nj,
00058 unsigned nk, unsigned nplanes, vil_pixel_format format) const
00059 {
00060 if ( format != VIL_PIXEL_FORMAT_BYTE && format != VIL_PIXEL_FORMAT_SBYTE &&
00061 format != VIL_PIXEL_FORMAT_UINT_32 && format != VIL_PIXEL_FORMAT_INT_32 &&
00062 format != VIL_PIXEL_FORMAT_UINT_16 && format != VIL_PIXEL_FORMAT_INT_16 &&
00063 format != VIL_PIXEL_FORMAT_FLOAT && format != VIL_PIXEL_FORMAT_DOUBLE &&
00064 format != VIL_PIXEL_FORMAT_BOOL)
00065 {
00066 vcl_cerr << "vimt3d_vil3d_v3m_format::make_output_image() WARNING\n"
00067 << " Unable to deal with file format : " << format << vcl_endl;
00068 return 0;
00069 }
00070
00071 vcl_auto_ptr<vcl_fstream> of(
00072 new vcl_fstream(filename, vcl_ios_out | vcl_ios_binary | vcl_ios_trunc) );
00073 if (!of.get() || !of->is_open())
00074 {
00075 vcl_cerr << "vimt3d_vil3d_v3m_format::make_output_image() WARNING\n"
00076 << " Unable to open file: " << filename << vcl_endl;
00077 return 0;
00078 }
00079
00080 return new vimt3d_vil3d_v3m_image(of, ni, nj, nk, nplanes, format);
00081 }
00082
00083
00084 bool vimt3d_vil3d_v3m_image::header_t::operator==(const header_t& rhs) const
00085 {
00086 return this->ni == rhs.ni
00087 && this->nj == rhs.nj
00088 && this->nk == rhs.nk
00089 && this->nplanes == rhs.nplanes
00090 && this->pixel_format == rhs.pixel_format
00091 && this->w2i == rhs.w2i;
00092 }
00093
00094
00095 void vimt3d_vil3d_v3m_image::load_full_image() const
00096 {
00097 file_->seekg(0);
00098 vsl_b_istream is(file_);
00099 unsigned magic;
00100 vsl_b_read(is, magic);
00101 if (magic != vimt3d_vil3d_v3m_format::magic_number())
00102 {
00103 im_ =0;
00104 is.is().clear(vcl_ios::badbit);
00105 vil_exception_warning(vil_exception_corrupt_image_file(
00106 "vimt3d_vil3d_v3m_image::load_full_image", "vimt3d_vil3d_v3m_image", "", "Incorrect v3m magic number detected"));
00107 return;
00108 }
00109 short version;
00110 vsl_b_read(is, version);
00111
00112 switch (version)
00113 {
00114 case 1:
00115 {
00116 vsl_b_read(is, header_.ni);
00117 vsl_b_read(is, header_.nj);
00118 vsl_b_read(is, header_.nk);
00119 vsl_b_read(is, header_.nplanes);
00120 int v;
00121 vsl_b_read(is, v);
00122 header_.pixel_format = static_cast<vil_pixel_format>(v);
00123 vsl_b_read(is, header_.w2i);
00124 vcl_size_t size = static_cast<vcl_size_t>(header_.ni) * header_.nj *
00125 header_.nk * header_.nplanes;
00126 vil_memory_chunk_sptr chunk_ptr( new vil_memory_chunk(
00127 size * vil_pixel_format_sizeof_components(header_.pixel_format), header_.pixel_format) );
00128
00129 switch (header_.pixel_format)
00130 {
00131 #define macro( F , T ) \
00132 case F : \
00133 { \
00134 vcl_ptrdiff_t istep=0, jstep=0, kstep=0, pstep=0; \
00135 T* origin_ptr=static_cast<T*>(chunk_ptr->data()); \
00136 if (size) \
00137 { \
00138 vsl_block_binary_rle_read(is, static_cast<T *>(chunk_ptr->data()), size); \
00139 vsl_b_read(is, istep); \
00140 vsl_b_read(is, jstep); \
00141 vsl_b_read(is, kstep); \
00142 vsl_b_read(is, pstep); \
00143 vcl_ptrdiff_t offset; \
00144 vsl_b_read(is, offset); \
00145 origin_ptr += offset; \
00146 } \
00147 im_ = new vimt3d_image_3d_of<T>( \
00148 vil3d_image_view<T>(chunk_ptr, origin_ptr, \
00149 header_.ni, header_.nj, header_.nk, header_.nplanes, \
00150 istep, jstep, kstep, pstep), header_.w2i ); \
00151 } \
00152 break;
00153 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00154
00155
00156
00157
00158 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00159
00160 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00161 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00162 #undef macro
00163 case VIL_PIXEL_FORMAT_INT_32 :
00164 {
00165 vxl_int_32* origin_ptr=static_cast<vxl_int_32*>(chunk_ptr->data());
00166 vcl_ptrdiff_t istep=0, jstep=0, kstep=0, pstep=0;
00167 if (size)
00168 {
00169 vsl_block_binary_rle_read(is, static_cast<vxl_int_32 *>(chunk_ptr->data()), size);
00170 vsl_b_read(is, istep);
00171 vsl_b_read(is, jstep);
00172 vsl_b_read(is, kstep);
00173 vsl_b_read(is, pstep);
00174 vcl_ptrdiff_t offset;
00175 vsl_b_read(is, offset);
00176 origin_ptr += offset;
00177 }
00178 im_ = new vimt3d_image_3d_of<vxl_int_32>(
00179 vil3d_image_view<vxl_int_32>(chunk_ptr, origin_ptr,
00180 header_.ni, header_.nj, header_.nk, header_.nplanes,
00181 istep, jstep, kstep, pstep),
00182 header_.w2i );
00183 }
00184 break;
00185 default:
00186 vil_exception_error(vil_exception_unsupported_pixel_format(
00187 im_->image_base().pixel_format(), "vimt3d_vil3d_v3m_image constructor"));
00188 }
00189 }
00190 break;
00191
00192 default:
00193 im_ =0;
00194 is.is().clear(vcl_ios::badbit);
00195 vcl_ostringstream oss;
00196 oss << "I/O ERROR: vimt3d_vil3d_v3m_image::load_full_image()\n"
00197 << " Unknown version number "<< version << '\n';
00198 vil_exception_warning(vil_exception_invalid_version(
00199 "vimt3d_vil3d_v3m_image::load_full_image", "vimt3d_vil3d_v3m_image", "", oss.str()));
00200 return;
00201 }
00202 if (!is)
00203 {
00204 vil_exception_warning(vil_exception_corrupt_image_file(
00205 "vimt3d_vil3d_v3m_image::load_full_image", "vimt3d_vil3d_v3m_image", "", "Failed to read all expected values."));
00206 im_=0;
00207 }
00208 }
00209
00210
00211
00212
00213 vimt3d_vil3d_v3m_image::vimt3d_vil3d_v3m_image(vcl_auto_ptr<vcl_fstream> file):
00214 file_(file.release()), im_(0), dirty_(false)
00215 {
00216 file_->seekg(0);
00217 vsl_b_istream is(file_);
00218
00219 unsigned magic;
00220 vsl_b_read(is, magic);
00221 if (magic != vimt3d_vil3d_v3m_format::magic_number())
00222 {
00223 is.is().clear(vcl_ios::badbit);
00224 vil_exception_warning(vil_exception_corrupt_image_file(
00225 "vimt3d_vil3d_v3m_image constructor", "vimt3d_vil3d_v3m_image", "", "Incorrect v3m magic number detected"));
00226 return;
00227 }
00228
00229 short version;
00230 vsl_b_read(is, version);
00231
00232 switch (version)
00233 {
00234 case 1:
00235 {
00236 vsl_b_read(is, header_.ni);
00237 vsl_b_read(is, header_.nj);
00238 vsl_b_read(is, header_.nk);
00239 vsl_b_read(is, header_.nplanes);
00240 int v;
00241 vsl_b_read(is, v);
00242 header_.pixel_format = static_cast<vil_pixel_format>(v);
00243 vsl_b_read(is, header_.w2i);
00244
00245 break;
00246 }
00247 default:
00248 vcl_ostringstream oss;
00249 oss << "I/O ERROR: vimt3d_vil3d_v3m_image::vimt3d_vil3d_v3m_image()\n"
00250 << " Unknown version number "<< version << '\n';
00251 vil_exception_warning(vil_exception_invalid_version("vimt3d_vil3d_v3m_image constructor", "vimt3d_vil3d_v3m_image", "", oss.str()));
00252 return;
00253 }
00254 if (!is)
00255 {
00256 vil_exception_warning(vil_exception_image_io(
00257 "vimt3d_vil3d_v3m_image constructor", "vimt3d_vil3d_v3m_image", ""));
00258 }
00259 return;
00260 }
00261
00262
00263
00264 vimt3d_vil3d_v3m_image::vimt3d_vil3d_v3m_image(vcl_auto_ptr<vcl_fstream> file, unsigned ni,
00265 unsigned nj, unsigned nk,
00266 unsigned nplanes,
00267 vil_pixel_format format):
00268 file_(file.release()), im_(0), dirty_(true)
00269 {
00270 header_.ni = ni;
00271 header_.nj = nj;
00272 header_.nk = nk;
00273 header_.nplanes = nplanes;
00274 header_.pixel_format = format;
00275 switch (format)
00276 {
00277 #define macro( F , T ) \
00278 case F : \
00279 im_ = new vimt3d_image_3d_of< T > (ni, nj, nk, nplanes); \
00280 break;
00281 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00282
00283
00284
00285 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00286 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00287
00288 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00289 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00290 #undef macro
00291 default:
00292 vil_exception_error(vil_exception_unsupported_pixel_format(
00293 format, "vimt3d_vil3d_v3m_image constructor"));
00294 }
00295 }
00296
00297
00298 vimt3d_vil3d_v3m_image::~vimt3d_vil3d_v3m_image()
00299 {
00300 if (dirty_)
00301 {
00302 file_->seekp(0);
00303 vsl_b_ostream os(file_);
00304
00305 vsl_b_write(os, vimt3d_vil3d_v3m_format::magic_number());
00306
00307 const short version = 1;
00308 vsl_b_write(os, version);
00309
00310 vsl_b_write(os, im_->image_base().ni());
00311 vsl_b_write(os, im_->image_base().nj());
00312 vsl_b_write(os, im_->image_base().nk());
00313 vsl_b_write(os, im_->image_base().nplanes());
00314 vsl_b_write(os, im_->image_base().pixel_format());
00315 vsl_b_write(os, im_->world2im());
00316
00317 switch (im_->image_base().pixel_format())
00318 {
00319 #define macro( F , T ) \
00320 case F : \
00321 { \
00322 const vil3d_image_view<T> &image = static_cast<vil3d_image_view<T> >(im_->image_base()); \
00323 if (image.size()) \
00324 { \
00325 \
00326 assert(!image || image.size()*sizeof(T) == image.memory_chunk()->size()); \
00327 \
00328 assert(!image || image.pixel_format() == image.memory_chunk()->pixel_format()); \
00329 vsl_block_binary_rle_write(os, static_cast<const T *>(image.memory_chunk()->const_data()), \
00330 image.size()); \
00331 vsl_b_write(os, image.istep()); \
00332 vsl_b_write(os, image.jstep()); \
00333 vsl_b_write(os, image.kstep()); \
00334 vsl_b_write(os, image.planestep()); \
00335 vcl_ptrdiff_t offset = (image.origin_ptr() - \
00336 reinterpret_cast<const T*>(image.memory_chunk()->data())); \
00337 vsl_b_write(os, offset); \
00338 } \
00339 } \
00340 break;
00341 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00342
00343
00344
00345
00346 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00347
00348 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00349 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00350 #undef macro
00351 case VIL_PIXEL_FORMAT_INT_32 :
00352 {
00353 const vil3d_image_view<vxl_int_32> &image = static_cast<vil3d_image_view<vxl_int_32> >(im_->image_base());
00354 if (image.size())
00355 {
00356
00357 assert(!image || image.size()*sizeof(vxl_int_32) == image.memory_chunk()->size());
00358
00359 assert(!image || image.pixel_format() == image.memory_chunk()->pixel_format());
00360 vsl_block_binary_rle_write(os, static_cast<const vxl_int_32 *>(image.memory_chunk()->const_data()),
00361 image.size());
00362 vsl_b_write(os, image.istep());
00363 vsl_b_write(os, image.jstep());
00364 vsl_b_write(os, image.kstep());
00365 vsl_b_write(os, image.planestep());
00366 vcl_ptrdiff_t offset = (image.origin_ptr() -
00367 reinterpret_cast<const vxl_int_32*>(image.memory_chunk()->data()));
00368 vsl_b_write(os, offset);
00369 }
00370 }
00371 break;
00372 default:
00373 vil_exception_error(vil_exception_unsupported_pixel_format(
00374 im_->image_base().pixel_format(), "vimt3d_vil3d_v3m_image constructor"));
00375 }
00376
00377
00378 }
00379 delete file_;
00380 delete im_;
00381 }
00382
00383
00384
00385
00386 unsigned vimt3d_vil3d_v3m_image::nplanes() const
00387 {
00388 return header_.nplanes;
00389 }
00390
00391
00392
00393 unsigned vimt3d_vil3d_v3m_image::ni() const
00394 {
00395 return header_.ni;
00396 }
00397
00398
00399
00400 unsigned vimt3d_vil3d_v3m_image::nj() const
00401 {
00402 return header_.nj;
00403 }
00404
00405
00406
00407 unsigned vimt3d_vil3d_v3m_image::nk() const
00408 {
00409 return header_.nk;
00410 }
00411
00412
00413 enum vil_pixel_format vimt3d_vil3d_v3m_image::pixel_format() const
00414 {
00415 return header_.pixel_format;
00416 }
00417
00418
00419
00420 bool vimt3d_vil3d_v3m_image::get_property(char const *key, void * value) const
00421 {
00422 if (vcl_strcmp(vil3d_property_voxel_size, key)==0)
00423 {
00424 vgl_vector_3d<double> p111 = header_.w2i.inverse()(1.0, 1.0, 1.0) - header_.w2i.inverse().origin();
00425
00426
00427 float* array = static_cast<float*>(value);
00428 array[0] = (float) p111.x();
00429 array[1] = (float) p111.y();
00430 array[2] = (float) p111.z();
00431 return true;
00432 }
00433
00434 if (vcl_strcmp(vil3d_property_origin_offset, key)==0)
00435 {
00436 vgl_point_3d<double> origin = header_.w2i.origin();
00437 float* array = static_cast<float*>(value);
00438 array[0] = (float)(origin.x());
00439 array[1] = (float)(origin.y());
00440 array[2] = (float)(origin.z());
00441 return true;
00442 }
00443
00444 return false;
00445 }
00446
00447
00448
00449
00450 bool vimt3d_vil3d_v3m_image::set_voxel_size(float si, float sj, float sk)
00451 {
00452 const vimt3d_transform_3d &tr = im_->world2im();
00453
00454
00455 vgl_vector_3d<double> w111 = header_.w2i(1.0, 1.0, 1.0) - header_.w2i.origin();
00456
00457 vimt3d_transform_3d zoom;
00458 zoom.set_zoom_only (w111.x()/si, w111.y()/sj, w111.z()/sk, 0.0, 0.0, 0.0);
00459
00460 header_.w2i = header_.w2i * zoom;
00461 if (im_)
00462 im_->set_world2im(tr*zoom);
00463 dirty_ = true;
00464
00465 return true;
00466 }
00467
00468 const vimt3d_transform_3d & vimt3d_vil3d_v3m_image::world2im() const
00469 {
00470 return header_.w2i;
00471 }
00472
00473 void vimt3d_vil3d_v3m_image::set_world2im(const vimt3d_transform_3d & tr)
00474 {
00475 header_.w2i=tr;
00476 if (im_)
00477 im_->set_world2im(header_.w2i);
00478 dirty_ = true;
00479 }
00480
00481
00482
00483
00484
00485 vil3d_image_view_base_sptr vimt3d_vil3d_v3m_image::get_copy_view(unsigned i0, unsigned ni,
00486 unsigned j0, unsigned nj,
00487 unsigned k0, unsigned nk) const
00488 {
00489 if (!im_)
00490 load_full_image();
00491 if (!im_) return 0;
00492
00493 const vil3d_image_view_base &view = im_->image_base();
00494
00495 if (i0 + ni > view.ni() || j0 + nj > view.nj() ||
00496 k0 + nk > view.nk()) return 0;
00497
00498 switch (view.pixel_format())
00499 {
00500 #define macro( F , T ) \
00501 case F : { \
00502 const vil3d_image_view< T > &v = \
00503 static_cast<const vil3d_image_view< T > &>(view); \
00504 vil3d_image_view< T > w(v.memory_chunk(), &v(i0,j0,k0), \
00505 ni, nj, nk, v.nplanes(), \
00506 v.istep(), v.jstep(), v.kstep(), v.planestep()); \
00507 return new vil3d_image_view< T >(vil3d_copy_deep(w)); }
00508 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00509
00510
00511
00512 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00513 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00514
00515 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00516 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00517 #undef macro
00518 default:
00519 vil_exception_warning(vil_exception_unsupported_pixel_format(
00520 view.pixel_format(), "vimt3d_vil3d_v3m_image::get_copy_view"));
00521 return 0;
00522 }
00523 }
00524
00525
00526
00527 vil3d_image_view_base_sptr vimt3d_vil3d_v3m_image::get_view(unsigned i0, unsigned ni,
00528 unsigned j0, unsigned nj,
00529 unsigned k0, unsigned nk) const
00530 {
00531 if (!im_)
00532 load_full_image();
00533 if (!im_) return 0;
00534
00535 const vil3d_image_view_base &view = im_->image_base();
00536
00537 if (i0 + ni > view.ni() || j0 + nj > view.nj() ||
00538 k0 + nk > view.nk()) return 0;
00539
00540 switch (view.pixel_format())
00541 {
00542 #define macro( F , T ) \
00543 case F : { \
00544 const vil3d_image_view< T > &v = \
00545 static_cast<const vil3d_image_view< T > &>(view); \
00546 return new vil3d_image_view< T >(v.memory_chunk(), (!v)?0:&v(i0,j0,k0), \
00547 ni, nj, nk, v.nplanes(), \
00548 v.istep(), v.jstep(), v.kstep(), \
00549 v.planestep()); }
00550 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00551
00552
00553
00554
00555 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00556
00557 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00558 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00559 #undef macro
00560 case VIL_PIXEL_FORMAT_INT_32 : {
00561 const vil3d_image_view< vxl_int_32 > &v =
00562 static_cast<const vil3d_image_view< vxl_int_32 > &>(view);
00563 return new vil3d_image_view< vxl_int_32 >(v.memory_chunk(), v.size()?&v(i0,j0,k0):0,
00564 ni, nj, nk, v.nplanes(),
00565 v.istep(), v.jstep(), v.kstep(),
00566 v.planestep()); }
00567 default:
00568 vil_exception_warning(vil_exception_unsupported_pixel_format(
00569 view.pixel_format(), "vimt3d_vil3d_v3m_image::get_view"));
00570 return 0;
00571 }
00572 }
00573
00574
00575
00576 bool vimt3d_vil3d_v3m_image::put_view(const vil3d_image_view_base& vv,
00577 unsigned i0, unsigned j0, unsigned k0)
00578 {
00579 if (!im_)
00580 load_full_image();
00581 if (!im_) return false;
00582
00583 if (!view_fits(vv, i0, j0, k0))
00584 {
00585 vil_exception_warning(vil_exception_out_of_bounds("vimt3d_vil3d_v3m_image::put_view"));
00586 return false;
00587 }
00588
00589 if (vv.pixel_format() != im_->image_base().pixel_format())
00590 {
00591 vil_exception_warning(vil_exception_pixel_formats_incompatible(
00592 vv.pixel_format(), im_->image_base().pixel_format(), "vimt3d_vil3d_v3m_image::put_view"));
00593 return false;
00594 }
00595
00596 dirty_ = true;
00597
00598 switch (vv.pixel_format())
00599 {
00600 #define macro( F , T ) \
00601 case F : \
00602 vil3d_copy_to_window(static_cast<vil3d_image_view<T >const&>(vv), \
00603 static_cast<vimt3d_image_3d_of<T >&>(*im_).image(), \
00604 i0, j0, k0); \
00605 return true;
00606
00607 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00608
00609
00610
00611 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00612 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00613
00614 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00615 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00616 #undef macro
00617 default:
00618 vil_exception_warning(vil_exception_unsupported_pixel_format(
00619 vv.pixel_format(), "vimt3d_vil3d_v3m_image::put_view"));
00620 return false;
00621 }
00622 }