void OpenJPEGImage::loadImageInfo( int seq, int ang )
{

#ifdef DEBUG
  Timer timer;
  timer.start();
#endif

  // Get info structure
  opj_codestream_info_v2_t* cst_info = opj_get_cstr_info( _codec );
  numResolutions = cst_info->m_default_tile_info.tccp_info[0].numresolutions;
  quality_layers = cst_info->m_default_tile_info.numlayers;


  // High Throughput JPEG2000
#if defined(DEBUG) && defined(J2K_CCP_CBLKSTY_HT)
  if( (cst_info->m_default_tile_info.tccp_info[0].cblksty & J2K_CCP_CBLKSTY_HT) != 0 ||
      (cst_info->m_default_tile_info.tccp_info[0].cblksty & J2K_CCP_CBLKSTY_HTMIXED) != 0 ){
    logfile << "OpenJPEG :: HTJ2K codestream" << endl;
  }
#endif


  // Close our info structure
  opj_destroy_cstr_info( &cst_info );


  channels = _image->numcomps;
  bpc = _image->comps[0].prec;


  // Save first resolution level
  unsigned int w = _image->x1 - _image->x0;
  unsigned int h = _image->y1 - _image->y0;
  image_widths.push_back(w);
  image_heights.push_back(h);

#ifdef DEBUG
  logfile << "OpenJPEG :: DWT Levels: " << numResolutions << endl;
  logfile << "OpenJPEG :: Resolution : " << w << "x" << h << endl;
#endif

  // Loop through each resolution and calculate the image dimensions - 
  // We force a similar behaviour to TIFF with resolutions at floor(x/2)
  // rather than OpenJPEG's default ceil(x/2) 
  for( unsigned int c=1; c<numResolutions; c++ ){
    w = floor( w/2.0 );
    h = floor( h/2.0 );
    image_widths.push_back(w);
    image_heights.push_back(h);
#ifdef DEBUG
    logfile << "OpenJPEG :: Resolution : " << w << "x" << h << endl;
#endif
  }


  // If we don't have enough resolutions to fit a whole image into a single tile
  // we need to generate them ourselves virtually.
  unsigned int n = 1;
  w = image_widths[0];
  h = image_heights[0];
  while( (w>tile_width) || (h>tile_height) ){
    n++;
    w = floor( w/2.0 );
    h = floor( h/2.0 );
    if( n > numResolutions ){
      image_widths.push_back(w);
      image_heights.push_back(h);
    }
  }

  if( n > numResolutions ){
#ifdef DEBUG
    logfile << "OpenJPEG :: Warning! Insufficient resolution levels in JPEG2000 stream. Will generate "
	    << n-numResolutions << " extra levels dynamically -" << endl
	    << "OpenJPEG :: However, you are advised to regenerate the file with at least " << n << " levels" << endl;
#endif
  }

  if( n > numResolutions ) virtual_levels = n-numResolutions-1;
  numResolutions = n;


  // Need to assign basic colorspace information
  if( channels == 1 ){
    colourspace = (bpc==1)? BINARY : GREYSCALE;
  }
  else if( channels == 3 ) colourspace = sRGB;

  // Color space details
  string cs;
  switch( _image->color_space ){
    case OPJ_CLRSPC_SRGB:
      cs = "sRGB";
      break;
    case  OPJ_CLRSPC_SYCC:
      cs = "YUV";
      break;
    case OPJ_CLRSPC_CMYK:
      cs = "CMYK";
      break;
    case OPJ_CLRSPC_EYCC:
      cs = "e-YCC";
      break;
    case OPJ_CLRSPC_UNSPECIFIED:
      cs = "Unspecified";
      break;
    default:
      cs = "Unknown";
      break;
  }


#ifdef DEBUG
  logfile << "OpenJPEG :: " << bpc << " bit data" << endl
	  << "OpenJPEG :: " << channels << " channels" << endl
 	  << "OpenJPEG :: colour space: " << cs << endl
	  << "OpenJPEG :: " << quality_layers << " quality layers detected" << endl;
#endif

  // For bilevel images, force channels to 1 as we sometimes come across such images which claim 3 channels
  if( bpc == 1 ) channels = 1;

  // Get the max and min values for our data type
  for( unsigned int i=0; i<channels; i++ ){
    min.push_back( 0.0 );
    if( bpc > 8 && bpc < 16 ) max.push_back( 1<<bpc );
    if( bpc == 16 ) max.push_back( 65535.0 );
    else max.push_back( 255.0 );
  }
  
  // Indicate that our metadata has been read
  isSet = true;


#ifdef DEBUG
  logfile << "OpenJPEG :: loadImageInfo() :: " << timer.getTime() << " microseconds" << endl;
#endif
}