\chapter{Image I/O API Helper Classes}
\label{chap:imageioapi}
\index{Image I/O API Helper Classes|(}



\section{Data Type Descriptions: {\cf TypeDesc}}
\label{sec:dataformats}
\label{sec:TypeDesc}
\index{data formats}

There are two kinds of data that are important to \product:

\begin{itemize}
\item \emph{Internal data} is in the memory of the computer, used by an
  application program.
\item \emph{Native file data} is what is stored in an image file itself
  (i.e., on the ``other side'' of the abstraction layer that \product
  provides).
\end{itemize}

Both internal and file data is stored in a particular \emph{data format}
that describes the numerical encoding of the values.  \product
understands several types of data encodings, and there is 
a special class, \TypeDesc, that allows their enumeration and
is described in the header file {\cf OpenImageIO/typedesc.h}.
A \TypeDesc describes a base data format type, aggregation into simple
vector and matrix types, and an array length (if
it's an array).

The remainder of this section describes the C++ API for \TypeDesc.
See Section~\ref{sec:pythontypedesc} for the corresponding Python
bindings.

\TypeDesc supports the following base data format types, given by the
enumerated type {\cf BASETYPE}:

\medskip

\begin{tabular}{l p{4.75in}}
{\cf UINT8} &  8-bit integer values ranging from
  0..255, corresponding to the C/C++ {\cf unsigned char}. \\
{\cf INT8} &  8-bit integer values ranging from
  -128..127, corresponding to the C/C++ {\cf char}. \\
{\cf UINT16} &  16-bit integer values ranging
  from 0..65535, corresponding to the C/C++ {\cf unsigned short}. \\
{\cf INT16} &  16-bit integer values ranging
  from -32768..32767, corresponding to the C/C++ {\cf short}. \\
{\cf UINT} &  32-bit integer values,
  corresponding to the C/C++ {\cf unsigned int}. \\
{\cf INT} &  signed 32-bit integer values, corresponding
  to the C/C++ {\cf int}. \\
{\cf UINT64} &  64-bit integer values,
  corresponding to the C/C++ {\cf unsigned long long} (on most architectures). \\
{\cf INT64} &  signed 64-bit integer values, corresponding
  to the C/C++ {\cf long long} (on most architectures). \\
{\cf FLOAT} &  32-bit IEEE floating point values,
  corresponding to the C/C++ {\cf float}. \\
{\cf DOUBLE} &  64-bit IEEE floating point values,
  corresponding to the C/C++ {\cf double}. \\
{\cf HALF} &  16-bit floating point values in the format
  supported by OpenEXR and OpenGL.
\end{tabular}
\medskip

\noindent A \TypeDesc can be constructed using just this information, either as
a single scalar value, or an array of scalar values:

\apiitem{{\ce TypeDesc} (BASETYPE btype) \\
{\ce TypeDesc} (BASETYPE btype, int arraylength)}
Construct a type description of a single scalar value of the given base
type, or an array of such scalars if an array length is supplied.  For
example, {\cf TypeDesc(UINT8)} describes an unsigned 8-bit integer,
and {\cf TypeDesc(FLOAT,7)} describes an array of 7 32-bit float values.
Note also that a non-array \TypeDesc may be implicitly constructed from
just the {\cf BASETYPE}, so it's okay to pass a {\cf BASETYPE}
to any function parameter that takes a full \TypeDesc.
\apiend


\medskip
\noindent In addition, \TypeDesc supports certain aggregate types, described
by the enumerated type {\cf AGGREGATE}:

\medskip
\begin{tabular}{l p{4.75in}}
{\cf SCALAR} & a single scalar value (such as a raw {\cf int}
  or {\cf float} in C).  This is the default. \\
{\cf VEC2} & two values representing a 2D vector. \\
{\cf VEC3} & three values representing a 3D vector. \\
{\cf VEC4} & four values representing a 4D vector. \\
{\cf MATRIX33} & nine values representing a $3 \times 3$ matrix. \\
{\cf MATRIX44} & sixteen values representing a $4 \times 4$ matrix.
\end{tabular}
\medskip

\noindent And optionally, a hint about the semantics of the data,
described by the enumerated type {\cf VECSEMANTICS}:\footnote{It's
unfortunately called {\cf VECSEMANTICS} because it used to be used
strictly for 3-vectors. If we were to do it over again, it would just
be {\cf SEMANTICS}.}

\medskip
\begin{tabular}{p{1in} p{4.25in}}
{\cf NOSEMANTICS} & nothing special known. \\
{\cf COLOR} & indicates a vector that is intended to represent
  a ``color,'' not a spatial
  quantity (and of course therefore does not undergo a transformation). \\
{\cf POINT} &  indicates a vector that represents a
  spatial position and should be transformed by a $4 \times 4$ matrix
  as if it had a 4th component of 1. \\
{\cf VECTOR} &  indicates a vector that represents a
  spatial direction and should be transformed by a $4 \times 4$ matrix
  as if it had a 4th component of 0. \\
{\cf NORMAL} &  indicates a vector that represents a
  surface normal and should be transformed like a vector, but using the
  inverse-transpose of a $4 \times 4$ matrix. \\
{\cf TIMECODE} & indicates an {\cf int[2]} representing the standard
  4-byte encoding of an SMPTE timecode. \\
{\cf KEYCODE} & indicates an {\cf int[7]} representing the standard
  28-byte encoding of an SMPTE keycode. \\
{\cf RATIONAL} & indicates an {\cf VEC2} representing a rational
  number {\cf val[0] / val[1]}. \\
\end{tabular}
\medskip

\noindent These can be combined to fully describe a complex type:

\apiitem{{\ce TypeDesc} (BASETYPE btype, AGGREGATE agg=SCALAR, VECSEMANTICS
xform=NOSEMANTICS)  \\
{\ce TypeDesc} (BASETYPE btype, int arraylen) \\
{\ce TypeDesc} (BASETYPE btype, AGGREGATE agg, int arraylen) \\
{\ce TypeDesc} (BASETYPE btype, AGGREGATE agg, VECSEMANTICS xform, int arraylen)
}
Construct a type description of an aggregate (or array of aggregates),
with optional vector transformation semantics.  For example, 
{\cf TypeDesc(HALF,COLOR)} describes an aggregate of 3 16-bit floats
comprising a color, and {\cf TypeDesc(FLOAT,VEC3,POINT)} describes 
an aggregate of 3 32-bit floats comprising a 3D position.

Note that aggregates and arrays are different.  A {\cf
  TypeDesc(FLOAT,3)} is an array of three floats, a {\cf
  TypeDesc(FLOAT,COLOR)} is a single 3-channel color comprised of
floats, and {\cf TypeDesc(FLOAT,3,COLOR)} is an array of 3 color values,
each of which is comprised of 3 floats.
\apiend

\apiitem{{\ce TypeDesc} (string_view typestring)}
Construct a type description based on a string. For example,

\begin{code}
    TypeDesc("int") == TypeDesc(TypeDesc::INT)       // C++ int32_t
    TypeDesc("float") == TypeDesc(TypeDesc::FLOAT)   // C++ float
    TypeDesc("float[4]") == TypeDesc(TypeDesc::FLOAT, 4)  // array
    TypeDesc("point") == TypeDesc(TypeDesc::FLOAT, TypeDesc::POINT)
    TypeDesc("uint16") == TypeDesc(TypeDesc::UINT16)   // C++ uint16_t
\end{code}
\apiend

\bigskip

A number of {\cf static constexpr TypeDesc} aliases for common types exist
in the outer {\cf OpenImageIO} scope:

\begin{quote}
{\cf
TypeUnknown
TypeFloat
TypeColor
TypePoint
TypeVector
TypeNormal \\
TypeMatrix33
TypeMatrix44
TypeMatrix
TypeHalf \\
TypeInt
TypeUInt
TypeInt16
TypeUInt16
TypeInt8
TypeUInt8 \\
TypeString
TypeTimeCode
TypeKeyCode
TypeFloat4
TypeRational
}
\end{quote}

The only types commonly used to store \emph{pixel values} in image files
are scalars of {\cf UINT8}, {\cf UINT16}, {\cf FLOAT}, and {\cf HALF}
(the last only used by OpenEXR, to the best of our knowledge).

Note that the \TypeDesc (which is also used for applications other
than images) can describe many types not used by
\product.  Please ignore this extra complexity; only the above simple types are understood by
\product as pixel storage data types, though a few others, including
{\cf STRING} and {\cf MATRIX44} aggregates, are occasionally used for
\emph{metadata} for certain image file formats (see
Sections~\ref{sec:imageoutput:metadata}, \ref{sec:imageinput:metadata},
and the documentation of individual ImageIO plugins for details).


\newpage

\section{Non-owning string views: {\cf string_view}}
\label{sec:stringview}
\indexapi{string_view}

A \stringview a non-owning, non-copying, non-allocating reference to a
sequence of characters.  It encapsulates both a character pointer and a
length.

A function that takes a string input (but does not need to alter the string
in place) may use a \stringview parameter and accept input that is any of
{\cf char*} (C string), string literal (constant char array), a {\cf
std::string} (C++ string), or OIIO \ustring.  For all of these cases, no
extra allocations are performed, and no extra copies of the string  contents
are performed (as they would be, for example, if the function took a const
{\cf std::string\&} argument but was passed a {\cf char*} or string
literal).

Furthermore, a function that returns a copy or a substring of one of its
inputs (for example, a {\cf substr()}-like function) may return a \stringview
rather than a {\cf std::string}, and thus generate its return value without
any allocation or copying. Upon assignment to a {\cf std::string} or \ustring,
it will properly auto-convert.

There are two important caveats to using this class:
\begin{enumerate}
\item The \stringview merely refers to characters owned by another string,
   so the \stringview may not be used outside the lifetime of the string
   it refers to. Thus, \stringview is great for parameter passing, but
   it's not a good idea to use a \stringview to store strings in a data
   structure (unless you are really sure you know what you're doing).
\item Because the run of characters that the \stringview refers to may not
   be 0-terminated, it is important to distinguish between the {\cf data()}
   method, which returns the pointer to the characters, and the {\cf c_str()}
   method, which is guaranteed to return a valid C string that is
   0-terminated. Thus, if you want to pass the contents of a \stringview
   to a function that expects a 0-terminated string (say, fopen), you
   must call {\cf fopen(my_string_view.c_str()}).  Note that the usual case
   is that the \stringview does refer to a 0-terminated string, and in
   that case c_str() returns the same thing as data() without any extra
   expense; but in the rare case that it is not 0-terminated, c_str()
   will incur extra expense to internally allocate a valid C string.
\end{enumerate}

\apiitem{{\ce string_view} (const char *chars) \\
{\ce string_view} (const char *chars, size_t length) \\
{\ce string_view} (const std::string \&str) \\
{\ce string_view} (ustring ustr)}
Constructs a \stringview.  The \stringview doesn't have its own copy of the
characters, so don't use the \stringview after the original string has been
destroyed or altered.

Note that the version that takes a {\cf const char*} but not a length will
automatically take the {\cf strlen(chars)} to determine the length.  (All
the other constructors can deduce the length without walking through all
of the characters.)
\apiend

\apiitem{const char* string_view::{\ce data} () \\
size_t string_view::{\ce size} ()}
The raw pointer to the characters (not necessarily 0-terminated!)
and the length of the \stringview.
\apiend

\apiitem{const char* string_view::{\ce c_str} ()}
Return a 0-terminated {\cf char*} version of the \stringview (a proper C
string).
\apiend

\apiitem{std::string (string_view sr) \\
ustring (string_view sr)}
Automatic constructions of C++ {\cf std::string} or OIIO \ustring from
a \stringview.
\apiend

\smallskip
\noindent Additionally, a large portion of the usual API for {\cf std::string}
is mimicked by \stringview.  Please consult the public {\cf string_view.h}
header file for full details, if you wish to use \stringview in your own
code.


\section{Non-owning array views: {\cf span} / {\cf cspan}}
\label{sec:span}
\indexapi{span} \index{cspan} \indexapi{array_view}

{\bf Note:} {\cf span} and {\cf array_view} are synonyms. The new preferred name is
{\cf span}, in keeping with the equivalent template that has been accepted into
future C++ standards. But the old name {\cf array_view} is still accepted. Over
time, we will eventually update the documentation to reflect the change.
% DEPRECATED 2.0

A {\cf template span<typename T>} is a non-owning, non-copying,
non-allocating reference to an array of contiguous {\cf T} objects.  It
encapsulates both a pointer and a length, and thus is a safer way of passing
pointers around (because the function called knows how long the array is). A
function that might ordinarily take a {\cf T*} and a length could instead
just take a {\cf span<T>}.

A non-mutable (i.e., read-only) reference would be {\cf span<const T>}.
Thus, a function that might ordinarily take a {\cf const T*} and a length
could instead take a {\cf span<const T>}. As a shorthand, {\cf cspan<T>} is
defined as a synonym to {\cf span<const T>}, they are equivalent.

For historical reasons, the deprecated name {\cf array_view} is accepted as a
synonym for {\cf span}. (But will eventually be removed.)

A {\cf span} may be initialized explicitly from a pointer and length, by
initializing with a {\cf std::vector<T>}, or by initalizing with a constant
(treated as an array of length 1). For all of these cases, no extra
allocations are performed, and no extra copies of the array contents are
made.

Important caveat: The {\cf span} merely refers to items owned by another
array, so the {\cf span} should not be used outside the lifetime of the
array it refers to. Thus, {\cf span} is great for parameter passing, but
it's not a good idea to use a {\cf span} to store strings in a data
structure (unless you are really sure you know what you're doing).

\noindent Commonly used {\cf span} methods include:

\apiitem{{\ce span<T>} (T *data, ptrdiff_t len) \\
{\ce span<T>} (T \&data) \\
{\ce span<T>} (T *begin, T *end) \\
{\ce span<T>} (std::vector<T> \&vec) \\
{\ce span<T>} (std::array<T,N> \&vec) \\
{\ce span<T>} (T[N]) }
Constructs a {\cf span}.  The {\cf span} doesn't have its own copy of the
array elements, so don't use the {\cf span} after the original array has been
destroyed or altered.
\apiend

\apiitem{T* span<T>::{\ce data} () \\
ptrdiff_t span<T>::{\ce size} ()}
The raw pointer to the array, and its length.
\apiend

\apiitem{T\& span<T>::operator{\ce []} (ptrdiff_t pos)}
References a single element of the {\cf span}.
\apiend

\smallskip
\noindent Please consult the public {\cf span.h}
header file for full details, if you wish to use {\cf span} in your own
code.


\section{Efficient unique strings: {\cf ustring}}
\label{sec:ustring}
\indexapi{ustring}

A \ustring is an alternative to {\cf char*} or {\cf std::string} for storing
strings, in which the character sequence is stored uniquely.  If there are
many copies of the same \ustring, they all point to the same canonical
characters, which themselves are stored only once. This allows \ustring's to
be assigned to one another with only the copy of a pointer assignment (not
allocation or copying of characters), and for {\cf ==} and {\cf !=}
comparisons of two \ustring values for only the cost of comparing the
pointers (not examining the characters).

\OpenImageIO uses \ustring in a few select places, where string
assignment/copy and equality/inequality are the dominant string operation
and we want them to be the same low cost as a simple pointer assignment or
comparison.  (This primarily comes into play for the \ImageCache and
\TextureSystem, where we refer to images by their filenames and want
very fast lookups.)

Please consult the public header {\cf ustring.h} for details, especially if
you want to use \ustring extensively in your own code. But here are the most
important details to know if you are calling the \OpenImageIO functions that
take \ustring parameters:

\apiitem{{\ce ustring} (const char *chars) \\
{\ce ustring} (const char *chars, size_t length) \\
{\ce ustring} (const std::string \&str) \\
{\ce ustring} (string\_view sref)}
Constructs a \ustring from a C string ({\cf char*}), C++ {\cf std::string},
or a \stringview.
\apiend

\apiitem{const char* ustring::{\ce c_str} () \\
const std::string\& ustring::{\ce string()} \\
string\_view ustring::{\ce operator string\_view}()}
Convert a \ustring to a 0-terminated C string, a C++ {\cf std::string}, or
a {\cf string_view}.  All of these are extremely inexpensive.
\apiend

\apiitem{static ustring ustring::{\ce sprintf} (const char* fmt, ...)}
Create a formatted \ustring using the C printf formatting notation
(e.g., \qkw{\%d \%s}, akin to C {\cf sprintf()}, except that this one
uses variadic templates and is type-safe).
\apiend



\section{Helper: \ROI}
\label{sec:ROI}
\indexapi{ROI}
\index{region of interest}

\ROI is a small helper struct that describes a rectangular region of
pixels of an image (and a channel range).  An \ROI holds the following
data members:

\apiitem{int xbegin, xend, ybegin, yend, zbegin, zend; \\
int chbegin, chend;}
Describes the $x, y, z$ range of the region.  The {\cf end} values are
\emph{exclusive}; that is, ({\cf xbegin, ybegin, zbegin}) is the first
pixel included in the range, ({\cf xend-1, yend-1, zend-1}) is the last
pixel included in the range, and ({\cf xend, yend, zend}) is \emph{one
past the last pixel} in each dimension.

Similarly, {\cf chbegin} and {\cf chend} describe a range of channels:
{\cf chbegin} is the first channel, {\cf chend} is \emph{one past the last
channel}.
\apiend

\smallskip

\noindent \ROI has the following member functions and friends:

\smallskip

\apiitem{{\ce ROI} ()}
A default-constructed \ROI has an \emph{undefined} region, which
is interpreted to mean all valid pixels and all valid channels of
an image.
\apiend

\apiitem{bool ROI::{\ce defined} () const}
Returns {\cf true} if the \ROI is defined, having a specified region,
or {\cf false} if the \ROI is undefined.
\apiend

\apiitem{static ROI ROI::{\ce All} ()}
Returns an undefined \ROI, which is interpreted to mean all valid pixels
and all valid channels of an image.
\apiend

\apiitem{int ROI::{\ce width} () const \\
int ROI::{\ce height} () const \\
int ROI::{\ce depth} () const}
Returns the width, height, and depth, respectively, of a defined region.
These do not return sensible values for an \ROI that is not {\cf defined()}.
\apiend

\apiitem{imagesize_t ROI::{\ce npixels} () const}
For an \ROI that is {\cf defined()}, returns the total number of pixels
included in the region, or {\cf 0} for an undefined \ROI.
\apiend

\apiitem{imagesize_t ROI::{\ce nchannels} () const}
For an \ROI that is {\cf defined()}, returns the number of channels
in the channel range.
\apiend

\apiitem{bool ROI::{\ce contains} (int x, int y, int z=0, int ch=0) const}
Returns {\cf true} if the ROI contains the coordinate.
\apiend

\apiitem{bool ROI::{\ce contains} (const ROI \&other) const}
Returns {\cf true} if the ROI {\cf other} is entirel contained within
this ROI.
\apiend

\apiitem{ROI {\ce roi_union} (const ROI \&A, const ROI \&B) \\
ROI {\ce roi_intersection} (const ROI \&A, const ROI \&B)}
Returns the union of two \ROI's (an \ROI that is exactly big enough
to include all the pixels of both individual \ROI's) or intersection
of two \ROI's (an \ROI that contains only the pixels that are contained
in \emph{both} \ROI's).
\apiend

\apiitem{ROI {\ce get_roi} (const ImageSpec \&spec) \\
ROI {\ce get_roi_full} (const ImageSpec \&spec)}
Return the ROI describing {\cf spec}'s pixel data window (the {\cf x, y, z,
width, height, depth} fields)
or the full (display) window (the {\cf full_x, full_y, full_z,
full_width, full_height, full_depth} fields), respectively.
\apiend

\apiitem{void {\ce set_roi} (const ImageSpec \&spec, const ROI \&newroi) \\
void {\ce set_roi_full} (const ImageSpec \&spec, const ROI \&newroi)}
Alters the {\cf spec} so to make its pixel data window 
or the full (display) window match {\cf newroi}.
\apiend


\newpage

\section{Image Specification: {\cf ImageSpec}}
\label{sec:ImageSpec}
\indexapi{ImageSpec}

An \ImageSpec is a structure that describes the complete
format specification of a single image.  It contains:

\begin{itemize}
\item The image resolution (number of pixels) and origin. This specifies
  what is often called the ``pixel data window.''
\item The full size and offset of an abstract ``full'' or ``display''
  window. Differing full and data windows can indicate that the pixels
  are a crop region or a larger image, or contain overscan pixels.
\item Whether the image is organized into \emph{tiles}, and if so, the
  tile size.
\item The \emph{native data format} of the pixel values (e.g., float, 8-bit
  integer, etc.).
\item The number of color channels in the image (e.g., 3 for RGB
  images), names of the channels, and whether any particular channels
  represent \emph{alpha} and \emph{depth}.
\item A user-extensible (and format-extensible) list of any other
  arbitrarily-named and -typed data that may help describe the image or
  its disk representation.
\end{itemize}

The remainder of this section describes the C++ API for \ImageSpec.
See Section~\ref{sec:pythonimagespec} for the corresponding Python
bindings.

\subsection{\ImageSpec Data Members}

The \ImageSpec contains data fields for the values that are
required to describe nearly any image, and an extensible list of
arbitrary attributes that can hold metadata that may be user-defined or
specific to individual file formats.  Here are the hard-coded data
fields:

\apiitem{int width, height, depth \\
int x, y, z}

{\cf width, height, depth} are the size of the data of this image, i.e.,
the number of pixels in each dimension.  A {\cf depth} greater than 1
indicates a 3D ``volumetric'' image.

{\cf x, y, z} indicate the \emph{origin} of the pixel data of the image.
These default to (0,0,0), but setting them differently may indicate that
this image is offset from the usual origin.

Therefore the pixel data are defined over pixel coordinates
[{\cf x} ... {\cf x+width-1}] horizontally, 
[{\cf y} ... {\cf y+height-1}] vertically, 
and [{\cf z} ... {\cf z+depth-1}] in depth.
\apiend

\apiitem{int full_width, full_height, full_depth \\
int full_x, full_y, full_z}

These fields define a ``full'' or ``display'' image window over the
region [{\cf full_x} ... {\cf full_x+full_width-1}] horizontally, 
[{\cf full_y} ... {\cf full_y+full_height-1}] vertically, 
and [{\cf full_z} ... {\cf full_z+full_depth-1}] in depth.

Having the full display window different from the pixel data window can
be helpful in cases where you want to indicate that your image is a
\emph{crop window} of a larger image (if the pixel data window is a
subset of the full display window), or that the pixels include
\emph{overscan} (if the pixel data is a superset of the full display
window), or may simply indicate how different non-overlapping images
piece together.
\apiend

\apiitem{int tile_width, tile_height, tile_depth}
If nonzero, indicates that the image is stored on disk organized into
rectangular \emph{tiles} of the given dimension.  The default of 
(0,0,0) indicates that the image is stored in scanline order, rather
than as tiles.
\apiend

\apiitem{int nchannels}
The number of \emph{channels} (color values) present in each pixel of
the image.  For example, an RGB image has 3 channels.
\apiend

%\newpage
%\vspace{24pt}  % make some space

\apiitem{TypeDesc format \\[0.5ex]
std::vector<TypeDesc> channelformats}
Describes the native format of the pixel data values themselves, as a
\TypeDesc (see \ref{sec:TypeDesc}).  Typical values would be 
{\cf TypeDesc::UINT8} for 8-bit unsigned values, {\cf TypeDesc::FLOAT}
for 32-bit floating-point values, etc.

If all channels of the image have the same data format, that will
be described by {\cf format} and {\cf channelformats} will be empty
(zero length).

If there are different data formats for each channel, they will be
described in the {\cf channelformats} vector, and the {\cf format} field
will indicate a single default data format for applications that don't
wish to support per-channel formats (usually this will be the format
of the channel that has the most precision).
\apiend

\apiitem{std::vector<std::string> channelnames}
The names of each channel, in order.  Typically this will be \qkw{R},
\qkw{G},\qkw{B}, \qkw{A} (alpha), \qkw{Z} (depth), or other arbitrary
names.
\apiend

\apiitem{int alpha_channel}
The index of the channel that represents \emph{alpha} (pixel coverage
and/or transparency).  It defaults to -1 if no alpha channel is present,
or if it is not known which channel represents alpha.
\apiend

\apiitem{int z_channel}
The index of the channel that respresents \emph{z} or \emph{depth} (from
the camera).  It defaults to -1 if no depth channel is present, or if it
is not know which channel represents depth.
\apiend

\apiitem{bool deep}
If {\cf true}, this indicates that the image describes contains ``deep''
data consisting of multiple samples per pixel.  If {\cf false}, it's an
ordinary image with one data value (per channel) per pixel.
\apiend

\apiitem{ParamValueList extra_attribs}
A list of arbitrarily-named and arbitrarily-typed additional attributes
of the image, for any metadata not described by the hard-coded fields
described above.  This list may be manipulated with the {\cf
attribute()} and {\cf find_attribute()} methods.
\apiend

\subsection{\ImageSpec member functions}
\label{sec:ImageSpecMemberFuncs}

\noindent \ImageSpec contains the following methods that
manipulate format specs or compute useful information about images given
their format spec:

\apiitem{{\ce ImageSpec} (int xres, int yres, int nchans, TypeDesc fmt = UINT8)}
Constructs an \ImageSpec with the given $x$ and $y$ resolution, number
of channels, and pixel data format.

All other fields are set to the obvious defaults -- the image is an
ordinary 2D image (not a volume), the image is not offset or a crop of a
bigger image, the image is scanline-oriented (not tiled), channel names
are ``R'', ``G'', ``B,'' and ``A'' (up to and including 4 channels,
beyond that they are named ``channel \emph{n}''), the fourth channel (if
it exists) is assumed to be alpha, and values are assumed to be linear.
\apiend

\apiitem{{\ce ImageSpec} (const ROI \&roi, TypeDesc fmt = TypeDesc::UINT8)}
Constructs an \ImageSpec whose dimensions (both data and ``full'') and
number of channels are given by the \ROI (\ref{sec:ROI}), pixel data type
by {\cf fmt}, and other fields are set to their default values.
\apiend

\apiitem{void {\ce set_format} (TypeDesc fmt)}
Sets the format as described, and clears any per-channel format information
in {\cf channelformats}.
\apiend

\apiitem{void {\ce default_channel_names} ()}
Sets the {\cf channelnames} to reasonable defaults for the number of
channels.  Specifically, channel names are set to ``R'', ``G'', ``B,''
and ``A'' (up to and including 4 channels, beyond that they are named
``channel\emph{n}''.
\apiend

\apiitem{size_t {\ce channel_bytes} () const}
Returns the number of bytes comprising each channel of each pixel (i.e.,
the size of a single value of the type described by the {\cf format} field).
\apiend

\apiitem{size_t {\ce channel_bytes} (int chan, bool native=false) const}
Returns the number of bytes needed for the single specified
channel.  If native is {\cf false} (default), compute the size of one
channel of {\cf this->format}, but if native is {\cf true}, compute the size
of the channel in terms of the ``native'' data format of that
channel as stored in the file.
\apiend

\apiitem{size_t {\ce pixel_bytes} (bool native=false) const}
Returns the number of bytes comprising each pixel (i.e. the number of
channels multiplied by the channel size).

If {\cf native} is true, this will be the sum of all the per-channel
formats in {\cf channelformats}.  If {\cf native} is false (the
default), or if all channels use the same format, this will simply be
the number of channels multiplied by the width (in bytes) of the {\cf format}.
\apiend

\apiitem{size_t {\ce pixel_bytes} (int chbegin, int chend, bool native=false) const}
Returns the number of bytes comprising the range of channels 
  $[${\cf chbegin}, {\cf chend}$)$ for each pixel.

If {\cf native} is true, this will be the sum of the per-channel
formats in {\cf channelformats} (for the given range of channels).  
If {\cf native} is false (the
default), or if all channels use the same format, this will simply be
the number of channels multiplied by the width (in bytes) of the {\cf format}.
\apiend

\apiitem{imagesize_t {\ce scanline_bytes} (bool native=false) const}
Returns the number of bytes comprising each scanline,
i.e., \\ {\cf pixel_bytes(native) * width} \\
This will return {\cf std::numeric_limits<imagesize_t>::max()} in the event
of an overflow where it's not representable in an {\cf imagesize_t}.
\apiend

\apiitem{imagesize_t {\ce tile_pixels} () const}
Returns the number of tiles comprising an image tile (if it's a tiled image).
This will return {\cf std::numeric_limits<imagesize_t>::max()} in the event
of an overflow where it's not representable in an {\cf imagesize_t}.
\apiend

\apiitem{imagesize_t {\ce tile_bytes} (bool native=false) const}
Returns the number of bytes comprising an image tile (if it's a tiled
image), i.e., \\ {\cf pixel_bytes(native) * tile_width * tile_height * tile_depth } \\
This will return {\cf std::numeric_limits<imagesize_t>::max()} in the event
of an overflow where it's not representable in an {\cf imagesize_t}.
\apiend

\apiitem{imagesize_t {\ce image_pixels} () const}
Returns the number of pixels comprising an entire image image of these dimensions.
This will return {\cf std::numeric_limits<imagesize_t>::max()} in the event
of an overflow where it's not representable in an {\cf imagesize_t}.
\apiend

\apiitem{imagesize_t {\ce image_bytes} (bool native=false) const}
Returns the number of bytes comprising an entire image of these
dimensions, i.e., \\
{\cf pixel_bytes(native) * width * height * depth } \\
This will return {\cf std::numeric_limits<imagesize_t>::max()} in the event
of an overflow where it's not representable in an {\cf imagesize_t}.
\apiend

\apiitem{bool {\ce size_t_safe} () const}
Return {\cf true} if an image described by this spec can the sizes
(in pixels or bytes) of its scanlines, tiles, and the entire image can
be represented by a {\cf size_t} on that platform.  If this returns
{\cf false}, the client application should be very careful allocating
storage!
\apiend

\apiitem{int {\ce channelindex} (string_view name) const}
Returns the index of the channel with the given name, or -1 if no such
channel is present in {\cf channelnames}.
\apiend

\apiitem{ROI {\ce roi} () const \\
ROI {\ce roi_full} () const}
The {\cf roi()} method returns an \ROI describing the pixel data window and
channel range, and {\cf roi_full()} returns an \ROI describing the ``full
size'' (a.k.a.\ ``display window'').
\apiend

\apiitem{void {\ce set_roi} (ROI roi) \\
void {\ce set_roi_full} (ROI roi)}
Sets the dimensions and offset of the pixel data window and full/display
window, respectively. Note that the channel range of the \ROI is ignored,
i.e., these methods do not modify the {\cf nchannels} field of the \ImageSpec.
\apiend

\apiitem{void {\ce copy_dimensions} (const ImageSpec \&other)}
Copies from {\cf other} only the fields describing the dimensions and
data types, and \emph{not} arbitrary named metadata or channel names (thus,
for an \ImageSpec with lots of metadata, it is much less expensive than
copying the whole thing with {\cf operator=()}).
\apiend

\apiitem{bool {\ce undefined} () const}
Returns {\cf true} for a newly initialized (undefined) \ImageSpec.
\apiend


% FIXME - document auto_stride() ?

\apiitem{void {\ce attribute} (string_view name, TypeDesc type, \\
\bigspc const void *value)}
Add a metadata attribute to {\cf extra_attribs}, with the given name and
data type.  The {\cf value} pointer specifies
the address of the data to be copied.
\apiend

\apiitem{void {\ce attribute} (string_view name, unsigned int value)\\
    void {\ce attribute} (string_view name, int value)\\
    void {\ce attribute} (string_view name, float value)\\
    void {\ce attribute} (string_view name, string_view value)}
Shortcuts for passing attributes comprised of a single integer,
floating-point value, or string.
\apiend

\apiitem{void {\ce erase_attribute} (string_view name,\\
\bigspc\bigspc                   TypeDesc searchtype=UNKNOWN,\\
\bigspc\bigspc                   bool casesensitive=false)}

Searches {\cf extra_attribs} for any attributes matching {\cf name} (as
a regular expression), removing them entirely from {\cf extra_attribs}.
If {\cf searchtype} is anything other than {\cf TypeDesc::UNKNOWN},
matches will be restricted only to attributes with the given type.
The name comparison will be case-sensitive if {\cf casesensitive} is true, otherwise
in a case-insensitive manner if {\cf caseinsensitive} is false.
\apiend

\apiitem{ParamValue * {\ce find_attribute} (string_view name,\\
\bigspc\bigspc\bigspc                        TypeDesc searchtype=UNKNOWN,\\
\bigspc\bigspc\bigspc                        bool casesensitive=false)\\
const ParamValue * {\ce find_attribute} (string_view name,\\
\bigspc\bigspc\bigspc\spc                     TypeDesc searchtype=UNKNOWN,\\
\bigspc\bigspc\bigspc\spc                     bool casesensitive=false) const}

Searches {\cf extra_attribs} for an attribute matching {\cf name},
returning a pointer to the attribute record, or NULL if there was no
match.  If {\cf searchtype} is anything other than {\cf TypeDesc::UNKNOWN},
matches will be restricted only to attributes with the given type.
The name comparison will be exact if {\cf casesensitive} is true, otherwise
in a case-insensitive manner if {\cf caseinsensitive} is false.
\apiend

\apiitem{const ParamValue * {\ce find_attribute} (string_view name,\\
\bigspc\bigspc\bigspc\spc                     ParamValue \&tmpparam,\\
\bigspc\bigspc\bigspc\spc                     TypeDesc searchtype=UNKNOWN,\\
\bigspc\bigspc\bigspc\spc                     bool casesensitive=false) const}
Search for the named attribute and return the pointer to its
{\cf ParamValue} record, or {\cf NULL} if not found.  This variety of
{\cf find_attribute(}) can retrieve items such as \qkw{width}, which are
part of the \ImageSpec, but not in {\cf extra_attribs}. The {\cf tmpparam}
is a temporary storage area owned by the caller, which is used as temporary
buffer in cases where the information does not correspond to an actual
{\cf extra_attribs} (in this case, the return value will be {\cf \&tmpparam}).
The extra names it understands are:
\begin{description}
\item[\spc]
\item[\rm \qkw{x}, \qkw{y}, \qkw{z}, \qkw{width}, \qkw{height}, \qkw{depth}]
\item[\rm \qkw{full_x}, \qkw{full_y}, \qkw{full_z},
  \qkw{full_width}, \qkw{full_height}, \qkw{full_depth}] \spc\\
  Returns the {\cf ImageSpec} fields of those names (despite the fact that
  they are technically not arbitrary named attributes in {\cf extra_attribs}).
  All are of type {\cf int}.
\item[\rm \qkw{datawindow}] \spc\\
  Without a type, or if requested explicitly as an {\cf int[4]}, returns the
  OpenEXR-like pixel data min and max coordinates, as a 4-element integer
  array: {\cf \{ x, y, x+width-1, y+height-1 \}}.  If instead you specifically
  request as an {\cf int[6]}, it will return the volumetric data window,
  {\cf \{ x, y, z, x+width-1, y+height-1, z+depth-1 \}}.
\item[\rm \qkw{displaywindow}] \spc\\
  Without a type, or if requested explicitly as an {\cf int[4]}, returns the
  OpenEXR-like pixel display min and max coordinates, as a 4-element integer
  array: {\cf \{ full_x, full_y, full_x+full_width-1, full_y+full_height-1 \}}.
  If instead you specifically
  request as an {\cf int[6]}, it will return the volumetric display window,
  {\cf \{ full_x, full_y, full_z, full_x+full_width-1, full_y+full_height-1, full_z+full_depth-1 \}}.
\end{description}

\EXAMPLES
\begin{code}
    ImageSpec spec;           // has the info
    Imath::Box2i dw;          // we want the displaywindow here
    ParamValue tmp;           // so we can retrieve pseudo-values
    TypeDesc int4("int[4]");  // Equivalent: TypeDesc int4(TypeDesc::INT,4);
    const ParamValue* p = spec.find_attribute ("displaywindow", int4);
    if (p)
        dw = Imath::Box2i(p->get<int>(0), p->get<int>(1),
                          p->get<int>(2), p->get<int>(3));

    p = spec.find_attribute("temperature", TypeFloat);
    if (p)
        float temperature = p->get<float>();
\end{code}

\apiend


\apiitem{TypeDesc {\ce getattributetype} (string_view name, \\
\bigspc\bigspc                     bool casesensitive=false) const}
\indexapi{getattributetype}
\NEW % 2.1
If the named attribute can be found in the \ImageSpec, return its data type.
If no such attribute exists, return {\cf TypeUnknown}.
\apiend

\apiitem{bool {\ce getattribute} (string_view name, TypeDesc type,
  void *val,
\bigspc\bigspc                     bool casesensitive=false) const}
\indexapi{getattribute}
\NEW % 2.1
If the \ImageSpec contains the named attribute and its type matches
{\cf type}, copy the attribute value into the memory pointed to by {\cf val}
(it is up to the caller to ensure there is enough space) and return {\cf true}.
If no such attribute is found, or if it doesn't match the type, return
{\cf false} and do not modify {\cf val}.

\noindent Here are examples:

\begin{code}
      ImageSpec spec;
      ...
      // Retrieving an integer attribute:
      int orientation = 0;
      spec.getattribute ("orientation", TypeInt, &orientation);

      // Retrieving a string attribute with a char*:
      const char* compression = nullptr;
      spec.getattribute ("compression", TypeString, &compression);

      // Alternately, retrieving a string with a ustring:
      ustring compression;
      spec.getattribute ("compression", TypeString, &compression);
\end{code}

Note that when passing a string, you need to pass a pointer to the {\cf
  char*}, not a pointer to the first character.  Also, the {\cf char*}
will end up pointing to characters owned by the \ImageSpec; the
caller does not need to ever free the memory that contains the
characters.
\apiend

\apiitem{int {\ce get_int_attribute} (string_view name, int defaultval=0) const}
Gets an integer metadata attribute (silently converting to {\cf int}
even if if the data is really int8, uint8, int16, uint16, or uint32),
and simply substituting the supplied default value if no such metadata
exists.  This is a convenience function for when you know you are just
looking for a simple integer value.
\apiend

\apiitem{float {\ce get_float_attribute} (string_view name, float defaultval=0) const}
Gets a float metadata attribute (silently converting to {\cf float} even
if the data is really half or double), simply substituting the supplied
default value if no such metadata exists.  This is a convenience
function for when you know you are just looking for a simple float value.
\apiend

\apiitem{string_view {\ce get_string_attribute} (string_view name, \\
\bigspc\bigspc\bigspc  string_view defaultval = "") const}
Gets a string metadata attribute, simply substituting the supplied
default value if no such metadata exists.  This is a convenience
function for when you know you are just looking for a simple string value.
\apiend

\apiitem{AttrDelegate {\ce operator[]} (string_view name)}
\NEW % 2.1
Metadata inside an \ImageSpec can be set and retrieved using an array-access
notation with the metadata name as the ``index.'' Technically, the {\cf [name]}
operator is returning a temporary structure called an {\cf AttrDelegate},
which you can assign to or from.

\noindent To set metadata, simply assign:

\begin{code}
    ImageSpec spec;
    spec["foo"] = 42;                   // int
    spec["pi"] = float(M_PI);           // float
    spec["oiio:ColorSpace"] = "sRGB";   // string
    spec["cameratoworld"] = Imath::Matrix44(...);  // matrix
\end{code}

\noindent Be very careful, the data type of the metadata will be whatever
is implied by the C++ type you are ``assigning.''

Retrieval is also simple, but requires you to say what data type you want:

\begin{code}
    float bar = spec["bar"].get<float>();
    int x = spec["FrameNumber"].get<int>(1000); // optional default
\end{code}
\apiend


\apiitem{static std::string {\ce metadata_val} (const ParamValue \&p,
  bool human=true) const}
For a given parameter {\cf p}, format the value nicely as a string.
If {\cf human} is true, use
especially human-readable explanations (units, or decoding of
values) for certain known metadata.
\apiend


\apiitem{std::string {\ce serialize} (SerialFormat format, SerialVerbose verbose) const}
Returns, as a string, a serialized version of the \ImageSpec.
The {\cf format} may be either {\cf ImageSpec::SerialText} or
{\cf ImageSpec::SerialXML}.
The {\cf verbose} argument may be one of: {\cf ImageSpec::SerialBrief} (just
resolution and other vital statistics, one line for {\cf SerialText},
{\cf ImageSpec::SerialDetailed} (contains all metadata in orginal form), or
{\cf ImageSpec::SerialDetailedHuman} (contains all metadata, in many cases
with human-readable explanation).

\apiend

\apiitem{std::string {\ce to_xml} () const}
Saves the contents of the \ImageSpec as XML, returning it as a string.
\apiend

\apiitem{void {\ce from_xml} (const char *xml) const}
Populates the fields of the \ImageSpec based on the XML passed in.
\apiend

\apiitem{TypeDesc {\ce channelformat} (int chan) const}
Returns a \TypeDesc describing the format of the requested channel.
\apiend

\apiitem{void {\ce get_channelformats} (std::vector<TypeDesc> \&formats) const}
Fill in an array of channel formats describing all channels in the
image.  (Note that this differs slightly from the member data 
{\cf channelformats}, which is empty if there are not separate per-channel
formats.)
\apiend



\section{``Deep'' pixel data: {\cf DeepData}}
\label{sec:deepdata}
\indexapi{DeepData}

A \DeepData holds the contents of an image of ``deep'' pixels (multiple
depth samples per pixel).

\noindent Commonly used \DeepData fields and methods include:

\apiitem{void {\ce init} (const ImageSpec \&spec)}
Initialize the \DeepData based on the \ImageSpec's total number of pixels,
number and types of channels. At this stage, all pixels are assumed to
have 0 samples, and no sample data is allocated.
\apiend

\apiitem {void {\ce init} (int npix, int nchan,\\
    \bigspc cspan<TypeDesc> channeltypes),\\
    \bigspc cspan<std::string> channelnames)}
Initialize the \DeepData with a number of pixels, channels, channel
types, and channel names.
\apiend

\apiitem{void {\ce clear} ()}
Reset the \DeepData to be equivalent to its empty initial state.
\apiend

\apiitem{void {\ce free} ()}
Not only {\cf clear()}, but also ensure that all allocated memory has been
truly freed.
\apiend

\apiitem{int {\ce npixels} () const}
Retrieve the total number of pixels.
\apiend

\apiitem{int {\ce nchannels} () const}
Retrieve the number of channels.
\apiend

\apiitem{string_view {\ce channelname} (int c) const}
Retrieve the name of channel {\cf c}.
\apiend

\apiitem{TypeDesc {\ce channeltype} (int c) const}
Retrieve the data type of channel {\cf c}.
\apiend

\apiitem{size_t {\ce channelsize} (int c) const}
Retrieve the size (in bytes) of one datum of channel {\cf c}.
\apiend

\apiitem{size_t {\ce samplesize} () const}
Retrieve the packed size (in bytes) of all channels of one sample.
\apiend

\apiitem{int {\ce samples} (int pixel) const}
Retrieve the number of samples for the given pixel index.
\apiend

\apiitem{void {\ce set_samples} (int pixel, int samps)}
Set the number of samples for the given pixel index.
\apiend

\apiitem{void {\ce insert_samples} (int pixel, int samplepos, int n=1)}
Insert {\cf n} samples of the specified pixel, betinning at the sample
position index. After insertion, the new samples will have uninitialized
values.
\apiend

\apiitem{void {\ce erase_samples} (int pixel, int samplepos, int n=1)}
Remove {\cf n} samples of the specified pixel, betinning at the sample
position index.
\apiend

\apiitem{float {\ce deep_value} (int pixel, int channel, int sample) const \\
uint32_t {\ce deep_value_uint} (int pixel, int channel, int sample) const}
Retrieve the value of the given pixel, channel, and sample indices, for
floating point or unsigned integer channel types, respectively.
\apiend

\apiitem{void {\ce set_deep_value} (int pixel, int channel, int sample, float value) \\
void {\ce set_deep_value} (int pixel, int channel, int sample, uint32_t value)}
Set the value of the given pixel, channel, and sample indices, for
floating point or unsigned integer channel types, respectively.
\apiend

\apiitem{bool {\ce copy_deep_sample} (int pixel, int sample, \\
    \bigspc const DeepData \&src, int srcpixel, int srcsample)}
Copy a deep sample from {\cf src} to this \DeepData. They must have the same
channel layout. Return {\cf true} if ok, {\cf false} if the operation could
not be performed.
\apiend

\apiitem{bool {\ce copy_deep_pixel} (int pixel, const DeepData \&src, int srcpixel)}
Copy an entire deep pixel from {\cf src} to this \DeepData, completely
replacing any pixel data for that pixel. They must have the same channel
layout. Return {\cf true} if ok, {\cf false} if the operation could not be
performed.
\apiend

\apiitem{bool {\ce split} (int pixel, float depth)}
Split any samples of the pixel that cross {\cf depth}. Return {\cf true} if
any splits occurred, {\cf false} if the pixel was unmodified.
\apiend

\apiitem{void {\ce sort} (int pixel)}
Sort the samples of the pixel by their Z depth.
\apiend

\apiitem{void {\ce merge_overlaps} (int pixel)}
Merge any adjacent samples in the pixel that exactly overlap in $z$
range. This is only useful if the pixel has previously been split at
all sample starts and ends, and sorted by depth. Note that this may change
the number of samples in the pixel.
\apiend

\apiitem{bool {\ce merge_deep_pixels} (int pixel, const DeepData \&src, int srcpixel)}
Merge the samples of {\cf src}'s pixel into this \DeepData's pixel.
Return {\cf true} if ok, {\cf false} if the operation could not be
performed.
\apiend

\apiitem{bool {\ce occlusion_cull} (int pixel)}
Eliminate any samples beyond an opaque sample.
\apiend

\apiitem{float {\ce opaque_z} (int pixel)}
For the given pixel index. return the $z$ value at which the pixel reaches
full opacity.
\apiend


\section{Miscellaneous Utilities}
\label{sec:miscapi}

These helper functions are not part of any other \OpenImageIO class,
they just exist in the {\cf OpenImageIO} namespace as general utilities.
(See Section~\ref{sec:pythonmiscapi} for the corresponding Python
bindings.)

\apiitem{int {\ce openimageio_version} ()}
\index{version}
\indexapi{openimageio_version}
Returns a numeric value for the version of \product, 10000 for each
major version, 100 for each minor version, 1 for each patch.  For
example, \product 1.2.3 would return a value of 10203.
\apiend

\apiitem{std::string {\ce geterror} ()}
\index{error checking}
\indexapi{geterror}
Returns any error string describing what went wrong if 
{\cf ImageInput::create()} or \\ {\cf ImageOutput::create()} failed
(since in such cases, the \ImageInput or \ImageOutput itself does 
not exist to have its own {\cf geterror()} function called).
This function returns the last error
for this particular thread; separate threads will not clobber each
other's global error messages.
\apiend


\apiitem{bool {\ce attribute} (string_view name, TypeDesc type,
  const void *val)}
\index{globalattribute}
\label{sec:globalattribute}
\indexapi{attribute}

Sets an global attribute (i.e., a property or option) of \product.
The {\cf name} designates the name of the attribute, {\cf type}
describes the type of data, and {\cf val} is a pointer to memory 
containing the new value for the attribute.

If the name is known, valid attribute that matches the type specified,
the attribute will be set to the new value and {\cf attribute()} will
return {\cf true}.  If {\cf name} is not recognized, or if the types do
not match (e.g., {\cf type} is {\cf TypeFloat} but the named
attribute is a string), the attribute will not be modified, and {\cf
  attribute()} will return {\cf false}.

\noindent The following are the recognized attributes:

\apiitem{string options}
\vspace{10pt}
This catch-all is simply a comma-separated list of {\cf name=value}
settings of named options, which will be parsed and individually set.
For example,
\begin{code}
        OIIO::attribute ("options", "threads=4,log_times=1");
\end{code}
Note that if an option takes a string value that must itself contain a
comma, it is permissible to enclose the value in either single ({\cf ' '})
or double ({\cf " "}) quotes.
\apiend

\apiitem{int threads}
\vspace{10pt}
\index{threads} \label{sec:attribute:threads}
Some \product operations can be accelerated if allowed to spawn multiple
threads to parallelize the task.  (Examples: simultaneous format conversions
of multiple scanlines read together, or many \ImageBufAlgo operations.)
This attribute sets the default number of threads that will be spawned
for these operations (the ``fan out'').
The default is 0, which means that it should spawn as many
threads as there are hardware cores present on the system.

Situations where the main application logic is essentially single threaded
(i.e., one top-level call into OIIO at a time) should leave this at the
default value, or some reasonable number of cores, thus allowing lots of
threads to fill the cores when OIIO has big tasks to complete. But
situations where you have many threads at the application level, each of
which is expected to be making separate OIIO calls simultaneously, should
set this to 1, thus having each calling thread do its own work inside of
OIIO rather than spawning new threads with a high overall ``fan out.''
\apiend

\apiitem{int exr_threads}
\vspace{10pt}
\index{exr_threads}
Sets the internal OpenEXR thread pool size. The default is to use as many
threads as the amount of hardware concurrency detected.
Note that this is separate from the OIIO
\qkw{threads} attribute.
\apiend

\apiitem{string plugin_searchpath}
\vspace{10pt}
\index{plugin_searchpath}
A colon-separated list of directories to search for 
dynamically-loaded format plugins.
\apiend

\apiitem{int read_chunk}
\vspace{10pt}
\index{read_chunk}
When performing a {\cf read_image()}, this is the number of scanlines it
will attempt to read at a time (some formats are more efficient when reading
and decoding multiple scanlines).  The default is 256.  The special value
of 0 indicates that it should try to read the whole image if possible.
\apiend

\apiitem{float[] missingcolor \\
string missingcolor}
\vspace{10pt}
\index{missingcolor} \label{sec:missingcolor}
\NEW % 2.0
The \qkw{missingcolor} attribute may either be an array of float values,
or a string containing a comma-separated list of the values.
Setting this option globally is equivalent to always passing an
\ImageInput open-with-configuration hint \qkw{oiio:missingcolor} with the
value.

When set, it gives some {\cf ImageInput} readers the option of ignoring any
\emph{missing} tiles or scanlines in the file, and instead of treating the
read failure of an individual tile as a full error, will interpret is as
an intentionally missing tile and proceed by simply filling in the missing
pixels with the color specified. If the first element is negative, it will
use the absolute value, but draw alternating diagonal stripes of the color.
For example,
\begin{code}
    float missing[4] = { -1.0, 0.0, 0.0, 0.0 }; // striped red
    OIIO::attribute ("missingcolor", TypeDesc("float[4]"), &missing);
\end{code}

Note that only some file formats support files with missing tiles or
scanlines, and this is only taken as a hint. Please see
Section~\ref{chap:bundledplugins} for details on which formats accept a
\qkw{missingcolor} configuration hint.
\apiend

\apiitem{int debug}
\vspace{10pt}
\index{debug}
When nonzero, various debug messages may be printed. The default is 0 for
release builds, 1 for {\cf DEBUG} builds, but also may be overridden by the
{\cf OPENIMAGEIO\_DEBUG} env variable. Values $> 1$ are for OIIO developers
to print even more debugging information.
\apiend

\apiitem{int log_times \\
string timing_report {\rm ~(read only)}}
\vspace{10pt}
\index{log_times} \index{timing_report}

When the \qkw{log_times} attribute is nonzero, {\cf ImageBufAlgo} functions
are instrumented to record the number of times they were called and the
total amount of time spent executing them. When enabled, there is a slight
runtime performance cost due to checking the time at the start and end of
each of those function calls, and the locking and recording of the data
structure that holds the log information. When the {\cf log_times} attribute
is disabled, there is no additional performance cost.

The {\cf log_times} attribute is initialized to 0, but may be overridden by
environment variable {\cf OPENIMAGEIO_LOG_TIMES}.
\index{OPENIMAGEIO_LOG_TIMES}

The report of totals can be retrieved as the value of the
\qkw{timing_report} attribute, which is a string and is read-only. The
report is sorted alphabetically and for each named instrumentation region,
prints the number of times it executed, the total runtime, and the average
per call, like this:
\begin{code}
    IBA::computePixelStats        2   2.69ms  (avg   1.34ms)
    IBA::make_texture             1  74.05ms  (avg  74.05ms)
    IBA::mul                      8   2.42ms  (avg   0.30ms)
    IBA::over                    10  23.82ms  (avg   2.38ms)
    IBA::resize                  20   0.24s   (avg  12.18ms)
    IBA::zero                     8   0.66ms  (avg   0.08ms)
\end{code}

If the value of {\cf log_times} is 2 or more when the application terminates,
the timing report will be printed to {\cf stdout} upon exit.
\apiend

\apiitem{string format_list \\
string input_format_list \\
string output_format_list {\rm ~(read only)}}
\vspace{10pt}
\index{format_list} \index{input_format_list} \index{output_format_list}
A comma-separated list of all the names of, respectively, all supported
image formats, all formats accepted as inputs, and all formats accepted
as outputs.  (Note: can only be retrieved
by {\cf getattribute()}, cannot be set by {\cf attribute()}.)
\apiend

\apiitem{string extension_list {\rm ~(read only)}}
\vspace{10pt}
\index{extension_list}
For each format, the format name, followed by a colon, followed by
a comma-separated list of all extensions that are presumed to be used
for that format.  Semicolons separate the lists for formats.  For
example,
\begin{code}
     "tiff:tif;jpeg:jpg,jpeg;openexr:exr"
\end{code}
(Note: can only be retrieved
by {\cf getattribute()}, cannot be set by {\cf attribute()}.)
\apiend

\apiitem{string library_list {\rm ~(read only)}}
\vspace{10pt}
\index{library_list}
For each format that uses a dependent library, the format name, followed by
a colon, followed by the name and version of the dependency. Semicolons
separate the lists for formats.  For example,
\begin{code}
     "tiff:LIBTIFF 4.0.4;gif:gif_lib 4.2.3;openexr:OpenEXR 2.2.0"
\end{code}
(Note: can only be retrieved by {\cf getattribute()}, cannot be set by
{\cf attribute()}.)
\apiend

\apiitem{string hw:simd \\
string oiio:simd}
\vspace{10pt}
\index{hw:simd} \index{oiio:simd}
% added in 1.8
The \qkw{hw:simd} read-only attribute is a comma-separated list of
hardware CPU features for SIMD (and some other things). The \qkw{oiio:simd}
is similarly a list of which features this build of OIIO was compiled
to support.
\apiend

\apiitem{float resident_memory_used_MB {\rm ~(read only)}}
\vspace{10pt}
\index{resident_memory_used_MB}
This read-only attribute can be used for debugging purposes to report
the approximate process memory used (resident) by the application, in MB.
\apiend

\apiend


\apiitem{bool {\ce attribute} (string_view name, int val) \\
bool {\ce attribute} (string_view name, float val) \\
bool {\ce attribute} (string_view name, const char *val) \\
bool {\ce attribute} (string_view name, const std::string \& val)}
Specialized versions of {\cf attribute()} in which the data type is
implied by the type of the argument.
\apiend



\apiitem{bool {\ce getattribute} (string_view name, TypeDesc type,
  void *val)}
\indexapi{getattribute}

Gets the current value of a global attribute.  The {\cf name} designates
the name of the attribute, {\cf type} describes the type of data, and
{\cf val} is a pointer to memory where the user would like the value
placed.

If the attribute name is valid and matches the type specified, the
attribute value will be stored at address {\cf val} and {\cf
  attribute()} will return {\cf true}.  If {\cf name} is not recognized
as a valid attribute name, or if the types do not match (e.g., {\cf
  type} is {\cf TypeFloat} but the named attribute is a
string), no data will be written to {\cf val}, and {\cf attribute()}
will return {\cf false}.

The complete list of attributes can be found above, in the description
of the {\cf attribute()} function.
\apiend

\apiitem{bool {\ce getattribute} (string_view name, int \&val) \\
bool {\ce getattribute} (string_view name, float \&val) \\
bool {\ce getattribute} (string_view name, char **val) \\
bool {\ce getattribute} (string_view name, std::string \& val)}
Specialized versions of {\cf getattribute()} in which the data type is
implied by the type of the argument.

For example, the following are equivalent to the example above for the
general (pointer) form of {\cf getattribute()}:

\begin{code}
      int threads;
      OIIO::getattribute ("threads", &threads);
      std::string path;
      OIIO::getattribute ("plugin_searchpath", &path);
\end{code}
\apiend

\apiitem{int {\ce get_int_attribute} (string_view name, int defaultvalue=0) \\
float {\ce get_float_attribute} (string_view name, float defaultvalue=0) \\
string_view {\ce get_string_attribute} (string_view name, \\
\bigspc\bigspc\bigspc  string_view defaultvalue="")}
\indexapi{get_int_attribute} \indexapi{get_float_attribute}
\indexapi{get_string_attribute}
Specialized versions of {\cf getattribute()} for common types, in which the
data is returned directly, and a supplied default value is returned if the
attribute was not found.

For example, the following are equivalent to the example above for the
general (pointer) form of {\cf getattribute()}:

\begin{code}
      int threads = OIIO::getattribute ("threads", 0);
      string_view path = OIIO::getattribute ("plugin_searchpath");
\end{code}
\apiend


\apiitem{void {\ce declare_imageio_format} (const std::string \&format_name,\\
\bigspc\bigspc\spc                    ImageInput::Creator input_creator, \\
\bigspc\bigspc\spc                    const char **input_extensions,\\
\bigspc\bigspc\spc                    ImageOutput::Creator output_creator, \\
\bigspc\bigspc\spc                    const char **output_extensions, \\
\bigspc\bigspc\spc                    const char *lib_version)}
Register the input and output `create' functions and list of file extensions
for a particular format.
\apiend

\section{Environment variables}

There are a few special environment variables that can be used to control
\product at times that it is not convenient to set options individually from
inside the source code.

\apiitem{OPENIMAGEIO_OPTIONS}
\NEW % 2.0
Allows you to seed the global \product-wide options.

The value of the environment variable should be a comma-separated list of
\emph{name=value} settings. If a value is a string that itself needs to
contain commas, it may be enclosed in single or double quotes.

Upon startup, the contents of this environment variable will be passed
to a call to:
\begin{code}
    OIIO::attribute ("options", value);
\end{code}
\apiend

\apiitem{OPENIMAGEIO_IMAGECACHE_OPTIONS}
Allows you to seed the options for any \ImageCache created.

The value of the environment variable should be a comma-separated list of
\emph{name=value} settings. If a value is a string that itself needs to
contain commas, it may be enclosed in single or double quotes.

Upon creation of any \ImageCache, the contents of this environment variable
will be passed to a call to:
\begin{code}
    imagecache->attribute ("options", value);
\end{code}
\apiend

\apiitem{OPENIMAGEIO_TEXTURESYSTEM_OPTIONS}
Allows you to seed the options for any \TextureSystem created.

The value of the environment variable should be a comma-separated list of
\emph{name=value} settings. If a value is a string that itself needs to
contain commas, it may be enclosed in single or double quotes.

Upon creation of any \TextureSystem, the contents of this environment variable
will be passed to a call to:
\begin{code}
    texturesys->attribute ("options", value);
\end{code}
\apiend


\index{Image I/O API Helper Classes|)}

\chapwidthend
