#ifndef _JP2_Reader_
#define _JP2_Reader_

#include	"JP2_Metadata.hh"
#include	"JP2_Exception.hh"

#include	"Dimensions.hh"

#include	<string>
#include	<vector>

#ifdef  STRINGIFIED
#undef  STRINGIFIED
#undef  AS_STRING
#endif
#define STRINGIFIED(name)		#name
#define AS_STRING(name)			STRINGIFIED(name)

namespace UA::HiRISE
{

using PIRL::Cube;
using PIRL::Rectangle;

class JP2_Reader
:	public JP2_Metadata
{
public:

static const char* const
	ID;

enum Image_Data_Format
	{
	FORMAT_AD_HOC = 0,
	FORMAT_BSQ = 1,
	FORMAT_BIP = 2,
	FORMAT_BIL = 3,
	TOTAL_FORMATS
	};

static const char* const
	FORMAT_DESCRIPTIONS[];

static const unsigned int
	ALL_BANDS;

static const unsigned long long
	DEFAULT_RENDERING_INCREMENT_BYTES;

static Image_Data_Format
	Default_Image_Data_Format;

typedef std::vector<bool>				Band_Map;

struct Rendering_Monitor
	{

	enum Status
		{
		INFO_ONLY			= 0,
		LOW_QUALITY_DATA	= (1 << 0),
		TOP_QUALITY_DATA	= (1 << 1),
		RENDERED_DATA_MASK	= (1 << 0) |
							  (1 << 1),
		CANCELED			= (1 << 2),
		DONE				= (1 << 3)
		};

	static const std::string
		Status_Message[];

	virtual bool notify (JP2_Reader& JP2_reader,
		Status status, const std::string& message,
		const Cube& rendered_region = Cube (),
		const Cube& image_region = Cube ()) = 0;

	virtual ~Rendering_Monitor () {}
	};

JP2_Reader ();

JP2_Reader (const JP2_Reader& JP2_reader);

virtual ~JP2_Reader () throw();

JP2_Reader& image_data (void** pixel_buffers, unsigned long long buffer_size);

inline void** image_data (unsigned long long* buffer_size = NULL) const
	{
	if (buffer_size)
		*buffer_size = Buffer_Size;
	return Image_Data;
	}

void* image_data (unsigned int band,
	unsigned int line = 0, unsigned int pixel = 0);

inline bool user_buffer () const
	{return User_Buffer;}

JP2_Reader& image_data_format (Image_Data_Format data_format);

inline Image_Data_Format image_data_format () const
	{return Data_Format;}

std::string image_data_format_description (Image_Data_Format data_format) const;

static Image_Data_Format default_image_data_format
	(Image_Data_Format data_format);

inline static Image_Data_Format default_image_data_format ()
	{return Default_Image_Data_Format;}

JP2_Reader& image_data_format
	(unsigned int pixel_stride, unsigned int line_stride);

unsigned int pixel_stride () const;

unsigned int line_stride () const;

bool render_band (unsigned int band, bool enable = true);

bool is_rendered_band (unsigned int band) const;

inline unsigned int rendered_bands () const
	{return Rendered_Region.Depth;}

inline const Band_Map& rendered_bands_map () const
	{return Rendered_Bands;}

inline JP2_Reader& image_region (const Rectangle& region)
	{resolution_and_region (Resolution_Level, region); return *this;}

inline JP2_Reader& image_region
	(int x, int y, unsigned int width, unsigned int height)
	{resolution_and_region (Resolution_Level, Rectangle (x, y, width, height));
		return *this;}

inline Cube image_region () const
	{return Image_Region;}

inline JP2_Reader& resolution_level (unsigned int level)
	{resolution_and_region (level, Image_Region); return *this;}

inline unsigned int resolution_level () const
	{return Resolution_Level;}

inline Cube rendered_region () const
	{return Rendered_Region;}

inline unsigned int rendered_width () const
	{return Rendered_Region.Width;}

inline unsigned int rendered_height () const
	{return Rendered_Region.Height;}

inline JP2_Reader& swap_pixel_bytes (bool swap_data)
	{Swap_Pixel_Bytes = swap_data; return *this;}

inline bool swap_pixel_bytes () const
	{return Swap_Pixel_Bytes;}

JP2_Reader& rendered_pixel_bits (unsigned int bits);

inline unsigned int rendered_pixel_bits () const
	{return Rendered_Bits;}

unsigned int rendered_pixel_bytes () const;

inline JP2_Reader& rendering_increment_lines (unsigned int line_increment)
	{Rendering_Increment_Lines = line_increment; return *this;}

inline unsigned int rendering_increment_lines () const
	{return Rendering_Increment_Lines;}

unsigned int effective_rendering_increment_lines () const;

JP2_Reader& processing_threads (unsigned int threads);

inline unsigned int processing_threads () const
	{return Thread_Count;}

inline static void default_jpip_proxy (const std::string& server)
	{Default_JPIP_Proxy = server;}
inline static std::string default_jpip_proxy ()
	{return Default_JPIP_Proxy;}
inline JP2_Reader& jpip_proxy (const std::string& server)
	{JPIP_Proxy = server; return *this;}
inline std::string jpip_proxy () const
	{return JPIP_Proxy;}

inline static void default_jpip_cache_directory (const std::string& directory)
	{Default_JPIP_Cache_Directory = directory;}
inline static std::string default_jpip_cache_directory ()
	{return Default_JPIP_Cache_Directory;}
inline JP2_Reader& jpip_cache_directory (const std::string& directory)
	{JPIP_Cache_Directory = directory; return *this;}
inline std::string jpip_cache_directory () const
	{return JPIP_Cache_Directory;}

inline JP2_Reader& rendering_monitor (Rendering_Monitor* monitor)
	{Monitor = monitor; return *this;}

inline Rendering_Monitor* rendering_monitor () const
	{return Monitor;}

inline unsigned long long bytes_rendered ()
	{return Bytes_Rendered;}

virtual JP2_Reader* clone () const = 0;

virtual int open (const std::string& source) = 0;

virtual bool is_open () const = 0;

static unsigned int default_JPIP_request_timeout (unsigned int timeout);

inline static unsigned int default_JPIP_request_timeout ()
	{return Default_JPIP_Request_Timeout;}

inline JP2_Reader& JPIP_request_timeout (unsigned int timeout)
	{JPIP_Request_Timeout = timeout; return *this;}

inline unsigned int JPIP_request_timeout () const
	{return JPIP_Request_Timeout;}

virtual bool reconnect ();

static int default_autoreconnect_retries (int retries);

inline static int default_autoreconnect_retries ()
	{return Default_Autoreconnect_Retries;}

inline JP2_Reader& autoreconnect_retries (int retries)
	{Autoreconnect_Retries = retries; return *this;}

inline int autoreconnect_retries () const
	{return Autoreconnect_Retries;}

virtual bool ready (std::string* report = NULL) const;

virtual bool resolution_and_region
	(unsigned int resolution, const Rectangle& region) = 0;

virtual Cube render () = 0;

virtual void close (bool force = false) = 0;

virtual void reset ();

unsigned long long rendered_image_bytes () const;

unsigned long long minimum_buffer_size () const;

protected:

bool data_disposition
	(Rendering_Monitor::Status status, const std::string& message,
		const Cube& region_rendered, const Cube& image_region_rendered);

void allocate_image_data_buffer ();

private:

bool allocate_data_buffers_array ();

void delete_local_data_buffer ();

protected:

bool
	Rendering_Configuration_Initialized;

void
	**Image_Data;

unsigned long long
	Buffer_Size;

bool
	User_Buffer;

unsigned int
	Pixel_Stride;

unsigned int
	Line_Stride;

Image_Data_Format
	Data_Format;

Band_Map
	Rendered_Bands;

Cube
	Image_Region;

unsigned int
	Resolution_Level;

Cube
	Rendered_Region;

bool
	Swap_Pixel_Bytes;

unsigned int
	Rendered_Bits;

unsigned int
	Rendering_Increment_Lines;

unsigned int
	Thread_Count;

static unsigned int
	Default_JPIP_Request_Timeout;

unsigned int
	JPIP_Request_Timeout;
static std::string
	Default_JPIP_Proxy,
	Default_JPIP_Cache_Directory;
std::string
	JPIP_Proxy,
	JPIP_Cache_Directory;

Rendering_Monitor
	*Monitor;

static int
	Default_Autoreconnect_Retries;
int
	Autoreconnect_Retries;

unsigned long long
	Bytes_Rendered;

};	

std::string magnitude (unsigned long long value);

unsigned int processing_units ();

}	
#endif
/*	JP2_Reader

HiROC CVS ID: $Id: JP2_Reader.hh,v 1.49 2012/03/12 22:21:19 castalia Exp $

Copyright (C) 2009-2010  Arizona Board of Regents on behalf of the
Planetary Image Research Laboratory, Lunar and Planetary Laboratory at
the University of Arizona.

This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License, version 2.1,
as published by the Free Software Foundation.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.

*******************************************************************************/

#ifndef _JP2_Reader_
#define _JP2_Reader_

#include	"JP2_Metadata.hh"
#include	"JP2_Exception.hh"

//	PIRL++
#include	"Dimensions.hh"

#include	<string>
#include	<vector>

//	Provides stringification of #defined names.
#ifdef  STRINGIFIED
#undef  STRINGIFIED
#undef  AS_STRING
#endif
#define STRINGIFIED(name)		#name
#define AS_STRING(name)			STRINGIFIED(name)

namespace UA::HiRISE
{
//	PIRL++ Dimensions classes.
using PIRL::Cube;
using PIRL::Rectangle;

/**	A <i>JP2_Reader</i> reads image pixel data from a JPEG2000 JP2
	formatted image source.

	After a JP2_Reader is constructed it must be configured. The reader
	must be configured with at least an input JP2 {@link source(const
	std::string&) source} before it can be {@link open() opened}. Once
	opened accessors can be used to get information from the JP2 file,
	especially image data characterization. A JP2_Reader may be
	configured to operate on a selected {@link image_region(const
	Rectangle&) region} of the entire image or render at less than the
	full {@link resolution_level(unsigned int) resolution level}. It may
	be configured to {@link swap_pixel_bytes(bool) reorder} multi-byte
	pixel data, though the correct data order for the host system will be
	generated by default. It must also be configured with an output
	{@link image_data(void*, unsigned long long*) image data pixel
	buffer} to be {@link ready() ready} to {@link render() render the
	image data}.

	A JP2_Reader may be reused with or without reconfiguration between
	uses. Typically, changes are made to the image region and/or
	resolution, and possibly the pixel data buffer, before initiating
	A JP2_Reader is an abstract base class for subclasses that implement
	the JP2 format handler and JPEG2000 codestream rendering engine.

	@author		Bradford Castalia, UA/HiROC
	@version	$Revision: 1.49 $
*/
class JP2_Reader
:	public JP2_Metadata
{
public:
/*==============================================================================
	Constants
*/
//!	Class identification name with source code version and date.
static const char* const
	ID;

//!	Specifies the output structure of image pixel data.
enum Image_Data_Format
	{
	FORMAT_AD_HOC = 0,
	FORMAT_BSQ = 1,
	FORMAT_BIP = 2,
	FORMAT_BIL = 3,
	TOTAL_FORMATS
	};

static const char* const
	FORMAT_DESCRIPTIONS[];

/**	The {@link render_band(unsigned int, bool) band rendering selection}
	applies to all image bands.
*/
static const unsigned int
	ALL_BANDS;

/**	Default incremental rendering data amount.

	The default maximum rendering increment amount is 8 MB.
*/
static const unsigned long long
	DEFAULT_RENDERING_INCREMENT_BYTES;

/*==============================================================================
	Defaults
*/
static Image_Data_Format
	Default_Image_Data_Format;

/*==============================================================================
	Types
*/
//!	Map of image bands to be rendered.
typedef std::vector<bool>				Band_Map;

/**	Source rendering process progress monitoring class.

	An implementation of this class may be used to receive notifications
	of each rendering increment.

	@see	rendering_monitor(Rendering_Monitor*)
*/
struct Rendering_Monitor
	{
	//!	Rendering status code.
	enum Status
		{
		INFO_ONLY			= 0,
		LOW_QUALITY_DATA	= (1 << 0),
		TOP_QUALITY_DATA	= (1 << 1),
		RENDERED_DATA_MASK	= (1 << 0) |
							  (1 << 1),
		CANCELED			= (1 << 2),
		DONE				= (1 << 3)
		};

	static const std::string
		Status_Message[];

	/**	Notification of rendering progress.

		Sending a notification provides information about the progress of
		rendering activity. This can be particularly useful when the
		rendering is being done within an asynchronous thread by an
		application that needs to remain responsive to GUI events while
		rendering is in progress. Each notification occurs within a
		rendering context. Typically this will be the availability of new
		rendered image data, either some part of the current render
		request or the completion of the request. It may also be
		informational only; e.g. that a JPIP server connection needed to
		obtain data for rendering is in progress.

		<b>N.B.</b>: The return value from the notification determines
		whether the redering activity will continue or not. A false
		return value will immediately discontinue a JPIP server connection
		attempt or any data rendering in progress. This can be very
		useful in interactive applications where the image data rendering
		request is no longer needed - e.g. because the user as moved the
		image region of interest - or because a JPIP server connection is
		taking too long.

		@param	JP2_reader	A reference to the JP2_Reader that is doing
			the image rendering process. The JP2_Reader may be modifed,
			however rendering will continue - if there is more source
			data to render and the return value is true - using the
			JP2_Reader configuration (including pixel data buffers) that
			was in effect at the time that {@link render() rendering} was
			started.
		@param	status	A rendering {@link #Status} code that indicates
			the context in which the notification is being sent.
		@param	message	A message associated with the notification event.
			This may be empty.
		@param	rendered_region	A Cube describing the region of the image
			that has just been rendered relative to the resolution of the
			rendering grid. The Depth of the cube is the number of source
			image bands that have been rendered. This may be empty if the
			notification event is not associated with rendered data
			availability.
		@param	image_region	A Cube describing the region of the image
			that has just been rendered relative to the full resolution
			image grid. The Depth of the cube is the number of source
			image bands that have been rendered. This may be empty if the
			notification event is not associated with rendered data
			availability.
		@return	true, if the rendering process is to continue; false if
			the rendering process is to be discontinued.
	*/
	virtual bool notify (JP2_Reader& JP2_reader,
		Status status, const std::string& message,
		const Cube& rendered_region = Cube (),
		const Cube& image_region = Cube ()) = 0;

	virtual ~Rendering_Monitor () {}
	};

/*==============================================================================
	Constructors
*/
/**	Construct a JP2_Reader.

	The reader must be {@link open() opened} before it can be used.
*/
JP2_Reader ();

/**	Copy a JP2_Reader.

	The new JP2_Reader will be {@link open() open} and ready to use.

	@param	JP2_reader	The JP2_Reader to be copied.
*/
JP2_Reader (const JP2_Reader& JP2_reader);

/**	Destroy this JP2_Reader.
*/
virtual ~JP2_Reader () throw();

/*==============================================================================
	Accessors
*/
/**	Set the image data buffers to contain the rendered pixels.

	A data storage buffer must be provided for the pixels rendered from
	the source. Each band that is rendered must be provided with a
	buffer. Thus the array of image data buffers must contain one entry
	for each {@link image_bands() image band} to be rendered in image
	band order (the first entry corresponds to the first band, etc.);
	bands that are not to be rendered must have a NULL entry in the
	array. <b>N.B.</b> The specification of NULL pixel buffers array
	entries enables selective rendering of image bands, however image
	band rendering may also be independently {@link render_band(unsigned
	int) disabled or enabled}.

	<b>WARNING</b>: The address of each image data buffer must be
	correctly aligned for the data type that will be used to access the
	rendered pixel values. For {@link rendered_pixel_bytes() rendered
	pixels} of one byte, there are no alignment issues. But for two byte
	pixels access as 16-bit data types alignment is necessary. In this
	case alignment can be achieved by allocating the buffers as arrays of
	the data type (or larger) that will be used to access the pixel
	values.

	Each pixel buffers array entry is the address of the first pixel
	sample for the corresonding band; or NULL if the corresponding band
	is not to be rendered. There is no requirement that all the pixel
	buffers be contiguous in memory. Rendered pixel sample values for
	each image band will be stored in the corresponding buffer according
	to the structure specified by the {@link pixel_stride(unsigned int)
	pixel stride} and {@link line_stride(unsigned int) line stride}. All
	bands will use the same image data structure.

	The size of one buffer must be specified; all buffers must be able to
	hold the same amount of data. This value is used as a safety check
	before pixel {@link render() rendering} occurs that adequate buffer
	storage has been allocated. <b>N.B.</b>: It is the responsibility of the
	user to actually allocate sufficient storage for each buffer.

	The size of each data buffer must be sufficient to hold the pixels of
	one band of the rendered region. The size of each data buffer depends
	on several factors: the sizes of the {@link rendered_pixel_bytes()
	rendered pixel sample} and {@link rendered_region() rendered region},
	and the specified structure of the {@link image_data_format(unsigned
	int, unsigned int) data format} as it affects the {@link
	pixel_stride() pixel stride} and {@link line_stride() line stride} of
	the data structure. All these factors are include in determining the
	{@link minimum_buffer_size() minimum buffer size}. For example, for
	single byte pixel data stored in BSQ format the minimum buffer size
	would be {@link rendered_width() rendered width} times the {@link
	rendered_height() rendered height}; for a two byte pixel, all other
	rendering characteristics being equal, the minimum buffer size would
	then quadruple (the size of each dimension, in bytes, doubles).
	<b>N.B.</b>: The buffer size check is not done here because other
	rendering configuration settings that would affect the minimum buffer
	size} may not yet have been specified; the check is done just before
	rendering is started.

	If an array of image pixel data buffers is not specified, or it is
	specified as NULL, rendered image data storage will be automatically
	provided when the source is {@link render() rendered}.

	<b>N.B.</b>: When image data buffers are automatically allocated the
	size of each buffer is limited to the maximum value of the host
	system's native size_t data type. This is typically either an
	unsigned 32- or 64-bit value depending on the system architecture and
	compiler options (e.g. the -m64 option might be required to obtain a
	64-bit size_t). {@link render() Rendering} will not be {@link ready()
	ready} if the required data buffers size can not be allocated.

	@param	pixel_buffers	An array of pointers to memory that will
		receive the rendered pixel data. There must be one entry for each
		{@link image_bands() image band}. NULL entries indicate image
		bands that are not to be rendered. If NULL, pixel data storage
		will automatically be provided locally.
	@param	buffer_size	The size, in bytes, of the first pixel buffer.
		<b>N.B.</b>: Only the size of one pixel buffer is needed; the
		storage requirements for each image band is the same. The
		specified size will be used to check that sufficient space is
		available to receive the region of the image to be rendered. The
		application is responsible for ensuring sufficient space given
		the rendering characteristics that have been specified. More
		space than is needed may be allocated and specified.
	@return	This JP2_Reader.
	@throws	JP2_Logic_Error	If the source has not yet been {@link
		open(const std::string&) opened}, and thus the number of image
		bands is not yet known.
*/
JP2_Reader& image_data (void** pixel_buffers, unsigned long long buffer_size);

/**	Get the image data pixel buffers.

	To access pixel values cast the value of each array entry to the data
	type consistent with the {@link rendered_pixel_bits() pixel
	precision}. The application must be aware of {@link
	swap_pixel_bytes() byte ordering} for multi-byte pixels, and might
	need to be concered about whether the pixel values are {@link
	signed_data() signed}.

	Pixel values are rendered into the image data buffers according to
	the {@link pixel_stride(unsigned int) pixel stride} and {@link
	line_stride(unsigned int) line stride} structure.

	<b>WARNING</b>: Do not delete image data buffers unless they are
	{@link user_buffer() user specified}. Note that there may be NULL
	entries in the array of image data buffer pointers corresponding to
	image bands that are not rendered.

	<b>CAUTION</b>: An image data buffer array and its associate buffer
	storage that is not {@link user_buffer() user specified} will be
	deleted and reallocated whenever the image data is {@link render()
	rendered} which will invalidate the previous image data buffer. If
	data from an automatically provided pixel buffer is to be retained
	across multiple renderings it must be copied.

	@param	buffer_size	A pointer to an unsigned long long variable that
		will receive the size of the image data buffer in bytes. This
		will be zero if the size of the buffer is unknown. May be NULL if
		the buffer size is not to be returned.
	@return	The address (void**) of the pixel data buffers array.
	@see	image_data(void**, unsigned long long)
	@see	bytes_of_bits(unsigned int)
*/
inline void** image_data (unsigned long long* buffer_size = NULL) const
	{
	if (buffer_size)
		*buffer_size = Buffer_Size;
	return Image_Data;
	}

/**	Get the image data address for an image location.

	@param	band	A rendered image band index; zero is the first band.
	@param	line	The index of a line in the band; zero is the first
		line of the rendered region.
	@param	pixel	The index of a pizel in the line; zero is the first
		pixel of the rendered line.
	@return	The address of the start of the pixel value. This will be
		NULL if no {@link image_data(void**, unsigned long long) image
		data is available.
	@throws	JP2_Invalid_Argument	If any of the arguments are outside the
		limits of the {@link rendered_region() rendered region}.
	@see	image_data(unsigned long long*)
	@see	rendered_region()
*/
void* image_data (unsigned int band,
	unsigned int line = 0, unsigned int pixel = 0);

/**	Test if the image data buffer is provided by the user.

	@return	true if the {@link image_data(unsigned long long*) image data
		buffer} is {@link image_data(void*, unsigned long long) user
		specified}; false if the buffer is automatically provided and
		locally managed.
*/
inline bool user_buffer () const
	{return User_Buffer;}

/**	Set the image data format structure.

	A named image data structure is used to indirectly specify the {@link
	pixel_stride(unsigned long) pixel stride} and {@link
	line_stride(unsigned long) line stride} used to traverse the rendered
	pixel stored in the {@link image_data(unsigned long long*) image
	data} buffer. <b>N.B.</b>: Using a named image data structure
	presumes that the image raster is stored contiguously in the buffer;
	i.e. there are no gaps when traversing the buffer for pixel data. If
	an {@link image_data(void*, unsigned long long) image data buffer is
	specified} in which the image data is to be non-contiguously stored -
	e.g. if an image region is to be rendered into a large buffer where
	other image regions reside - then the pixel and line strides need to
	be specified according to how the buffer is being used.

	Three standard image data format structures are recognized by an
	{@link #Image_Data_Format} token:
<dl>
<dt>FORMAT_BSQ (0) - Band Sequential
<dd>All pixels sample values for the first image band are sequentially
	stored in line-major raster order - all samples for the first line
	starting with the upper-left pixel immediately followed by all pixels
	for the second line, etc. - with any additional bands of sample data
	following sequentially. For example, a three color RGB image would
	have all the red smaple values first followed by the all the green
	values and then all the blue values.

	The distance from the start of a pixel sample to the start of the
	horizontally adjacent sample - the pixel stride - is the {@link
	rendered_pixel_bytes() pixel storage size}. The distance from a
	pixel sample to the vertically adjacent sample - the line stride - is
	the pixel stride * the {@link rendered_width() width of the rendered
	image area} or line length.

<dt>FORMAT_BIP (1) - Band Interleaved by Pixel
<dd>All the pixel sample values for all bands of the upper-left pixel
	are continguous followed by pixel samples for all bands of the next
	location in the same line; the samples for all bands of the first
	pixel of the second line immediately follows those of the last pixel
	of the first line, etc. For example, a three color RGB image would
	have the red, green and blue sample values for the first pixel
	followed by RGB value triplets for all remaining image pixels in
	line-major order.

	The distance from the start of a pixel sample to the start of the
	horizontally adjacent sample - the pixel stride - is the {@link
	rendered_pixel_bytes() pixel storage size} * the {@link image_bands
	() number of bands}. The distance from a pixel sample to the
	vertically adjacent sample - the line stride - is the pixel stride *
	the {@link rendered_width() width of the rendered image area} or
	line length.

<dt>FORMAT_BIL (2) - Band Interleaved by Line
<dd>All the pixel sample values for the first line, starting with the
	upper-left pixel, of the first band are followed by all the samples
	of the first line of the second band, etc. for all bands. This is
	immediately followed by all the pixel sample values for the second
	line of the first band, then the samples of the second line of the
	second band, etc. for all bands. This continues for all lines. For
	example, a three color RGB image would have all the red sample
	values for the first line followed by all the green values for the
	first line and then all blue values for the first line with this red
	line, green line, blue line sequence continuing for all the remaining
	lines of the image.

	The distance from the start of a pixel sample to the start of the
	horizontally adjacent sample - the pixel stride - is the {@link
	rendered_width() width of the rendered image area} or line length (in
	bytes, the line length * the {@link rendered_pixel_bytes() pixel
	storage size}). The distance from a pixel sample to the vertically
	adjacent sample - the line stride - is the line length * the {@link
	image_bands() number of bands} (in bytes, the line length * the
	number of bands * the {@link rendered_pixel_bytes() pixel storage
	size}).
</dl>

	The default image data pixel structure is determined when the
	module is compiled by the DEFAULT_IMAGE_DATA_FORMAT token which can
	be any one of the Image_Data_Format names. The runtime {@link
	default_image_data_format(Image_Data_Format) default image data
	format} may be changed.

	@param	data_format	An Image_Data_Format value.
	@return	This JP2_Reader.
	@throws	JP2_Invalid_Argument	If data_format is not a valid value.
	@see	image_data_format(unsigned int, unsigned int)
*/
JP2_Reader& image_data_format (Image_Data_Format data_format);

/**	Get the image data format structure.

	@return	An Image_Data_Format code, or zero indicating that an ad hoc
		format was specified.
	@see	image_data_format(Image_Data_Format data_format)
*/
inline Image_Data_Format image_data_format () const
	{return Data_Format;}

/**	Get the name of an {@link #Image_Data_Format}.

	@param	data_format	An Image_Data_Format value.
	@return A string providing a very brief description of the data format
		code.
	@see	image_data_format(Image_Data_Format)
*/
std::string image_data_format_description (Image_Data_Format data_format) const;

/**	Set the JP2_Reader default image data format.

	The specified {@link #Image_Data_Format} will be used whenever a
	new JP2_Reader is constructed and not explicitly configured with
	image data format structure information.

	@param	data_format	An Image_Data_Format value.
	@return	The previous default Image_Data_Format value.
	@throws	JP2_Invalid_Argument	If data_format is not a valid value.
*/
static Image_Data_Format default_image_data_format
	(Image_Data_Format data_format);

/**	Get the JP2_Reader default image data format.

	@return	The current default Image_Data_Format value. This will be
	@see	default_image_data_format(Image_Data_Format)
*/
inline static Image_Data_Format default_image_data_format ()
	{return Default_Image_Data_Format;}

/**	Set the image data format structure in terms of pixel and line stride.

	The pixel stride is the distance, in pixel samples, from the start of
	a pixel sample in the {@link image_data(unsigned long long*) image
	data} buffer to the start of the horizontally adjacent pixel in the
	same line of the same band. The pixel stride is used to move from one
	pixel datum to another when traversing an image line rendered into
	the image data buffer.

	The line stride is the distance, in pixel samples, from a pixel in the
	{@link image_data(unsigned long long*) image data} buffer to the
	vertically adjacent pixel in the same band. The line stride is used
	to move from one image line to another when traversing an image band
	rendered into the image data buffer.

	<b>N.B.</b>: The pixel sample size is the {@link
	bytes_of_bits(unsigned int) number of bytes} required to hold the
	{@link rendered_pixel_bits(unsigned int) pixel bits}. A multi-band
	image will have the corresponding number of pixel samples.

	<b>N.B.</b>: The pixel and line stride values are relative to the
	{@link rendered_region() rendered image} grid rather than the full
	resolution grid and so may be affected by the {@link
	resolution_level() resolution level} depending on how the image data
	storage is structured.

	@param	pixel_stride	The pixel stride distance in pixel samples. This
		must be a positive, non-zero value.
	@param	line_stride	The line stride distance in pixel samples.
	@return	This JP2_Reader.
	@throws	JP2_Invalid_Argument	If either stride value is zero.
	@see	image_data_format(Image_Data_Format)
	@see	pixel_stride()
	@see	line_stride()
*/
JP2_Reader& image_data_format
	(unsigned int pixel_stride, unsigned int line_stride);

/**	Get the image data buffer pixel stride.

	@return	The pixel stride distance in pixel samples.
	@see	image_data_format(unsigned int, unsigned int)
*/
unsigned int pixel_stride () const;

/**	Get the image data buffer line stride.

	@return	The line stride distance in pixel samples.
	@see	image_data_format(unsigned int, unsigned int)
*/
unsigned int line_stride () const;

/**	Set an image band to be rendered.

	<b>N.B.</b>: Each image band that is enabled for rendering must be
	provided with an image data buffer. If the image data buffers are not
	{@link user_buffer() provided by the user} then they will
	automatically be provided when the source is rendered. When the user
	provides the {@link image_data(void**, unsigned long long) image data
	storage) each band allocated a buffer is automatically enabled for
	rendering, and rendering of all other bands is disabled; this
	overrides rendered band selection previously set here. Rendering of a
	band automatically selected when image buffers were specified by the
	user may be disabled here without changing the image band buffer
	specifications (the user specified buffer will remain bound to the
	band, but will not be used); and the band may be re-enabled for
	rendering again. However, if a user specified buffer was not provided
	for a band - and therefore rendering for the band was disabled -
	attempting to enable the band for rendering here will have no effect;
	when user specified image data buffers are provided only image bands
	provided with a buffer may be enabled for rendering.

	@param	band	The index (starting with zero) of an image band,
		or {@link #ALL_BANDS} if the opertion applies to all bands.
	@param	enable	If true the band will be rendered; otherwise the
		band will not be rendered.
	@return	false if enable is true but the pixel image data buffer is
		{@link user_buffer() user specified} and the selected band, or
		any band if ALL_BANDS selected, does not have a buffer assigned
		to it; true otherwise.
	@throws	JP2_Invalid_Argument	If the band value is greater than the
		{@link image_bands() number of bands} in the source image. This
		will always happen if the source has not yet been {@link open()
		opened}.
	@see	rendered_bands_map()
	@see	is_rendered_band(unsigned int)
	@see	rendered_bands()
	@see	image_data(void**, unsigned long long)
*/
bool render_band (unsigned int band, bool enable = true);

/**	Test if an image band will be rendered.

	@param	band	The index (starting with zero) of an image band.
	@return	true if the band will be rendered; false otherwise;
	@see	render_band(unsigned int, bool)
*/
bool is_rendered_band (unsigned int band) const;

/**	Get the number of image bands that will be rendered.

	The number of rendered image bands only includes bands that have been
	selected for rendering.

	@return	The number of image bands selected for rendering. This will
		be zero until the source has been {@link open() opened}.
	@see	render_band(unsigned int, bool)
*/
inline unsigned int rendered_bands () const
	{return Rendered_Region.Depth;}

/**	Get the map of all bands to be rendered.

	Each entry of the Band_Map that is returned indicates whether the
	corresponding image band will be {@link render() rendered} or not.
	If the entry has a true value, the corresponding band will be rendered;
	otherwise the band will not be rendered.

	@return	A reference to the Band_Map for all bands to be rendered.
*/
inline const Band_Map& rendered_bands_map () const
	{return Rendered_Bands;}

/**	Set the image region that will be rendered from the JP2 source.

	The image region is specified relative to the full resolution image
	grid. The region can lie partially or completely outside of the
	source {@link image_size() image area}. The actual source image
	region rendered will be the intersection of the selected region with
	the image area. If there is no interesection nothing will be
	rendered.

	The depth of the image region is determined by the number of {@link
	rendered_bands() rendered bands} from the image.

	@param	region	A Rectangle specifying the image region to be
		rendered on the full resolution grid.
	@return	This JP2_Reader.
	@see	image_region(int, int, unsigned int, unsigned int)
*/
inline JP2_Reader& image_region (const Rectangle& region)
	{resolution_and_region (Resolution_Level, region); return *this;}

/**	Set the image region that will be rendered from the JP2 source.

	@param	x	The horizontal (x-axis) position of the image region.
	@param	y	The vertical (y-axis) position of the image region.
	@param	width	The width of the image region.
	@param	height	The height of the image region.
	@return	This JP2_Reader.
	@see	image_region(const Rectangle&)
*/
inline JP2_Reader& image_region
	(int x, int y, unsigned int width, unsigned int height)
	{resolution_and_region (Resolution_Level, Rectangle (x, y, width, height));
		return *this;}

/**	Get the image region that will be rendered from the JP2 source.

	The image region is relative to the full resolution image grid.
	<b>N.B.</b>: This is different than the {@link rendered_region()
	which is relative to the rendered grid; i.e. the full resolution
	image grid reduced by the {@link resolution_level() resolution level}
	currently selected for rendering.

	@return	The Cube specifying the image region from the source to be
		rendered. The depth of the cube is the number of {@link
		rendered_bands() rendered bands} from the source image. If the
		JP2 source has not yet been {@link open() opened} all the Cube
		values will be zero. When the JP2 source is opened the image
		region will be initialized to the entire {@link image_size()
		image size}.
	@see	image_region(const Rectangle&)
	@see	rendered_region()
	@see	image_size()
*/
inline Cube image_region () const
	{return Image_Region;}

/**	Set the resolution level at which the codestream will be rendered.

	Level 1 is full resolution. Level 2 renders the image at half size,
	level 3 at quarter size, etc.; i.e. the image size is divided by
	2**(level-1). Specifying a rendering {@link
	resolution_level(unsigned int) resolution level} greater than 1 will
	result in a correspondingly smaller {@link rendered_region()
	rendered image region} from the selected full resolution {@link
	image_region() image region}.

	<b>N.B.</b>: The resolution level is one more than the JPEG2000
	decomposition level.

	@param	level	The codestream rendering resolution level.
	@return	This JP2_Encoder.
*/
inline JP2_Reader& resolution_level (unsigned int level)
	{resolution_and_region (level, Image_Region); return *this;}

/**	Get the resolution level at which the codestream will be rendered.

	@return	The codestream rendering resolution level.
	@see	resolution_level(unsigned int)
*/
inline unsigned int resolution_level () const
	{return Resolution_Level;}

/**	Get the rendered image region.

	The rendered image region is the {@link image_region() image region}
	on the full resolution grid selected for rendering after reduction by
	the {@link resolution_level() resolution level} to the rendering
	grid. <b>N.B.</b>: The rendered region is affected by the current
	rendering resolution; the image region is not. For example, An image
	region located at 100,200 that is 300 pixels wide by 400 pixels high
	on the full resolution grid rendered at resolution level 2 will
	result in a rendered region located at 50,100 that is 150 pixels wide
	by 200 pixels high on the reduced resolution grid.

	<b>N.B.</b>: The depth of the rendered image region is the number of
	bands that will be rendered after accounting for disabled {@link
	render_band(unsigned int, bool) band rendering}.

	@return	A Cube specifying the rendered image region on the rendering
		grid with the depth specifying the number of {@link
		rendered_bands() bands to be rendered}. These values will be zero
		until the JP2 source has been {@link open() opened} when they will
		be initialized to the full {@link image_size() image size}.
	@see	rendered_width()
	@see	rendered_height()
	@see	image_region()
*/
inline Cube rendered_region () const
	{return Rendered_Region;}

/**	Get the width of the rendered region.

	@return	The width of the rendered region. This will be zero until the
		JP2 source has been {@link open() opened}.
	@see	rendered_height()
	@see	rendered_region()
*/
inline unsigned int rendered_width () const
	{return Rendered_Region.Width;}

/**	Get the height of the rendered region.

	@return	The height of the rendered region. This will be zero until the
		JP2 source has been {@link open() opened}.
	@see	rendered_width()
	@see	rendered_region()
*/
inline unsigned int rendered_height () const
	{return Rendered_Region.Height;}

/**	Set whether multi-byte pixels will be reordered when being rendered.

	By default multi-byte pixels be ordered appropriately for the host
	system architecture. <b>N.B.</b>: The compressed pixel data in a JP2
	file is expected to be effectively in MSB (most significant byte
	first) order. However, compressed pixel sample bits can be in any
	order and the JP2 file does not specify the order. Therefor, if the
	JP2 codestream is known, a priori, to produce LSB (least significant
	byte first) multi-byte pixel samples, then pixel byte swapping should
	be set.

	@param	swap_data	true if multi-byte pixels are to be reordered
		when rendering; false otherwise.
	@return	This JP2_Reader.
*/
inline JP2_Reader& swap_pixel_bytes (bool swap_data)
	{Swap_Pixel_Bytes = swap_data; return *this;}

/**	Tests if multi-byte pixels will be reordered when being rendered.

	@return	true if multi-byte pixels are to be reordered while
		rendering; false otherwise.
	@see	swap_pixel_bytes(bool)
*/
inline bool swap_pixel_bytes () const
	{return Swap_Pixel_Bytes;}

/**	Set the rendered pixel precision.

	The pixel precision can not exceed 16 bits

	@param	bits	The number of bits per pixel to be used when rendering
		the image data.
	@return	This JP2_Reader.
	@see	rendered_pixel_bits()
	@see	image_data(void*, unsigned int)
*/
JP2_Reader& rendered_pixel_bits (unsigned int bits);

/**	Get the rendered pixel precision.

	<b>N.B.</b>: The rendered pixel precision may be different from the
	source image {@link pixel_bits() pixel precision}.

	@return	The number of valid bits used by each rendered pixel. This
		will be zero until the JP2 source has been {@link open()
		opened}.
	@see	rendered_pixel_bits(unsigned int)
	@see	bytes_of_bits(unsigned int)
*/
inline unsigned int rendered_pixel_bits () const
	{return Rendered_Bits;}

/**	Get the number of bytes for each rendered pixel sample.

	@return	The number of bytes used to store each rendered pixel sample
		in one band.
	@see	rendered_pixel_bits()
*/
unsigned int rendered_pixel_bytes () const;

/**	Set the suggested rendering increment.

	The specified number of rendering increment lines is a suggestion to
	the source JPEG2000 codestream {@link render() renderer} of how many
	lines of the selected {@link image_region(const Rectangle&) image
	region} to render during incremental codestream decompression. The
	suggested rendering increment is used when determining the {@link
	effective_rendering_increment_lines() effective increment}.

	<b>N.B.</b>: The rendering increment is a <b>suggestion</b> to the
	codestream decompressor, which may render fewer or more lines - but
	always whole lines - in for each codestream decompression increment
	depending on the structure of the codestream. However, it will never
	render beyond the {@link rendered_region() rendered region} in effect
	at the time of image rendering.

	@param	The number of image lines to incrementally render that will
		be suggested to the rendering machinery. If zero, the effective
		increment will be the largest possible value given the current
		constraints.
	@return	This JP2_Reader.
	@see	rendering_increment_lines()
*/
inline JP2_Reader& rendering_increment_lines (unsigned int line_increment)
	{Rendering_Increment_Lines = line_increment; return *this;}

/**	Get the suggested rendering increment.

	@return	The number of lines to incrementally render. This will be
		zero until the JP2 source has been {@link open() opened} or a
		non-zero value has been specified by the user.
	@see	rendering_increment_lines(unsigned int)
*/
inline unsigned int rendering_increment_lines () const
	{return Rendering_Increment_Lines;}

/**	Get the effective rendering increment.

	When the JP2 source is {@link render() rendered} and the number of
	{@link rendering_increment_lines(unsigned int) suggested increment
	lines} has not been specified the number of {@link rendered_region()
	rendered region} lines that will fit in the {@link
	#DEFAULT_RENDERING_INCREMENT_BYTES} (rounded up to the nearest whole
	line) will be used. However, in no case will the effective rendering
	increment be less than one or greater than the height of the rendered
	region.

	@return	The rendering increment, in image lines, for the current
		image rendering characteristics. This will be zero if the JP2
		source is not {@link open() open}.
	@see	rendering_increment_lines(unsigned int)
*/
unsigned int effective_rendering_increment_lines () const;

/**	Set the number of processing threads used for decompression.

	@param	threads	The number of processing threads used for
		decompression. If zero, the value will be determined by the
		number of {@link processing_units() processing units} detected
		for the host system, which is the initial value.
	@return	This JP2_Reader.
	@see	processing_threads()
*/
JP2_Reader& processing_threads (unsigned int threads);

/**	Get the number of processing threads used for decompression.

	@return	The number of processing threads used for decompression.
	@see	processing_threads(unsigned int)
*/
inline unsigned int processing_threads () const
	{return Thread_Count;}

inline static void default_jpip_proxy (const std::string& server)
	{Default_JPIP_Proxy = server;}
inline static std::string default_jpip_proxy ()
	{return Default_JPIP_Proxy;}
inline JP2_Reader& jpip_proxy (const std::string& server)
	{JPIP_Proxy = server; return *this;}
inline std::string jpip_proxy () const
	{return JPIP_Proxy;}

inline static void default_jpip_cache_directory (const std::string& directory)
	{Default_JPIP_Cache_Directory = directory;}
inline static std::string default_jpip_cache_directory ()
	{return Default_JPIP_Cache_Directory;}
inline JP2_Reader& jpip_cache_directory (const std::string& directory)
	{JPIP_Cache_Directory = directory; return *this;}
inline std::string jpip_cache_directory () const
	{return JPIP_Cache_Directory;}

/**	Register a rendering monitor.

	The {@link #Rendering_Monitor} is called during {@link render()
	rendering} after each {@link rendering_increment_lines(unsigned int)
	increment of rendered source lines} has been decompressed as well as
	when the rendering of the current {@link image_region(const
	Rectange&) image region} has been completed.

	The Rendering_Monitor is an object with a notify function that
	identifies the JP2_Reader for which the event occured and provides
	information about the event. The function returns true if rendering
	should continue, or false if rendering should be discontinued.

	@param	monitor	The Rendering_Monitor to be notified on the completion
		of each rendering increment. If NULL no rendering notices will
		be provided.
	@return	This JP2_Reader.
	@see	rendering_monitor()
*/
inline JP2_Reader& rendering_monitor (Rendering_Monitor* monitor)
	{Monitor = monitor; return *this;}

/**	Get the Rendering_Monitor.

	@return	The Rendering_Monitor registered to receive rendering notices.
		This will be NULL if no Rendering_Monitor is currently registered.
	@see	rendering_monitor(Rendering_Monitor*)
*/
inline Rendering_Monitor* rendering_monitor () const
	{return Monitor;}

/**	Get the total number of image data bytes last rendered.

	At the beginning of each image data {@link render() rendering
	process}  the byte count is reset to zero, and the value returned
	from the rendering process is the same total byte count. However, the
	byte count is incrementally updated during the rendering process, so
	this method can be used to determine how much image data was rendered
	if an exception occurs during the rendering process.

	@return	The total number of image data bytes last rendered.
*/
inline unsigned long long bytes_rendered ()
	{return Bytes_Rendered;}

/*==============================================================================
	Reader Implementation

	This section declares the methods of the JP2_Reader interface that
	must be implemented by the subclasses that provide the rendering
	engines. Those methods that are not declared pure virtual provide
	assistance for common functionality but are still expected to have
	rendering engine implementations.
*/
/**	Clone the JP2_Reader.

	A copy of the implementing JP2_Reader is constructed.

	@return	A pointer to a copy of the implementing JP2_Reader.
*/
virtual JP2_Reader* clone () const = 0;

/**	Open a JP2 source.

	Normally the {@link JP2::reader(const std::string&) JP2 reader)
	factory function is used to instantiate and open an appropriate
	implementation of a JP2_Reader. However, if the particular subclass
	is constructed directly this method will invoke the open method for
	the subclass. If this method is invoked directly on an object of the
	JP2_Reader base class an exception will be thrown.

	@param	source	The meaning of this argument depends on the
		implementing subclass.
	@return	The ID for the opened source.
	@throws	JP2_Logic_Error	If the method is used directly on a JP2_Reader.
		Subclasses may throw other exceptions.
*/
virtual int open (const std::string& source) = 0;

/**	Test if the reader is open.

	@return	true if the implementing JP2_Reader subclass has been
		successfully opened on the JP2 source and not yet closed; false
		otherwise.
*/
virtual bool is_open () const = 0;

/**	Set the default JPIP request timeout that will be used with new
	JP2_JPIP_Reader objects.

	@param	timeout	The time, in seconds, to wait for a JPIP request to
		complete.
	@return	The previous default timeout.
	@see	default_request_timeout()
	@see	request_timeout(unsigned int timeout)
*/
static unsigned int default_JPIP_request_timeout (unsigned int timeout);

/**	Get the default JPIP request timeout that will be used with
	new JP2_JPIP_Reader objects.

	@return	The default timeout.
	@see	default_request_timeout(unsigned int timeout)
*/
inline static unsigned int default_JPIP_request_timeout ()
	{return Default_JPIP_Request_Timeout;}

/**	Set the maximum amount of time to wait for a JPIP request to complete.

	If a request does not complete before the timeout expires a JPIP_Timeout
	exception will be thrown.

	@param	timeout	The time, in seconds, to wait for a JPIP request to
		complete.
	@return	This JP2_Reader.
	@see	default_request_timeout(unsigned int timeout)
	@see	request_timeout()
*/
inline JP2_Reader& JPIP_request_timeout (unsigned int timeout)
	{JPIP_Request_Timeout = timeout; return *this;}

/**	Get the timeout for JPIP request completion.

	@return	The JPIP request timeout in seconds.
	@see	request_timeout(unsigned int)
*/
inline unsigned int JPIP_request_timeout () const
	{return JPIP_Request_Timeout;}

/**	Reconnect to the JP2 source.

	For a data source from a remote JPIP server, this method will
	attempt to reconnect to the server if the connection has been
	lost. The attempt will be repeated the number of {@link
	autoreconnect_retries() autoreconnect retries} specified.

	For the default implementation (i.e. for a local file data source)
	this method the return value depends on whether the reader {@link
	is_open() is open} or not.

	@retrun	true if the reader was reconnected to the JPIP server;
		false if all reconnect tries failed.
*/
virtual bool reconnect ();

/**	Set the default number of {@link reconnect() reconnect} tries
	that will automatically be done.

	@param	retries	The default number of times to attempt an automatic
		reconnection.
	@return	The previous default retries value.
*/
static int default_autoreconnect_retries (int retries);

/**	Get the default number of {@link reconnect() reconnect} tries
	that will automatically be done.

	@return	The default number of times to attempt an automatic
		reconnection.
*/
inline static int default_autoreconnect_retries ()
	{return Default_Autoreconnect_Retries;}

/**	Set the number of {@link reconnect() reconnect} tries
	that will automatically be done.

	@param	retries	The number of times to attempt an automatic
		reconnection. The initial value is determined by the {@link
		default_autoreconnect_retries default value}.
	@return	This JP2_Reader.
*/
inline JP2_Reader& autoreconnect_retries (int retries)
	{Autoreconnect_Retries = retries; return *this;}

/**	Get the number of {@link reconnect() reconnect} tries
	that will automatically be done.

	@return	The number of times to attempt an automatic reconnection. The
		initial value is determined by the {@link
		default_autoreconnect_retries default value}.
*/
inline int autoreconnect_retries () const
	{return Autoreconnect_Retries;}

/**	Tests if the reader has the information it needs to render.

	The {@link source() JP2 data source} must be {@link is_open() open}.

	If (@link user_buffer() user buffer} pixel {@link image_data(void**,
	unsigned long long*) image data} was specified then the buffer size
	must be sufficient to contain the image data to be rendered with the
	current rendering configuration. If image data storage is to be
	automatically provided then the amount required to render the
	selected {@link image_region(const Rectangle&) image region} must be
	smaller than the maximum possible allocation size.

	Implementing subclasses may have additional requirements to be
	ready for rendering.

	@param	report	A pointer to a string to which a report will be
		appended (if non-NULL) describing the reason for a false
		condition. No report will be provided if the condition is true. A
		report may contain several lines.
	@return	true if the reader is ready; false otherwise.
	@see	render()
*/
virtual bool ready (std::string* report = NULL) const;

/**	Set the effective rendering resolution level and image region.

	The {@link resolution_level(unsigned int) resolution level} and
	{@link image_region(const Rectangle&) image region} interact to
	determine the {@link rendered_region() rendered image region} so they
	are set together.

	<b.N.B.</b>: If the reader has not been {@link open() opened} nothing
	is done.

	The effective resolution level is limited to the range 1 - {@link
	resolution_levels() resolution levels} and applied as an input
	restriction on the codestream rendering machinery.

	If the image region is empty the entire {@link image_size() image
	size} is used as the selected {@link image_region() image region}.
	The dimensions of the selected image region are adjusted by the
	resolution level (divided by 2**(level - 1)), intersected with the
	full image size at the rendering resolution and the resulting effective
	image region is applied as an input restriction on the codestream
	rendering machinery. Both the effective image region and {@link
	rendered_region() rendered image region} are set. <b>N.B.</b>: If the
	selected image region does not intersect with the image size an empty
	effective image region will result.

	@param	resolution	The rendering resolution level.
	@param	region	The selected image area to be rendered relative to
		the full resolution image. This will be clipped to the full
		image size. <b>N.B.</b>: If the region is empty the entire image
		will be selected.
	@return	true if there was any change to the resolution or region;
		false otherwise. <b.N.B.</b>: If the data source is not open
		false is returned immediately.
	@throws	JP2_Exception	If their was a failure setting the resolution
		or region by an implementing subclass.
*/
virtual bool resolution_and_region
	(unsigned int resolution, const Rectangle& region) = 0;

/**	Render the image data.

	The reader is checked that it is {@link ready() ready}. Then the
	codestream for the current {@link rendered_region() rendered region}
	is acquired, decompressed and organized according to the current
	pixel data structure specifications into the rendered pixel data
	storage buffers. If a {@link rendering_monitor() rendering monitor}
	has been registered with the reader it is notified, as the data
	rendering progresses, after each {@link
	effective_rendering_increment_lines() rendering increment}.

	@return	A Cube indicating what was rendered.
	@throws	JP2_Logic_Error	If the reader is not ready().
	@throws	JP2_Out_of_Range	If insufficient memory is available to
		allocate the rendered image data buffers.
	@see	rendering_monitor(Rendering_Monitor*)
*/
virtual Cube render () = 0;

/**	Close access to the JP2 source.

	The JP2 source stream is closed and the rendering machinery resources
	associated with it are released.

	<b>N.B.</b>: The JP2 metadata describing the previously open source,
	if any, is not {@link JP2_Metadata::reset() reset} so it can still be
	queried; nor is the rendering configuration, including any {@link
	image_data(void**, unsigned long) image data} buffer, {@link reset()
	reset}. If the reader is subsequently {@link open(const std::string&)
	opened} on the same {@link JP2_Metadata::source_name() source} the
	same rendering configuration will be in effect after reopening the
	source, unless, of course, the reader is first reset. Opening a
	reader that has been closed on a different source will automatically
	result in a reader reset.

	It is safe to call this method on a reader that has already been
	closed.

	@param	force	Force closure of all connections to the source.
		Only used by a JP2_JPIP_Reader.
*/
virtual void close (bool force = false) = 0;

/**	Reset the reader to it's initial, default, configuration.

	All data members are reset to their empty, NULL or zero intial state
	with these exceptions: The {@link image_data (unsigned long long*)
	image data} buffer, if locally managed, is deleted; the {@link
	image_data_format() image data format} is set to the {@link
	default_image_data_format() default image data format}; the number of
	{@link processing_threads() processing threads} is set to the number
	of {@link processing_units() unless a non-zero THREAD_COUNT was
	defined at compile time; the {@link jpip_proxy() JPIP proxy} host is
	set to the {@link default_jpip_proxy{} default JPIP proxy}; the
	{@link jpip_cache_directory() JPIP cache directory} pathname is set
	to the {@link default_jpip_cache_directory() default JPIP cache
	directory}.

	The base JP2_Metadata is also {@link JP2_Metadata::reset() reset}.
*/
virtual void reset ();

/*============================================================================
	Helpers
*/
/**	Get the number of image data bytes in the current rendered image area.

	@return	The total size, in bytes, of the current rendered image area.
		This will be zero until the JP2 source has been {@link open()
		opened}.
	@see	rendered_region()
*/
unsigned long long rendered_image_bytes () const;

/**	Get the minimum image pixel data band buffer size.

	Given the current {@link rendered_region() rendered image size}
	and the pixel data structure specified by the {@link pixel_stride()
	pixel stride} and {@link line_stride() line stride}, the minimum
	buffer size is the amount of storage, in bytes, that must be
	allocated to a single {@link image_data(void**, unsigned
	long long) image data} buffer for rendering pixels. The pixel data
	buffers may be larger than the minimum. {@link render() Rendering}
	will not be done unless the buffer size is at least the minimum size.

	@return	The minimum number of image data buffer bytes required to
		accommodate pixel rendering. Will be zero if the source has not
		yet been {@link open(const std::string&) opened}.
*/
unsigned long long minimum_buffer_size () const;


protected:

/**	Disposition of rendered image data.

	During {@link render() rendering} source data is decompressed in
	{@link effective_rendering_increment_lines() increments}. For each
	rendering increment image data disposition occurs.

	If {@link swap_pixel_bytes(bool) byte swapping of multi-byte pixel
	samples} has been enabled data disposition will do this for the image
	data in the current rendering increment.

	Finally if a {@link #Rendering_Monitor} is registered it is notified
	of the image region that was rendered in the current decompression
	increment.

	@param	region	The current rendered region of image data relative to
		the rendered resolution grid. This region will be all or part of
		the image {@link rendered_region() region to be rendered}.
	@param	status	A rendering {@link #Rendering_Monitor::Status} code
		that indicates the context in which the notification is being
		sent.
	@param	message	A message associated with the notification event.
		This may be empty.
	@return	true if rendering is to be continued; false if it is to be
		discontinued. If a Rendering_Monitor is called its return value
		is used; otherwise true is returned by default.
	@see	rendering_monitor(Rendering_Monitor*)
*/
bool data_disposition
	(Rendering_Monitor::Status status, const std::string& message,
		const Cube& region_rendered, const Cube& image_region_rendered);

/**	An image data buffer is allocated.

	If the {@link image_data(void**, unsigned long long) image data}
	buffers are {@link user_buffer() user provided}, nothing is done.
	Otherwise a data buffer for each {@link image_bands() image band} is
	provided that is at least the {@link minimum_buffer_size() minimum
	buffer size}. Previously allocated data buffers may be reused;
	however, if the new buffer size is more than 1MB smaller than the
	previous buffer size reallocation occurs to shrink the amount of
	memory being used.

	@throws	length_error	If the buffers are locally allocated and the
		{@link minimum_buffer_size() minimum buffer size} is greater than
		the maximum amount that can be allocated using a size_t data type
		value.
	@see	ready()
*/
void allocate_image_data_buffer ();


private:

/**	Allocate the Image_Data array.

	If the Image_Data array has already been allocated nothing is done.

	If the number of {@link image_bands() image bands} is zero false is
	returned without doing anything.

	The Image_Data array of pointers to pixel data storage is allocated
	to have a size that is the number of image bands <i>plus 1</i>. The
	additional entry is provided for the pointer to a locally managed
	image data buffer; this will be NULL if the image data is owned by
	the user. All Image_Data array entries are initialized to NULL.

	@return	true if the Image_Data array is allocated or had already
		been allocated; false if there are no image bands (which suggests
		that the data source has not been {@link open(const std::string&)
		opened}.
*/
bool allocate_data_buffers_array ();

/**	Delete a locally managed image data buffer.

	If no array of pointers to pixel data storage has been {@link
	allocate_data_buffers_array() allocated} or the last, {@link
	image_bands() image bands} index, entry in the array is NULL, nothing
	is done; i.e. in this case the image data buffers are {@link
	user_buffer() user specified}.

	For locally managed pixel data storage the last entry in the array of
	image data pointers is for the {@link allocate_image_data_buffer()
	locally allocated buffer}. This buffer is deleted and all entries in
	the array of pointers are set to NULL.
*/
void delete_local_data_buffer ();

/*==============================================================================
	Data
*/
protected:

/**	Flags if the rendering configuration has been initialized.
	Used by implementing subclasses.
*/
bool
	Rendering_Configuration_Initialized;

/**	Image data buffers array.

	<b>N.B.</b>: The array of pointers to pixel data storage is
	{@link allocate_data_buffers_array() allocated} to have a
	size that is the number of {@link image_bands() image bands}
	<i>plus 1</i>. The additional entry is provided for the pointer to a
	locally managed image data buffer; this will be NULL if the image
	data is owned by the user.
*/
void
	**Image_Data;

//!	The number of bytes in the Image_Data buffer (zero means unknown).
unsigned long long
	Buffer_Size;

/**	Flags if the Image_Data buffers are owned by the user vs managed locally.

	This is, unfortunately, redundant with the use of the last Image_Data
	entry being NULL when the buffers are locally managed. However, the
	last Image_Data entry can also be NULL because the locally managed
	buffer has not yet been allocated. So, to avoid confusing complex
	logic it is simpler, and safer, to just use the User_Buffer flag.
*/
bool
	User_Buffer;

//!	Distance, in samples, between horizontally adjacent pixels.
unsigned int
	Pixel_Stride;

//!	Distance, in pixels, between vertically adjacent pixels.
unsigned int
	Line_Stride;

//!	Type of image data format structure.
Image_Data_Format
	Data_Format;

//!	Map of image bands to be rendered.
Band_Map
	Rendered_Bands;

/**	Image region on the full resolution grid of the source to be rendered.
	Its Depth is the number of bands to be rendered (also in Rendered_Bands).
*/
Cube
	Image_Region;

/**	Resolution level to render.

	<b>N.B.</b>: The resolution level is one more than the JPEG2000
	decomposition level; e.g. level 1 is full resolution, 2 is half
	resolution, etc.
*/
unsigned int
	Resolution_Level;

//!	Rendered image region after applying Resolution_Level to Image_Region.
Cube
	Rendered_Region;

//!	Whether pixel bytes should be reordered when rendered.
bool
	Swap_Pixel_Bytes;

//!	Rendered pixel precision in bits.
unsigned int
	Rendered_Bits;

//!	Suggested number of output image lines in each rendering increment.
unsigned int
	Rendering_Increment_Lines;

//!	Decompression processing thread count.
unsigned int
	Thread_Count;

//	JPIP_Client configuration options:

//!	The default JPIP request timeout (seconds).
static unsigned int
	Default_JPIP_Request_Timeout;
//!	The JPIP_Client request timeout (seconds).
unsigned int
	JPIP_Request_Timeout;
static std::string
	Default_JPIP_Proxy,
	Default_JPIP_Cache_Directory;
std::string
	JPIP_Proxy,
	JPIP_Cache_Directory;


Rendering_Monitor
	*Monitor;

static int
	Default_Autoreconnect_Retries;
int
	Autoreconnect_Retries;

unsigned long long
	Bytes_Rendered;

};	//	Class JP2_Reader

/*=*****************************************************************************
	Utility
*/
/**	Represent a value in magnitude form.

	The magnitude representation of the value will be reduced to a
	floating point number less than 1024 with up to three decimal
	place precision plus a 'K' (kilo; 1024), 'M' (mega; 1024**2),
	'G' (giga; 1024**3), 'T' (tera; 1024**4), or ' ' (the value is
	less than 1024) suffix indicating its magnitude.

	@param	value	An integer value.
	@return	A string representation of the value magnitude.
*/
std::string magnitude (unsigned long long value);

/**	Get the number of processing units detected for the host system.

	The number of processing units may be greater than the number of
	CPU cores available on the host system. If, for example, the cores
	provide hyperthreading capability there can be two processing units
	per core.

	@return	The number of processing units dectected for the host system.
*/
unsigned int processing_units ();


}	//	namespace UA::HiRISE
#endif
