RawTile OpenJPEGImage::getTile( int seq, int ang, unsigned int res, int layers, unsigned int tile )
{

  // Scale up our output bit depth to the nearest factor of 8
  unsigned obpc = bpc;
  if( bpc <= 16 && bpc > 8 ) obpc = 16;
  else if( bpc <= 8 ) obpc = 8;

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

  if( res > numResolutions ){
    ostringstream tile_no;
    tile_no << "OpenJPEG :: Asked for non-existent resolution: " << res;
    throw file_error( tile_no.str() );
  }

  int vipsres = (numResolutions - 1) - res;

  unsigned int tw = tile_width;
  unsigned int th = tile_height;
  
  // Get the width and height for last row and column tiles
  unsigned int rem_x = image_widths[vipsres] % tile_width;
  unsigned int rem_y = image_heights[vipsres] % tile_height;

  // Calculate the number of tiles in each direction
  unsigned int ntlx = (image_widths[vipsres] / tile_width) + (rem_x == 0 ? 0 : 1);
  unsigned int ntly = (image_heights[vipsres] / tile_height) + (rem_y == 0 ? 0 : 1);

  // Check whether requested tile exists
  if( tile >= ntlx*ntly ){
    ostringstream tile_no;
    tile_no << "OpenJPEG :: Asked for non-existent tile: " << tile;
    throw file_error( tile_no.str() );
  }

  // Alter the tile size if it's in the last column
  if( ( tile % ntlx == ntlx - 1 ) && ( rem_x != 0 ) ) {
    tw = rem_x;
  }

  // Alter the tile size if it's in the bottom row
  if( ( tile / ntlx == ntly - 1 ) && rem_y != 0 ) {
    th = rem_y;
  }

  // Calculate the pixel offsets for this tile
  int xoffset = (tile % ntlx) * tile_width;
  int yoffset = (unsigned int) floor((double)(tile/ntlx)) * tile_height;
  
#ifdef DEBUG
  logfile << "OpenJPEG :: Tile size: " << tw << "x" << th << " @" << channels << endl;
#endif

  // Create our Rawtile object and initialize with data
  RawTile rawtile( tile, res, seq, ang, tw, th, channels, obpc );

  if( obpc == 16 ) rawtile.data = new unsigned short[tw*th*channels];
  else if( obpc == 8 ) rawtile.data = new unsigned char[tw*th*channels];
  else throw file_error( "OpenJPEG :: Unsupported number of bits" );

  rawtile.dataLength = tw*th*channels*(obpc/8);
  rawtile.filename = getImagePath();
  rawtile.timestamp = timestamp;

  // Process the tile
  process( res, layers, xoffset, yoffset, tw, th, rawtile.data );

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

  return rawtile;
}
RawTile OpenJPEGImage::getTile( int seq, int ang, unsigned int res, int layers, unsigned int tile )
{

   
  unsigned obpc = bpc;
  if( bpc <= 16 && bpc > 8 ) obpc = 16;
  else if( bpc <= 8 ) obpc = 8;

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

  if( res > numResolutions ){
    ostringstream tile_no;
    tile_no << "OpenJPEG :: Asked for non-existent resolution: " << res;
    throw file_error( tile_no.str() );
  }

  int vipsres = (numResolutions - 1) - res;

  unsigned int tw = tile_width;
  unsigned int th = tile_height;
  
   
  unsigned int rem_x = image_widths[vipsres] % tile_width;
  unsigned int rem_y = image_heights[vipsres] % tile_height;

   
  unsigned int ntlx = (image_widths[vipsres] / tile_width) + (rem_x == 0 ? 0 : 1);
  unsigned int ntly = (image_heights[vipsres] / tile_height) + (rem_y == 0 ? 0 : 1);

   
  if( tile >= ntlx*ntly ){
    ostringstream tile_no;
    tile_no << "OpenJPEG :: Asked for non-existent tile: " << tile;
    throw file_error( tile_no.str() );
  }

   
  if( ( tile % ntlx == ntlx - 1 ) && ( rem_x != 0 ) ) {
    tw = rem_x;
  }

   
  if( ( tile / ntlx == ntly - 1 ) && rem_y != 0 ) {
    th = rem_y;
  }

   
  int xoffset = (tile % ntlx) * tile_width;
  int yoffset = (unsigned int) floor((double)(tile/ntlx)) * tile_height;
  
#ifdef DEBUG
  logfile << "OpenJPEG :: Tile size: " << tw << "x" << th << " @" << channels << endl;
#endif

   
  RawTile rawtile( tile, res, seq, ang, tw, th, channels, obpc );

  if( obpc == 16 ) rawtile.data = new unsigned short[tw*th*channels];
  else if( obpc == 8 ) rawtile.data = new unsigned char[tw*th*channels];
  else throw file_error( "OpenJPEG :: Unsupported number of bits" );

  rawtile.dataLength = tw*th*channels*(obpc/8);
  rawtile.filename = getImagePath();
  rawtile.timestamp = timestamp;

   
  process( res, layers, xoffset, yoffset, tw, th, rawtile.data );

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

  return rawtile;
}