00001
00002
00003
00004
00005 #include "vil_nitf2_image.h"
00006
00007
00008
00009
00010 #include <vcl_cassert.h>
00011 #include <vcl_cstring.h>
00012 #include <vcl_algorithm.h>
00013 #include <vcl_cstdlib.h>
00014 #include <vil/vil_stream_fstream.h>
00015 #include <vil/vil_image_view.h>
00016 #include <vil/vil_property.h>
00017 #include <vil/vil_config.h>
00018 #include "vil_nitf2_data_mask_table.h"
00019 #include "vil_nitf2_des.h"
00020
00021 #if HAS_J2K
00022 #include "vil_j2k_image.h"
00023 #endif //HAS_J2K
00024
00025 int debug_level = 0;
00026
00027
00028
00029
00030 static char const nitf2_string[] = "nitf";
00031
00032 char const* vil_nitf2_file_format::tag() const
00033 {
00034 return nitf2_string;
00035 }
00036
00037 vil_image_resource_sptr vil_nitf2_file_format::make_input_image(vil_stream *vs)
00038 {
00039 vil_nitf2_image* im = new vil_nitf2_image( vs );
00040 if ( !im->parse_headers() ) {
00041 delete im;
00042 im = 0;
00043 }
00044 return im;
00045 }
00046
00047 vil_image_resource_sptr
00048 vil_nitf2_file_format::make_output_image(vil_stream* ,
00049 unsigned ,
00050 unsigned ,
00051 unsigned ,
00052 enum vil_pixel_format )
00053 {
00054
00055 return 0;
00056 }
00057
00058
00059
00060
00061 vil_streampos vil_nitf2_image::get_offset_to( vil_nitf2_header::section_type sec,
00062 vil_nitf2_header::portion_type por,
00063 unsigned int index ) const
00064 {
00065 vil_streampos p;
00066 if ( sec == vil_nitf2_header::enum_file_header ) {
00067
00068
00069 assert( por == vil_nitf2_header::enum_subheader );
00070 assert( index == 0 );
00071
00072 p = 0;
00073 } else {
00074 vil_nitf2_header::section_type preceding_section = (vil_nitf2_header::section_type)(sec-1);
00075 p = get_offset_to( preceding_section, vil_nitf2_header::enum_subheader, 0 ) +
00076 size_to( preceding_section, vil_nitf2_header::enum_subheader, -1 ) +
00077 size_to( sec, por, index );
00078 }
00079 return p;
00080 }
00081
00082 vil_streampos vil_nitf2_image::size_to(vil_nitf2_header::section_type sec,
00083 vil_nitf2_header::portion_type por,
00084 int index ) const
00085 {
00086 if ( sec == vil_nitf2_header::enum_file_header ) {
00087 if ( index == -1 ) {
00088 int file_header_size;
00089 m_file_header.get_property("HL", file_header_size);
00090 return (vil_streampos)file_header_size;
00091 } else {
00092 return 0;
00093 }
00094 }
00095
00096 vil_streampos offset = 0;
00097
00098
00099 bool going_past_end = false;
00100 if ( index == -1 ) {
00101 int num_segments;
00102 m_file_header.get_property(vil_nitf2_header::section_num_tag(sec), num_segments);
00103 index = num_segments;
00104 going_past_end = true;
00105 }
00106 vcl_string sh = vil_nitf2_header::section_len_header_tag( sec );
00107 vcl_string s = vil_nitf2_header::section_len_data_tag( sec );
00108 int i;
00109 for (i = 0 ; i < index ; i++) {
00110 int current_header_size;
00111 m_file_header.get_property(sh, i, current_header_size);
00112 offset += current_header_size;
00113 if ( sec == vil_nitf2_header::enum_image_segments ){
00114 vil_nitf2_long current_data_size;
00115 m_file_header.get_property(s, i, current_data_size);
00116 offset += current_data_size;
00117 } else {
00118 int current_data_size;
00119 m_file_header.get_property(s, i, current_data_size);
00120 offset += current_data_size;
00121 }
00122 }
00123
00124
00125 if ( por == vil_nitf2_header::enum_data ) {
00126
00127
00128 if ( going_past_end ) { assert(!"skipped past all segments"); return 0L; }
00129 int current_header_size;
00130 m_file_header.get_property(sh, i, current_header_size);
00131 offset += current_header_size;
00132 }
00133 return offset;
00134 }
00135
00136 vil_image_view_base_sptr ( *vil_nitf2_image::s_decode_jpeg_2000 )
00137 ( vil_stream* vs, unsigned i0, unsigned ni, unsigned j0, unsigned nj, double i_factor, double j_factor ) = 0;
00138
00139 vil_nitf2_image::vil_nitf2_image(vil_stream* is)
00140 : m_stream(is),
00141 m_current_image_index(0)
00142 {
00143 m_stream->ref();
00144 }
00145
00146 vil_nitf2_image::vil_nitf2_image(const vcl_string& filePath, const char* mode)
00147 : m_current_image_index(0)
00148 {
00149 #ifdef VIL_USE_FSTREAM64
00150 m_stream = new vil_stream_fstream64(filePath.c_str(), mode);
00151 #else //VIL_USE_FSTREAM64
00152 m_stream = new vil_stream_fstream(filePath.c_str(), mode);
00153 #endif //VIL_USE_FSTREAM64
00154 m_stream->ref();
00155 }
00156
00157 void vil_nitf2_image::clear_image_headers()
00158 {
00159 for (unsigned int i = 0 ; i < m_image_headers.size() ; i++) {
00160 delete m_image_headers[i];
00161 }
00162 m_image_headers.clear();
00163 }
00164
00165 void vil_nitf2_image::clear_des()
00166 {
00167 for (unsigned int i = 0 ; i < m_des.size() ; i++) {
00168 delete m_des[i];
00169 }
00170 m_des.clear();
00171 }
00172
00173
00174 vil_nitf2_image::~vil_nitf2_image()
00175 {
00176 m_stream->unref();
00177 clear_image_headers();
00178 clear_des();
00179 }
00180
00181 unsigned int vil_nitf2_image::current_image() const
00182 {
00183 return m_current_image_index;
00184 }
00185
00186 void vil_nitf2_image::set_current_image(unsigned int index)
00187 {
00188 assert(index < m_image_headers.size());
00189 m_current_image_index = index;
00190 }
00191
00192 unsigned int vil_nitf2_image::nimages() const
00193 {
00194 int num_images;
00195 if (m_file_header.get_property("NUMI", num_images)) return num_images;
00196 else return 0;
00197 }
00198
00199 vil_streampos vil_nitf2_image::get_offset_to_image_data_block_band(
00200 unsigned int image_index, unsigned int block_index_x,unsigned int block_index_y, int bandIndex) const
00201 {
00202
00203 vcl_string i_mode;
00204 current_image_header()->get_property("IMODE", i_mode);
00205
00206
00207
00208 vil_streampos offset =
00209 get_offset_to( vil_nitf2_header::enum_image_segments, vil_nitf2_header::enum_data, image_index );
00210
00211
00212
00213
00214 int bits_per_pixel_per_band;
00215 current_image_header()->get_property("NBPP", bits_per_pixel_per_band);
00216
00217 #if 0 //Not valid if blocks are partially filled (JLM 11/03/07)
00218 unsigned int bytes_per_band = ni() * nj() * bits_per_pixel_per_band / 8;
00219 #endif
00220
00221 unsigned int nbi = n_block_i(), nbj = n_block_j();
00222 unsigned int sbi = size_block_i(), sbj = size_block_j();
00223 unsigned int bytes_per_band = nbi*nbj*sbi*sbj*bits_per_pixel_per_band/8;
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 const vil_nitf2_data_mask_table* data_mask_table = current_image_header()->data_mask_table();
00237 if (data_mask_table) {
00238 offset += data_mask_table->blocked_image_data_offset();
00239 }
00240 if (data_mask_table && data_mask_table->has_offset_table()) {
00241
00242 int bI = i_mode == "S" ? bandIndex : -1;
00243 if (data_mask_table->block_band_present(block_index_x, block_index_y, bI))
00244 {
00245 return 0;
00246 }
00247 offset += data_mask_table->block_band_offset(block_index_x, block_index_y, bI);
00248 } else {
00249 unsigned int pixels_per_block = size_block_i() * size_block_j();
00250 unsigned int bits_per_band = pixels_per_block * bits_per_pixel_per_band;
00251 unsigned int bytes_per_block_per_band = bits_per_band / 8;
00252
00253
00254 if (bits_per_band % 8 != 0) bytes_per_block_per_band++;
00255 if (i_mode == "S") {
00256
00257 unsigned int offset_to_desired_band = bandIndex * bytes_per_band;
00258 unsigned int offset_to_desired_block = bytes_per_block_per_band * (block_index_y * n_block_i() + block_index_x);
00259 offset += offset_to_desired_band + offset_to_desired_block;
00260 } else {
00261
00262 unsigned int block_size_bytes = bytes_per_block_per_band * nplanes();
00263 unsigned int offset_to_desired_block = block_size_bytes * (block_index_y * n_block_i() + block_index_x);
00264 offset += offset_to_desired_block;
00265 }
00266 }
00267 if (i_mode != "S") {
00268
00269
00270
00271 unsigned int offset_to_desired_band = bandIndex * bytes_per_band;
00272 offset += offset_to_desired_band;
00273 }
00274 return offset;
00275 }
00276
00277 bool vil_nitf2_image::parse_headers()
00278 {
00279 if (!m_stream->ok()) return false;
00280
00281 m_stream->seek(0);
00282 if (!m_file_header.read(m_stream)) {
00283 return false;
00284 }
00285
00286 clear_image_headers();
00287 m_image_headers.resize(nimages());
00288 for (unsigned int i = 0 ; i < nimages() ; i++) {
00289 vil_streampos offset = get_offset_to( vil_nitf2_header::enum_image_segments, vil_nitf2_header::enum_subheader, i);
00290 m_stream->seek(offset);
00291 m_image_headers[i] = new vil_nitf2_image_subheader(file_version());
00292 if (!m_image_headers[i]->read(m_stream)) return false;
00293 }
00294
00295
00296 clear_des();
00297 int num_des;
00298 m_file_header.get_property( "NUMDES", num_des );
00299 m_des.resize( num_des );
00300 for ( int j = 0 ; j < num_des ; j++ ){
00301 vil_streampos offset = get_offset_to( vil_nitf2_header::enum_data_extension_segments, vil_nitf2_header::enum_subheader, j);
00302 m_stream->seek(offset);
00303 int data_width;
00304 m_file_header.get_property( "LD", j, data_width );
00305 m_des[j] = new vil_nitf2_des(file_version(), data_width);
00306 if (!m_des[j]->read(m_stream)) return false;
00307 }
00308 return true;
00309 }
00310
00311 vil_nitf2_classification::file_version vil_nitf2_image::file_version() const
00312 {
00313 return m_file_header.file_version();
00314 }
00315
00316 char const * vil_nitf2_image::file_format() const
00317 {
00318 vil_nitf2_classification::file_version v = file_version();
00319 switch (v)
00320 {
00321 case vil_nitf2_classification::V_UNKNOWN :
00322 return "unknown";
00323 case vil_nitf2_classification::V_NITF_10 :
00324 return "nitf10";
00325 case vil_nitf2_classification::V_NITF_20 :
00326 return "nitf20";
00327 case vil_nitf2_classification::V_NITF_21 :
00328 return "nitf21";
00329 default:
00330 return "unknown";
00331 }
00332 }
00333
00334 const vil_nitf2_image_subheader* vil_nitf2_image::current_image_header() const
00335 {
00336 assert(m_current_image_index < m_image_headers.size());
00337 return m_image_headers[ m_current_image_index ];
00338 }
00339
00340 unsigned vil_nitf2_image::nplanes() const
00341 {
00342 return current_image_header()->nplanes();
00343 }
00344
00345 unsigned vil_nitf2_image::ni() const
00346 {
00347
00348
00349
00350
00351 int num_significant_cols;
00352 if (current_image_header()->get_property("NCOLS", num_significant_cols))
00353 {
00354 return num_significant_cols;
00355 }
00356 return 0;
00357 }
00358
00359 unsigned vil_nitf2_image::nj() const
00360 {
00361
00362
00363
00364
00365 int num_significant_rows;
00366 if (current_image_header()->get_property("NROWS", num_significant_rows))
00367 {
00368 return num_significant_rows;
00369 }
00370 return 0;
00371 }
00372
00373 enum vil_pixel_format vil_nitf2_image::pixel_format () const
00374 {
00375 vcl_string pixel_type;
00376 int bits_per_pixel;
00377 if (current_image_header()->get_property("PVTYPE", pixel_type) &&
00378 current_image_header()->get_property("NBPP", bits_per_pixel))
00379 {
00380
00381 int bytesPerPixel = bits_per_pixel / 8;
00382 if (bits_per_pixel % 8 != 0) bytesPerPixel++;
00383 bits_per_pixel = bytesPerPixel * 8;
00384 if (pixel_type == "INT") {
00385 if (bits_per_pixel == 8) {
00386 return VIL_PIXEL_FORMAT_BYTE;
00387 } else if (bits_per_pixel == 16) {
00388 return VIL_PIXEL_FORMAT_UINT_16;
00389 } else if (bits_per_pixel == 32) {
00390 return VIL_PIXEL_FORMAT_UINT_32;
00391 }
00392 #if VXL_HAS_INT_64
00393 else if (bits_per_pixel == 64) {
00394 return VIL_PIXEL_FORMAT_UINT_64;
00395 }
00396 #endif //VXL_HAS_INT_64
00397 } else if (pixel_type == "B") {
00398 return VIL_PIXEL_FORMAT_BOOL;
00399 } else if (pixel_type == "SI") {
00400 if (bits_per_pixel == 8) {
00401 return VIL_PIXEL_FORMAT_SBYTE;
00402 } else if (bits_per_pixel == 16) {
00403 return VIL_PIXEL_FORMAT_INT_16;
00404 } else if (bits_per_pixel == 32) {
00405 return VIL_PIXEL_FORMAT_INT_32;
00406 }
00407 #if VXL_HAS_INT_64
00408 else if (bits_per_pixel == 64) {
00409 return VIL_PIXEL_FORMAT_INT_64;
00410 }
00411 #endif //VXL_HAS_INT_64
00412 } else if (pixel_type == "R") {
00413 if (bits_per_pixel == 32) {
00414 return VIL_PIXEL_FORMAT_FLOAT;
00415 } else if (bits_per_pixel == 64) {
00416 return VIL_PIXEL_FORMAT_DOUBLE;
00417 }
00418 } else if (pixel_type == "C") {
00419
00420 if (bits_per_pixel == 64) {
00421 return VIL_PIXEL_FORMAT_COMPLEX_FLOAT;
00422 }
00423
00424
00425 }
00426 }
00427 return VIL_PIXEL_FORMAT_UNKNOWN;
00428 }
00429
00430 unsigned int vil_nitf2_image::size_block_i() const
00431 {
00432 return current_image_header()->get_pixels_per_block_x();
00433 }
00434
00435 unsigned int vil_nitf2_image::size_block_j() const
00436 {
00437 return current_image_header()->get_pixels_per_block_y();
00438 }
00439
00440 unsigned int vil_nitf2_image::n_block_i() const
00441 {
00442 return current_image_header()->get_num_blocks_x();
00443 }
00444
00445 unsigned int vil_nitf2_image::n_block_j() const
00446 {
00447 return current_image_header()->get_num_blocks_y();
00448 }
00449
00450 void compute_block_and_offset(unsigned j0, unsigned long block_size,
00451 unsigned int& block, unsigned int& offset)
00452 {
00453 block = 0;
00454 offset = 0;
00455
00456 if (j0 != 0) {
00457 block = (j0 / block_size);
00458 if (j0 > 0 && j0 % block_size != 0) {
00459 offset = j0 - (block * block_size);
00460 }
00461 }
00462 }
00463
00464 bool vil_nitf2_image::is_jpeg_2000_compressed() const
00465 {
00466 vcl_string compression_type;
00467
00468
00469
00470 return ( current_image_header()->get_property("IC", compression_type) ) &&
00471 ( compression_type == "C8" || compression_type == "M8" );
00472 }
00473
00474 vil_image_view_base_sptr vil_nitf2_image::get_copy_view_decimated_j2k(
00475 unsigned start_i, unsigned num_i, unsigned start_j, unsigned num_j, double i_factor, double j_factor ) const
00476 {
00477
00478 if ((start_i + num_i > ni()) || (start_j + num_j > nj())) {
00479 return 0;
00480 }
00481 assert( is_jpeg_2000_compressed() );
00482 if ( ! s_decode_jpeg_2000 ) {
00483 #if HAS_J2K
00484 s_decode_jpeg_2000 = vil_j2k_image::s_decode_jpeg_2000;
00485 #else //HAS_J2K
00486 return 0;
00487 #endif //HAS_J2K
00488 }
00489
00490
00491
00492
00493 m_stream->seek(get_offset_to( vil_nitf2_header::enum_image_segments, vil_nitf2_header::enum_data, m_current_image_index));
00494 return s_decode_jpeg_2000( m_stream, start_i, num_i, start_j, num_j, i_factor, j_factor );
00495 }
00496
00497 vil_image_view_base_sptr vil_nitf2_image::get_copy_view(unsigned start_i, unsigned num_i,
00498 unsigned start_j, unsigned num_j) const
00499 {
00500
00501 if ((start_i + num_i > ni()) || (start_j + num_j > nj())) {
00502 return 0;
00503 }
00504
00505 vcl_string compression_type;
00506 if (!current_image_header()->get_property("IC", compression_type)) return 0;
00507
00508
00509 if (compression_type == "NC" || compression_type == "NM") {
00510 return get_copy_view_uncompressed(start_i, num_i, start_j, num_j);
00511 } else if ( is_jpeg_2000_compressed() ) {
00512 return get_copy_view_decimated_j2k( start_i, num_i, start_j, num_j, 1.0, 1.0 );
00513 } else {
00514 return 0;
00515 }
00516 }
00517
00518 vil_image_view_base_sptr vil_nitf2_image::get_copy_view_uncompressed(unsigned start_i, unsigned num_i,
00519 unsigned start_j, unsigned num_j) const
00520 {
00521 return vil_blocked_image_resource::get_copy_view(start_i, num_i, start_j, num_j);
00522 }
00523
00524 template< class T >
00525 vil_memory_chunk_sptr maybe_byte_align_data(vil_memory_chunk_sptr in_data, unsigned int num_samples,
00526 unsigned int in_bits_per_sample, T )
00527 {
00528 if (in_bits_per_sample != sizeof(T)*8) {
00529 vil_memory_chunk_sptr new_memory = new vil_memory_chunk(num_samples*sizeof(T), in_data->pixel_format());
00530 byte_align_data((T*)in_data->data(), num_samples, in_bits_per_sample, (T*)new_memory->data());
00531 return new_memory;
00532 }
00533 return in_data;
00534 }
00535
00536
00537 template<> vil_memory_chunk_sptr maybe_byte_align_data<float> (
00538 vil_memory_chunk_sptr in_data, unsigned int , unsigned int , float )
00539 { return in_data; }
00540
00541 template<> vil_memory_chunk_sptr maybe_byte_align_data<double> (
00542 vil_memory_chunk_sptr in_data, unsigned int , unsigned int , double )
00543 { return in_data; }
00544
00545 template<> vil_memory_chunk_sptr maybe_byte_align_data< vcl_complex< float > > (
00546 vil_memory_chunk_sptr in_data, unsigned int , unsigned int , vcl_complex<float> )
00547 { return in_data; }
00548
00549
00550
00551
00552
00553
00554
00555
00556 template< class T >
00557 void right_justify(T* data, unsigned int num_samples, unsigned int bitsToMove)
00558 {
00559 for (unsigned int i = 0 ; i < num_samples ; i++) {
00560 data[i] = data[i] >> bitsToMove;
00561 }
00562 }
00563
00564
00565 template<> void right_justify<bool>(bool* , unsigned int , unsigned int ) {}
00566 template<> void right_justify<float>(float* , unsigned int , unsigned int ) {}
00567 template<> void right_justify<double>(double* , unsigned int , unsigned int ) {}
00568 template<> void right_justify< vcl_complex< float > >(vcl_complex< float >* , unsigned int ,
00569 unsigned int ) {}
00570
00571 template< class T >
00572 unsigned int get_index(T in_val)
00573 { return (T)in_val; }
00574
00575 template<> unsigned int get_index<bool>(bool in_val)
00576 { return in_val ? 1 : 0; }
00577
00578 template< class T >
00579 vil_image_view_base_sptr get_block_vcl_internal(vil_pixel_format pix_format, vil_memory_chunk_sptr image_memory,
00580 unsigned int pixels_per_block_x, unsigned int pixels_per_block_y,
00581 unsigned int nplanes,
00582 unsigned int i_step, unsigned int j_step, unsigned int plane_step,
00583 bool need_to_right_justify,
00584 unsigned int extra_bits, unsigned int bits_per_pixel_per_band,
00585 bool data_is_all_blank, const vil_nitf2_image_subheader* , T dummy)
00586 {
00587
00588 unsigned int num_samples = pixels_per_block_x * pixels_per_block_y * nplanes;
00589
00590 if (data_is_all_blank) {
00591
00592 T* data_ptr = reinterpret_cast<T*>(image_memory->data());
00593 for (unsigned int i = 0 ;
00594 i < pixels_per_block_x * pixels_per_block_y * nplanes ;
00595 i++)
00596 {
00597 data_ptr[i] = (T)0;
00598 }
00599 } else {
00600
00601
00602 if (need_to_right_justify)
00603 right_justify<T>(static_cast<T*>(image_memory->data()), image_memory->size()/sizeof(T), extra_bits);
00604
00605 vil_nitf2_data_mask_table::maybe_endian_swap(static_cast< char* >(image_memory->data()), image_memory->size(), pix_format);
00606
00607
00608 image_memory = maybe_byte_align_data(image_memory, num_samples, bits_per_pixel_per_band, dummy);
00609 }
00610
00611 vil_image_view< T >* result =
00612 new vil_image_view< T > (image_memory, reinterpret_cast<T*>(image_memory->data()),
00613 pixels_per_block_x, pixels_per_block_y, nplanes, i_step, j_step, plane_step);
00614
00615 return result;
00616 }
00617
00618 vil_image_view_base_sptr vil_nitf2_image::get_block_j2k( unsigned int blockIndexX, unsigned int blockIndexY ) const
00619 {
00620 if ( ! is_jpeg_2000_compressed() ) return 0;
00621 if ( blockIndexX >= n_block_i() ) return 0;
00622 if ( blockIndexY >= n_block_j() ) return 0;
00623
00624
00625
00626
00627
00628 unsigned int i0 = vcl_min( blockIndexX * size_block_i(), ni() );
00629 unsigned int num_i = vcl_min( size_block_i(), ni() - i0 );
00630 unsigned int j0 = vcl_min( blockIndexY * size_block_j(), nj() );
00631 unsigned int num_j = vcl_min( size_block_j(), nj() - j0 );
00632 return get_copy_view( i0, num_i, j0, num_j );
00633 }
00634
00635 vil_image_view_base_sptr vil_nitf2_image::get_block(unsigned int block_index_x, unsigned int block_index_y) const
00636 {
00637 if (pixel_format() == VIL_PIXEL_FORMAT_UNKNOWN) return 0;
00638
00639 if ( is_jpeg_2000_compressed() ) {
00640 return get_block_j2k( block_index_x, block_index_y );
00641 }
00642
00643 vcl_string image_mode_type;
00644 if (!current_image_header()->get_property("IMODE", image_mode_type)) return 0;
00645
00646
00647 int bits_per_pixel_per_band, actualBitsPerPixelPerBand;
00648 vcl_string bitJustification;
00649 if (!current_image_header()->get_property("NBPP", bits_per_pixel_per_band) ||
00650 !current_image_header()->get_property("ABPP", actualBitsPerPixelPerBand) ||
00651 !current_image_header()->get_property("PJUST", bitJustification)) {
00652 return 0;
00653 }
00654 int extra_bits = bits_per_pixel_per_band - actualBitsPerPixelPerBand;
00655 bool need_to_right_justify = bitJustification == "L" && (extra_bits > 0);
00656
00657
00658
00659
00660
00661 unsigned int pixels_per_block = size_block_i() * size_block_j();
00662 unsigned int bits_per_band = pixels_per_block * bits_per_pixel_per_band;
00663 unsigned int bytes_per_block_per_band = bits_per_band / 8;
00664 if (bits_per_band % 8 != 0) bytes_per_block_per_band++;
00665 unsigned int block_size_bytes = bytes_per_block_per_band * nplanes();
00666
00667 vil_memory_chunk_sptr image_memory = new vil_memory_chunk(block_size_bytes, pixel_format());
00668
00669
00670 unsigned int i_step(0), j_step(0), plane_step(0);
00671 bool data_is_all_blank = false;
00672 if (image_mode_type == "S") {
00673 #if 0 // NOT USED
00674 unsigned int bytes_per_band = ni() * nj() * bits_per_pixel_per_band / 8;
00675 unsigned int offset_to_desired_block = bytes_per_block_per_band * (block_index_y * n_block_i() + block_index_x);
00676 #endif // 0
00677
00678 for (unsigned int i = 0 ; i < nplanes() ; i++) {
00679 vil_streampos current_offset = get_offset_to_image_data_block_band(m_current_image_index, block_index_x, block_index_y, i);
00680 if (current_offset == 0) {
00681
00682 data_is_all_blank = true;
00683 } else {
00684 m_stream->seek(current_offset);
00685 char* position_to_read_to = static_cast<char*>(image_memory->data());
00686 position_to_read_to += i*bytes_per_block_per_band;
00687 if (m_stream->read((void*)position_to_read_to, bytes_per_block_per_band) != static_cast<int>(bytes_per_block_per_band)) {
00688 return 0;
00689 }
00690 }
00691 }
00692 i_step = 1;
00693 j_step = size_block_i();
00694 plane_step = size_block_i() * size_block_j();
00695 } else {
00696
00697 vil_streampos current_offset = get_offset_to_image_data_block_band(m_current_image_index, block_index_x, block_index_y, 0);
00698 if (current_offset == 0) {
00699
00700 data_is_all_blank = true;
00701 } else {
00702
00703 m_stream->seek(current_offset);
00704
00705 if (m_stream->read(image_memory->data(), block_size_bytes) != static_cast<int>(block_size_bytes)) {
00706 return 0;
00707 }
00708 }
00709
00710
00711 if (image_mode_type == "B") {
00712
00713 i_step = 1;
00714 j_step = size_block_i();
00715 plane_step = size_block_i() * size_block_j();
00716 } else if (image_mode_type == "P") {
00717
00718 i_step = nplanes();
00719 j_step = nplanes() * size_block_i();
00720 plane_step = 1;
00721 } else if (image_mode_type == "R") {
00722
00723 i_step = 1;
00724 j_step = nplanes() * size_block_i();
00725 plane_step = size_block_i();
00726 }
00727 }
00728
00729
00730 vil_image_view_base_sptr view = 0;
00731 switch (vil_pixel_format_component_format(image_memory->pixel_format()))
00732 {
00733 #define GET_BLOCK_CASE(FORMAT, T)\
00734 case FORMAT:{ \
00735 T t= (T)0; \
00736 return get_block_vcl_internal(\
00737 FORMAT, image_memory, size_block_i(),size_block_j(), nplanes(),\
00738 i_step, j_step, plane_step, need_to_right_justify, extra_bits, bits_per_pixel_per_band,\
00739 data_is_all_blank, current_image_header(), t);\
00740 } break
00741
00742 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00743 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00744
00745 #if VXL_HAS_INT_64
00746 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00747 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00748 #endif
00749 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00750 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00751 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00752 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00753 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00754 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00755 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00756 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_COMPLEX_FLOAT, vcl_complex<float>);
00757 #undef GET_BLOCK_CASE
00758
00759 default:
00760 assert(!"Unknown vil data type.");
00761 break;
00762 }
00763 return view;
00764 }
00765
00766 template<> bool* byte_align_data<bool>(bool* in_data, unsigned int num_samples, unsigned int in_bits_per_sample, bool* out_data)
00767 {
00768 switch (sizeof(bool))
00769 {
00770 case 1:
00771 byte_align_data((vxl_byte*)in_data, num_samples, in_bits_per_sample, (vxl_byte*)out_data);
00772 break;
00773 case 2:
00774 byte_align_data((vxl_uint_16*)in_data, num_samples, in_bits_per_sample, (vxl_uint_16*)out_data);
00775 break;
00776 case 4:
00777 byte_align_data((vxl_uint_32*)in_data, num_samples, in_bits_per_sample, (vxl_uint_32*)out_data);
00778 break;
00779 #if VXL_HAS_INT_64
00780 case 8:
00781 byte_align_data((vxl_uint_64*)in_data, num_samples, in_bits_per_sample, (vxl_uint_64*)out_data);
00782 break;
00783 #endif //VXL_HAS_INT_64
00784 default:
00785 assert(!"Unsupported size of bool.");
00786 }
00787
00788 #if 0
00789
00790 vcl_cout << "\nBools: ";
00791 for (unsigned int i = 0 ; i < num_samples ; i++) {
00792 vcl_cout << (out_data[i] ? '1' : '0');
00793 }
00794 vcl_cout << vcl_endl;
00795 #endif //0
00796 return out_data;
00797 }
00798
00799 bool vil_nitf2_image::get_property (char const *tag, void *property_value) const
00800 {
00801 if (vcl_strcmp(vil_property_size_block_i, tag)==0)
00802 {
00803 if (property_value)
00804 *static_cast<unsigned*>(property_value) = this->size_block_i();
00805 return true;
00806 }
00807
00808 if (vcl_strcmp(vil_property_size_block_j, tag)==0)
00809 {
00810 if (property_value)
00811 *static_cast<unsigned*>(property_value) = this->size_block_j();
00812 return true;
00813 }
00814 vcl_string result;
00815 if (m_file_header.get_property(tag, result) ||
00816 (current_image_header() && current_image_header()->get_property(tag, result)))
00817 {
00818 property_value = vcl_malloc(result.size());
00819 vcl_memcpy(property_value, result.c_str(), result.size());
00820 return true;
00821 }
00822 return false;
00823 }
00824
00825 vil_nitf2_field::field_tree* vil_nitf2_image::get_tree( ) const
00826 {
00827 vil_nitf2_field::field_tree* t = new vil_nitf2_field::field_tree;
00828 t->columns.push_back( "NITF File" );
00829 t->children.push_back( get_header().get_tree() );
00830 unsigned int i;
00831 for ( i = 0 ; i < m_image_headers.size() ; i++ ){
00832 t->children.push_back( m_image_headers[i]->get_tree(i+1) );
00833 }
00834 for ( i = 0 ; i < m_des.size() ; i++ ){
00835 t->children.push_back( m_des[i]->get_tree(i+1) );
00836 }
00837 return t;
00838 }
00839