\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 type, \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 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. \\
\end{tabular}
\medskip

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

\apiitem{{\ce TypeDesc} (BASETYPE btype, AGGREGATE agg, VECSEMANTICS
xform=NOSEMANTICS)  \\
{\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

\bigskip

Of these, the only ones commonly used to store 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).


\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{string_view (const char *chars) \\
string_view (const char *chars, size_t length) \\
string_view (const std::string \&str) \\
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{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{ustring (const char *chars) \\
ustring (const char *chars, size_t length) \\
ustring (const std::string \&str) \\
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


\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{void {\ce set_format} (TypeDesc fmt)}
Sets the format as described.
\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

% 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{ImageIOParameter * {\ce find_attribute} (string_view name,\\
\bigspc\bigspc\spc                           TypeDesc searchtype=UNKNOWN,\\
\bigspc\bigspc\spc                           bool casesensitive=false)\\
const ImageIOParameter * {\ce find_attribute} (string_view name,\\
\bigspc\bigspc\spc                           TypeDesc searchtype=UNKNOWN,\\
\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 {\cf TypeDesc::UNKNOWN}, the search will be made
regardless of the data type, whereas other values of {\cf searchtype}
will reject a matching name if the data type does not also match.  The
name comparison will be exact if {\cf casesensitive} is true, otherwise
in a case-insensitive manner if {\cf caseinsensitive} is false.
\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,\\
\bigspc\bigspc 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  string_view defaultval = string_view()) 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{std::string {\ce metadata_val} (const ImageIOParamaeter \&p,
  bool human=true) const}
For a given parameter (in this \ImageSpec's {\cf extra_attribs} field),
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 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


\subsection{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}
\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 TypeDesc::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{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: decompressing multiple
simultaneously-read OpenEXR scanlines, or many \ImageBuf operations.)
This attribute sets the maximum number of threads that will be spawned.
The default is 1.  If set to 0, it means that it should use as many
threads as there are hardware cores present on the system.
\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{string format_list}
\vspace{10pt}
\index{format_list}
A comma-separated list of all the names of all supported 
image format readers and writers.  (Note: can only be retrieved
by {\cf getattribute()}, cannot be set by {\cf attribute()}.)
\apiend

\apiitem{string extension_list}
\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

\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 TypeDesc::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 maxfiles;
      ts->getattribute ("max_open_files", &maxfiles);
      const char *path;
      ts->getattribute ("plugin_searchpath", &path);
\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)}
Register the input and output `create' routines and list of file
extensions for a particular format.
\apiend


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

\chapwidthend
