core/vil/file_formats/vil_nitf2_data_mask_table.cxx
Go to the documentation of this file.
00001 // vil_nitf2: Written by Rob Radtke (rob@) and Harry Voorhees (hlv@) of
00002 // Stellar Science Ltd. Co. (stellarscience.com) for
00003 // Air Force Research Laboratory, 2005.
00004 
00005 #include "vil_nitf2_data_mask_table.h"
00006 
00007 #include <vil/vil_stream.h>
00008 #include <vcl_string.h>
00009 #include <vcl_cassert.h>
00010 #include <vcl_cstdlib.h>
00011 
00012 vil_nitf2_data_mask_table::vil_nitf2_data_mask_table(
00013   unsigned int num_blocks_x, unsigned int num_blocks_y,
00014   unsigned int num_bands, const vcl_string i_mode )
00015   : num_blocks_x( num_blocks_x ),
00016     num_blocks_y( num_blocks_y ),
00017     num_bands( num_bands ),
00018     i_mode( i_mode )
00019 { }
00020 
00021 bool vil_nitf2_data_mask_table::parse( vil_stream* stream )
00022 {
00023   //get the vcl_fixed width stuff first
00024   if ( stream->read( (void*)(&IMDATOFF),  4 ) != 4 ||
00025       stream->read( (void*)(&BMRLNTH),   2 ) != 2 ||
00026       stream->read( (void*)(&TMRLNTH),   2 ) != 2 ||
00027       stream->read( (void*)(&TPXCDLNTH), 2 ) != 2 )
00028   {
00029     return false;
00030   } else {
00031     maybe_endian_swap( (char*)&IMDATOFF, 4, 4 );
00032     maybe_endian_swap( (char*)&BMRLNTH, 2, 2 );
00033     maybe_endian_swap( (char*)&TMRLNTH, 2, 2 );
00034     maybe_endian_swap( (char*)&TPXCDLNTH, 2, 2 );
00035   }
00036 
00037   //reading in TPXCD is quite an ordeal because
00038   //the width of the field varies based on the value of
00039   //TPXCDLNTH
00040   unsigned short width = TPXCDLNTH / 8;
00041   if ( TPXCDLNTH % 8 != 0 ) width++;
00042   void* val = vcl_malloc( width );
00043 //  if ( stream->read( &val, width ) != width ) return false;
00044   if ( stream->read( val, width ) != width ) return false;
00045   maybe_endian_swap( (char*)val, width, width );
00046   if ( width == 1 ){
00047     TPXCD = *((vxl_byte*)val);
00048   } else if ( width == 2 ){
00049     TPXCD = *((vxl_uint_16*)val);
00050   } else if ( width == 4 ){
00051     TPXCD = *((vxl_uint_32*)val);
00052   }
00053 #if VXL_HAS_INT_64
00054   else if ( width == 8 ){
00055     TPXCD = *((vxl_uint_64*)val);
00056   }
00057 #endif //VXL_HAS_INT64
00058 
00059   //properly size and then read in our vectors
00060   ////do BMR_n_BND_m first
00061   unsigned int i, j, b;
00062   if ( BMRLNTH != 0 ){
00063     BMR_n_BND_m.resize( num_blocks_x );
00064     for ( i = 0 ; i < num_blocks_y ; i++ ){
00065       BMR_n_BND_m[i].resize( num_blocks_y );
00066       for ( j = 0 ; j < num_blocks_x ; j++ ){
00067         BMR_n_BND_m[i][j].resize( i_mode == "S" ? num_bands : 1 );
00068       }
00069     }
00070     for ( i = 0 ; i < num_blocks_x ; i++ ){
00071       for ( j = 0 ; j < num_blocks_y ; j++ ){
00072         for ( b = 0 ; b < BMR_n_BND_m[i][j].size() ; b++ ){
00073           if ( stream->read( (void*)(&BMR_n_BND_m[i][j][b]), 4 ) != 4 ) return false;
00074           maybe_endian_swap( (char*)(&BMR_n_BND_m[i][j][b]), 4, 4 );
00075         }
00076       }
00077     }
00078   }
00079 
00080 
00081   //now do the pad pixel vcl_vector
00082   if ( TMRLNTH != 0 ){
00083     TMR_n_BND_m.resize( num_blocks_x );
00084     for ( i = 0 ; i < num_blocks_y ; i++ ){
00085       TMR_n_BND_m[i].resize( num_blocks_y );
00086       for ( j = 0 ; j < num_blocks_x ; j++ ){
00087         TMR_n_BND_m[i][j].resize( i_mode == "S" ? num_bands : 1 );
00088       }
00089     }
00090     for ( i = 0 ; i < num_blocks_x ; i++ ){
00091       for ( j = 0 ; j < num_blocks_y ; j++ ){
00092         for ( b = 0 ; b < TMR_n_BND_m[i][j].size() ; b++ ){
00093           if ( stream->read( (void*)(&TMR_n_BND_m[i][j][b]), 4 ) != 4 ) return false;
00094           maybe_endian_swap( (char*)(&TMR_n_BND_m[i][j][b]), 4, 4 );
00095         }
00096       }
00097     }
00098   }
00099 
00100   return true;
00101 }
00102 
00103 vxl_uint_32 vil_nitf2_data_mask_table::blocked_image_data_offset() const
00104 {
00105   return IMDATOFF;
00106 }
00107 
00108 vxl_uint_32 vil_nitf2_data_mask_table::block_band_offset( unsigned int block_x,
00109                                                           unsigned int block_y,
00110                                                           int band ) const
00111 {
00112   int band_to_use = i_mode == "S" ? band : 0;
00113   assert( block_x < BMR_n_BND_m.size() &&
00114           block_y < BMR_n_BND_m[block_x].size() &&
00115           band_to_use < static_cast<int>(BMR_n_BND_m[block_x][band_to_use].size()) );
00116   assert( ( band < 0 && i_mode != "S" ) ||
00117           ( band >= 0 && i_mode == "S" ) );
00118   return BMR_n_BND_m[block_x][block_y][band_to_use];
00119 }
00120 
00121 vxl_uint_32 vil_nitf2_data_mask_table::pad_pixel( unsigned int block_x,
00122                                                   unsigned int block_y,
00123                                                   int band ) const
00124 {
00125   int band_to_use = i_mode == "S" ? band : 0;
00126   assert( block_x < TMR_n_BND_m.size() &&
00127           block_y < TMR_n_BND_m[block_x].size() &&
00128           band_to_use < static_cast<int>(TMR_n_BND_m[block_x][band_to_use].size()) );
00129   assert( ( band < 0 && i_mode != "S" ) ||
00130           ( band >= 0 && i_mode == "S" ) );
00131   return TMR_n_BND_m[block_x][block_y][band_to_use];
00132 }
00133 
00134 #if VXL_LITTLE_ENDIAN
00135 
00136 #undef swap16
00137 void swap16(char *a, unsigned n)
00138 {
00139   for (unsigned i = 0; i < n * 2; i += 2)
00140   {
00141     vcl_swap( a[i+0], a[i+1] );
00142   }
00143 }
00144 
00145 #undef swap32
00146 void swap32(char *a, unsigned n)
00147 {
00148   for (unsigned i = 0; i < n * 4; i += 4)
00149   {
00150     vcl_swap( a[i+0], a[i+3] );
00151     vcl_swap( a[i+1], a[i+2] );
00152   }
00153 }
00154 
00155 #undef swap64
00156 void swap64(char *a, unsigned n)
00157 {
00158   for (unsigned i = 0; i < n * 8; i += 8)
00159   {
00160     vcl_swap( a[i+0], a[i+7] );
00161     vcl_swap( a[i+1], a[i+6] );
00162     vcl_swap( a[i+2], a[i+5] );
00163     vcl_swap( a[i+3], a[i+4] );
00164   }
00165 }
00166 
00167 #endif
00168 
00169 void vil_nitf2_data_mask_table::maybe_endian_swap( char* a, unsigned size_of_a_in_bytes,
00170                                                    vil_pixel_format pix_format )
00171 {
00172 #if VXL_LITTLE_ENDIAN
00173   maybe_endian_swap( a, size_of_a_in_bytes, vil_pixel_format_sizeof_components( pix_format ) );
00174 #else
00175   (void)a;
00176   (void)size_of_a_in_bytes;  // silence unused parameter compiler warning
00177   (void)pix_format;
00178 #endif //VXL_LITTLE_ENDIAN
00179 }
00180 
00181 void vil_nitf2_data_mask_table::maybe_endian_swap( char* a, unsigned size_of_a_in_bytes,
00182                                                    unsigned int bytesPerSample )
00183 {
00184 #if VXL_LITTLE_ENDIAN
00185   switch ( bytesPerSample )
00186   {
00187    case 8: swap64( a, size_of_a_in_bytes / 8 ); break; //64 bit
00188    case 4: swap32( a, size_of_a_in_bytes / 4 ); break; //32 bit
00189    case 2: swap16( a, size_of_a_in_bytes / 2 ); break; //16 bit
00190    default: break; // do nothing
00191   }
00192 #else
00193   (void)a;
00194   (void)size_of_a_in_bytes;  // silence unused parameter compiler warning
00195   (void)bytesPerSample;
00196 #endif //VXL_LITTLE_ENDIAN
00197 }
00198 
00199 vxl_uint_32 vil_nitf2_data_mask_table::block_band_present( unsigned int block_x, unsigned int block_y, int band ) const
00200 {
00201   int band_to_use = i_mode == "S" ? band : 0;
00202   assert( block_x < BMR_n_BND_m.size() &&
00203           block_y < BMR_n_BND_m[block_x].size() &&
00204           band_to_use < static_cast<int>(BMR_n_BND_m[block_x][band_to_use].size()) );
00205   if (band_to_use >= static_cast<int>(BMR_n_BND_m[block_x][band_to_use].size()) )
00206     return false;
00207   return block_band_offset( block_x, block_y, band ) != 0xFFFFFFFF;
00208 }
00209 
00210 vxl_uint_32 vil_nitf2_data_mask_table::block_band_has_pad( unsigned int block_x, unsigned int block_y, int band ) const
00211 {
00212   int band_to_use = i_mode == "S" ? band : 0;
00213   assert( block_x < TMR_n_BND_m.size() &&
00214           block_y < TMR_n_BND_m[block_x].size() &&
00215           band_to_use < static_cast<int>(TMR_n_BND_m[block_x][band_to_use].size()) );
00216   if (band_to_use >= static_cast<int>(TMR_n_BND_m[block_x][band_to_use].size()) )
00217     return false;
00218   return pad_pixel( block_x, block_y, band ) != 0xFFFFFFFF;
00219 }