\chapter{Image Buffers}
\label{chap:imagebuf}
\index{Image Buffers|(}
\index{ImageBuf|(}

\section{ImageBuf Introduction and Theory of Operation}
\label{sec:imagebuf:intro}

\ImageBuf is a utility class that stores an entire image.  It provides a
nice API for reading, writing, and manipulating images as a single unit,
without needing to worry about any of the details of storage or I/O.

\smallskip

\noindent An \ImageBuf can store its pixels in one of several ways:

\begin{itemize}
\item Allocate ``local storage'' to hold the image pixels
internal to the \ImageBuf.  This storage will be freed when the
\ImageBuf is destroyed.
\item ``Wrap'' pixel memory already allocated by the calling application,
which will continue to own that memory and be responsible for freeing
it after the \ImageBuf is destroyed.
\item Be ``backed'' by an \ImageCache, which will automatically be used
to retreive pixels when requested, but the \ImageBuf will not allocate
separate storage for it.  This brings all the advantages of the
\ImageCache, but can only be used for read-only \ImageBuf's that
reference a stored image file.
\end{itemize}

All I/O involving \ImageBuf (that is, calls to {\cf read} or {\cf write})
are implemented in terms of \ImageCache, \ImageInput,
and \ImageOutput underneath, and so support all of the image file
formats supported by OIIO.

\smallskip

\noindent The \ImageBuf class definition requires that you
\begin{code}
  #include <OpenImageIO/imagebuf.h>
\end{code}




\section{Constructing, reading, and writing an \ImageBuf}

\subsection*{Default constructor of an empty \ImageBuf}

\apiitem{{\ce ImageBuf} ()}
The default constructor makes an uninitialized \ImageBuf.  There isn't
much you can do with an uninitialized buffer until you call {\cf reset()}.
\apiend

\apiitem{void {\ce clear} ()}
Resets the \ImageBuf to a pristine state identical to that of a freshly
constructed \ImageBuf using the default constructor.
\apiend


\subsection*{Constructing and initializing a writable \ImageBuf}

\apiitem{{\ce ImageBuf} (const ImageSpec \&spec, \\
\bigspc\bigspc InitializePixels zero = InitializePixels::Yes) \\
{\ce ImageBuf} (string_view name, const ImageSpec \&spec, \\
\bigspc\bigspc InitializePixels zero = InitializePixels::Yes) }
Constructs a writable \ImageBuf with the given specification (including
resolution, data type, metadata, etc.).
The {\cf zero} parameter controls whether the pixel values are filled with
black/empty, or are left uninitialized after being allocated (if set to
{\cf InitializePixels::No}).
Optionally, you may name the \ImageBuf.
\apiend

\apiitem{void {\ce reset} (const ImageSpec \&spec, bool zero = true) \\
void {\ce reset} (string_view name, const ImageSpec \&spec, bool zero = true)}
Destroys any previous contents of the \ImageBuf and re-initializes it
as a writable all-black \ImageBuf with the given specification (including
resolution, data type, metadata, etc.).
The {\cf zero} parameter controls whether the pixel values are filled with
black/empty, or are left uninitialized after being allocated (if set to
{\cf InitializePixels::No}).
Optionally, you may name the \ImageBuf.
\ImageBuf.
\apiend

\apiitem{bool make_writable (bool keep_cache_type = false)}
Force the \ImageBuf to be writable. That means that if it was previously
backed by an \ImageCache (storage was {\cf IMAGECACHE}), it will force a
full read so that the whole image is in local memory.
This will invalidate any current iterators on the image. It has
no effect if the image storage not {\cf IMAGECACHE}.  Return {\cf true} if
it works (including if no read was necessary), {\cf false} if something went
horribly wrong. If {\cf keep_cache_type} is true, it preserves any
\ImageCache-forced data types (you might want to do this if it is critical
that the apparent data type doesn't change, for example if you are calling
make_writable from within a type-specialized function).
\apiend

\subsection*{Constructing a readable \ImageBuf and reading from a file}

Constructing a readable \ImageBuf that will hold an image to be read
from disk.

\apiitem{{\ce ImageBuf} (string_view name, int subimage=0, int miplevel=0, \\
\bigspc\bigspc ImageCache *imagecache = NULL, \\
\bigspc\bigspc const ImageSpec *config = NULL)}
Construct an \ImageBuf that will be used to read the named file (at the
given subimage and MIP-level, defaulting to the first in the file).  But
don't read it yet!  The image will actually be read when other methods
need to access the spec and/or pixels, or when an explicit call to
{\cf init_spec()} or {\cf read()} is made, whichever comes first. 
If {\cf imagecache} is non-NULL, the custom
\ImageCache will be used (if applicable); otherwise, a NULL imagecache
indicates that the global/shared \ImageCache should be used.
If {\cf config} is not NULL, it points to an \ImageSpec giving requests
or special instructions to be passed on to the eventual
{\cf ImageInput::open()} call.
\apiend

\apiitem{void {\ce reset} (string_view name, int subimage=0, int miplevel=0, \\
\bigspc\bigspc ImageCache *imagecache = NULL \\
\bigspc\bigspc const ImageSpec *config = NULL)}
Destroys any previous contents of the \ImageBuf and re-initializes it
to read the named file (but doesn't actually read yet).
If {\cf config} is not NULL, it points to an \ImageSpec giving requests
or special instructions to be passed on to the eventual
{\cf ImageInput::open()} call.
\apiend

\apiitem{bool {\ce read} (int subimage=0, int miplevel=0, bool force=false, \\
   \bigspc            TypeDesc convert=TypeDesc::UNKNOWN, \\
   \bigspc            ProgressCallback progress_callback=NULL, \\
   \bigspc            void *progress_callback_data=NULL) \\
bool {\ce read} (int subimage, int miplevel, \\
   \bigspc            int chbegin, int chend, bool force, TypeDesc convert, \\
   \bigspc            ProgressCallback progress_callback=NULL, \\
   \bigspc            void *progress_callback_data=NULL)}

Explicitly reads the particular subimage and MIP level of the image.  Generally,
this will skip the expensive read if the file has already been read into
the \ImageBuf (at the specified subimage and MIP level).  It will clear
and re-allocate memory if the previously allocated space was not
appropriate for the size or data type of the image being read.
If {\cf convert} is set to a specific type (not {\cf UNKNOWN}), the
\ImageBuf memory will be allocated for that type specifically and
converted upon read.

In general, {\cf read()} will try not to do any I/O at the time of the
{\cf read()} call, but rather to have the \ImageBuf ``backed'' by an
\ImageCache, which will do the file I/O on demand, as pixel values are
needed, and in that case the \ImageBuf doesn't actually allocate memory
for the pixels (the data lives in the \ImageCache).  However, there are
several conditions for which the \ImageCache will be bypassed, the
\ImageBuf will allocate ``local'' memory, and the disk file will be read
directly into allocated buffer at the time of the {\cf read()} call:
(a) if the {\cf force} parameter is {\cf true}; (b) if the {\cf convert}
parameter requests a data format conversion to a type that is not the
native file type and also is not one of the internal types supported by
the {\cf ImageCache} (specifically, {\cf FLOAT} and {\cf UINT8});
(c) if the \ImageBuf already has local pixel memory allocated, or
``wraps'' an application buffer.

The variety of {\cf read()} that takes {\cf chbegin} and {\cf chend}
parameters allows you to populate the \ImageBuf with a (contiguous) subset
of channels from the file. This can be useful if you are only interested
in a subset of channels and want to save the memory and I/O costs for the
channels you won't want.

If {\cf progress_callback} is non-NULL, the underlying read, if
expensive, may make several calls to
\begin{code}
  progress_callback(progress_callback_data, portion_done);
\end{code}
\noindent which allows you to implement some sort or progress meter.
Note that if the \ImageBuf is backed by an \ImageCache, the
progress callback will never be called, since no actual file I/O
will occur at this time (\ImageCache will load tiles or scanlines
on demand, as individual pixel values are needed).

Note that {\cf read()} is not strictly necessary. If you are happy with
the filename, subimage and MIP level specified by the \ImageBuf constructor
(or the last call to {\cf reset()}), and you want the storage to be backed
by the {\cf ImageCache} (including storing the pixels in whatever data
format that implies), then the file contents will be automatically read
the first time you make any other \ImageBuf API call that requires the
spec or pixel values.  The only reason to call {\cf read()} yourself is
if you are changing the filename, subimage, or MIP level, or if you want
to use {\cf force=true} or a specific {\cf convert} value to force data
format conversion.
\apiend

\apiitem{bool {\ce init_spec} (string_view filename,
                    int subimage, int miplevel)}
This call will read the \ImageSpec for the given file, subimage, and
MIP level into the \ImageBuf, but will not read the pixels or allocate
any local storage (until a subsequent call to {\cf read()}).  This is
helpful if you have an \ImageBuf and you need to know information about
the image, but don't want to do a full read yet, and maybe won't need
to do the full read, depending on what's found in the spec.

Note that {\cf init_spec()} is not strictly necessary. If you are happy with
the filename, subimage and MIP level specified by the \ImageBuf constructor
(or the last call to {\cf reset()}), then the spec will be automatically
read the first time you make any other \ImageBuf API call that requires it.
The only reason to call {\cf read()} yourself is if you are changing the
filename, subimage, or MIP level, or if you want to use {\cf force=true} or
a specific {\cf convert} value to force data format conversion.
\apiend


\subsection*{Constructing an \ImageBuf that ``wraps'' an application buffer}

\apiitem{{\ce ImageBuf} (const ImageSpec \&spec, void *buffer) \\
{\ce ImageBuf} (string_view name, const ImageSpec \&spec, void *buffer)}
Constructs an ImageBuf that "wraps" a memory buffer owned by the calling
application.  It can write pixels to this buffer, but can't change its
resolution or data type.  Optionally, it names the \ImageBuf.
\apiend


\subsection*{Writing an \ImageBuf to a file}

\apiitem{bool {\ce write} (string_view filename, \\
  \bigspc               TypeDesc dtype = TypeUnknown, \\
  \bigspc               string_view fileformat = "", \\
  \bigspc               ProgressCallback progress_callback=NULL, \\
  \bigspc               void *progress_callback_data=NULL) const}
Write the image to the named file, converted to the specified pixel data
type {\cf dtype} ({\cf TypeUnknown} signifies to use the data type of the
buffer), in the named file format (an empty {\cf fileformat} means to infer
the type from the filename extension).  Return {\cf true} if all went ok,
{\cf false} if there were errors writing.

By default, it will always write a scanline-oriented file, unless the
{\cf set_write_tiles()} method has been used to override this.
Also, it will use the data format of the buffer itself, unless the
{\cf set_write_format()} method has been used to override the data format.
\apiend

\apiitem{bool {\ce write} (ImageOutput *out, \\
  \bigspc                ProgressCallback progress_callback=NULL, \\
  \bigspc                void *progress_callback_data=NULL) const}
Write the image to the open \ImageOutput {\cf out}.  Return {\cf true}
if all went ok, {\cf false} if there were errors writing.  It does NOT
close the file when it's done (and so may be called in a loop to write a
multi-image file).
\apiend

\apiitem{void {\ce set_write_format} (cspan<TypeDesc> format)}
Override the pixel data format for subsequent calls to the {\cf write()}
method (the variety that does not take an open {\cf ImageOutput*}).
The {\cf format} parameter may be either a single \TypeDesc for all
channels, or a span giving a separate \TypeDesc for each channel (in order).
If this call is not made (or if the format is {\cf TypeUnknown}), then the
data type written will default to be whatever is described in the \ImageSpec
of the \ImageBuf.
\apiend

\apiitem{void {\ce set_write_tiles} (int width=0, int height=0, int depth=0)}
Override the tile sizing for subsequent calls to the {\cf write()} method
(the variety that does not take an open {\cf ImageOutput*}).
\apiend


\section{Getting and setting basic information about an \ImageBuf}

\apiitem{bool {\ce initialized} () const}
Returns {\cf true} if the \ImageBuf is initialized, {\cf false} if not
yet initialized.
\apiend

\apiitem{IBStorage {\ce storage} () const}
Returns an enumerated type describing the type of storage currently employed
by the \ImageBuf: {\cf UNINITIALIZED} (no storage), {\cf LOCALBUFFER} (the
\ImageBuf has allocated and owns the pixel memory), {\cf APPBUFFER} (the
\ImageBuf ``wraps'' memory owned by the calling application), or
{\cf IMAGECACHE} (the image is backed by an \ImageCache).
\apiend

\apiitem{const ImageSpec \& {\ce spec} () const \\
const ImageSpec \& {\ce nativespec} () const}

The {\cf spec()} function returns a {\cf const} reference to an
\ImageSpec that describes the image data held by the \ImageBuf.  

The {\cf nativespec()} function returns a {\cf const} reference
to an \ImageSpec that describes the actual data in the file that
was read.

These may differ --- for example, if a data format conversion was
requested, if the buffer is backed by an \ImageCache which stores the
pixels internally in a different data format than that of the file, or
if the file had differing per-channel data formats (\ImageBuf must
contain a single data format for all channels).
\apiend


\apiitem{string_view {\ce name} () const}
Returns the name of the buffer (name of the file, for an
\ImageBuf read from disk).
\apiend

\apiitem{string_view {\ce file_format_name} () const}
Returns the name of the file format, for an \ImageBuf read from disk
(for example, \qkw{openexr}).
\apiend

\apiitem{int {\ce subimage} () const \\
int {\ce nsubimages} () const \\
int {\ce miplevel} () const \\
int {\ce nmiplevels} () const}
The {\cf subimage()} and {\cf miplevel()} methods return the subimage and MIP
level of the image held by the \ImageBuf (the file it came from may hold
multiple subimages and/or MIP levels, but the \ImageBuf can only store
one of those at any given time).

The {\cf nsubimages()} method returns the total number of subimages in
the file, and the {\cf nmiplevels()} method returns the total number
of MIP levels in the currently-loaded subimage.
\apiend

\apiitem{int {\ce nchannels} () const}
Returns the number of channels stored in the buffer (this is equivalent
to {\cf spec().nchannels}).
\apiend

\apiitem{int {\ce xbegin} () const \\
    int {\ce xend} () const \\
    int {\ce ybegin} () const \\
    int {\ce yend} () const \\
    int {\ce zbegin} () const \\
    int {\ce zend} () const}
Returns the {\cf [begin,end)} range of the pixel data window of the
buffer.  These are equivalent to {\cf spec().x}, {\cf spec().x+spec().width},
{\cf spec().y}, {\cf spec().y+spec().height},
{\cf spec().z}, and {\cf spec().z+spec().depth}, respectively.
\apiend

\apiitem{int {\ce orientation} () const \\
    int {\ce oriented_width} () const \\
    int {\ce oriented_height} () const \\
    int {\ce oriented_x} () const \\
    int {\ce oriented_y} () const \\
    int {\ce oriented_full_width} () const \\
    int {\ce oriented_full_height} () const \\
    int {\ce oriented_full_x} () const \\
    int {\ce oriented_full_y} () const
}

The {\cf orientation()} returns the interpretation of the layout
(top/bottom, left/right) of the image, per the table in
Section~\ref{metadata:orientation}.

The oriented width, height, x, and y describe the pixel data window
after taking the display orientation into consideration.  The
\emph{full} versions the ``full'' (a.k.a.\ display) window after taking
the display orientation into consideration.
\apiend

\apiitem{void {\ce set_orientation} (int orient)}
Sets the \qkw{Orientation} metadata value.
\apiend

\apiitem{TypeDesc {\ce pixeltype} () const}
The data type of the pixels stored in the buffer (equivalent to
{\cf spec().format}).
\apiend

\apiitem{void {\ce set_origin} (int x, int y, int z=0)}
Alters the metadata of the spec in the \ImageBuf to reset the ``origin''
of the pixel data window to be the specified coordinates.  This does not
affect the size of the pixel data window, only its position.
\apiend

\apiitem{void {\ce set_full} (int xbegin, int xend, int ybegin, int yend, \\
  \bigspc\spc       int zbegin, int zend) \\
  void {\ce set_roi_full} (const ROI \&newroi)}
Alters the metadata of the spec in the \ImageBuf to reset the ``full''
image size (a.k.a.\ ``display window'').  This does not affect the size
of the pixel data window.
\apiend

\apiitem{ImageSpec \& {\ce specmod} ()}
This returns a \emph{writable} reference to the \ImageSpec describing
the buffer.  It's ok to modify most of the metadata, but if you modify
the spec's {\cf format}, {\cf width}, {\cf height}, or {\cf depth}
fields, you get the pain you deserve, as the \ImageBuf will no longer
have correct knowledge of its pixel memory layout.  USE WITH EXTREME
CAUTION.
\apiend

\apiitem{void {\ce threads} (int n) \\
int {\ce threads} () const}
\index{threads}
Get or set the threading policy for this \ImageBuf, controlling the
maximum amount of parallelizing thread ``fan-out'' that might occur during
expensive operations. The default of 0 means that the global
{\cf attribute("threads")} value should be used (which itself defaults to
using as many threads as cores; see Section~\ref{sec:attribute:threads}).

The main reason to change this value is to set it to 1 to indicate that the
calling thread should do all the work rather than spawning new threads. That
is probably the desired behavior in situations where the calling application
has already spawned multiple worker threads.
\apiend


\section{Copying \ImageBuf's and blocks of pixels}

\apiitem{const ImageBuf\& operator= (const ImageBuf \&src) \\
const ImageBuf\& operator= (ImageBuf \&\&src)}
Copy and move assignment.
\apiend

\apiitem{ImageBuf {\ce copy} (TypeDesc format=TypeUnknown) const}
Returns a full copy of {\cf this} (pixels and metadata), with optional data
format conversion.
\apiend

\apiitem{bool {\ce copy} (const ImageBuf \&src, TypeDesc format=TypeUnknown)}
Copies {\cf src} to {\cf this} -- both pixel values and all metadata.
If a {\cf format} is provided, {\cf this} will get the specified pixel
data type rather than using the same pixel format as {\cf src}.
\apiend

\apiitem{void {\ce copy_metadata} (const ImageBuf \&src)}
Copies all metadata (except for {\cf format}, {\cf width}, {\cf height},
{\cf depth} from {\cf src} to {\cf this}.
\apiend

\apiitem{bool {\ce copy_pixels} (const ImageBuf \&src)}
Copies the pixels of {\cf src} to {\cf this}, but does not change the
metadata (other than format and resolution) of {\cf this}.
\apiend

\apiitem{void {\ce swap} (ImageBuf \&other)}
Swaps the entire contents of {\cf other} and {\cf this}.
\apiend

\apiitem{bool {\ce get_pixels} (ROI roi, TypeDesc format, \\
  \bigspc\bigspc                void *result, stride_t xstride=AutoStride,\\
  \bigspc\bigspc                stride_t ystride=AutoStride, \\
  \bigspc\bigspc                stride_t zstride=AutoStride) const}
Retrieve the rectangle of pixels specified by ROI, at the current subimage
and MIP-map level, storing the pixel values beginning at the address
specified by {\cf result} and with the given strides (by default, {\cf
AutoStride} means the usual contiguous packing of pixels) and converting
into the data type described by {\cf format}.  It is up to the caller to
ensure that {\cf result} points to an area of memory big enough to
accommodate the requested rectangle. Return {\cf true} if the operation
could be completed, otherwise return {\cf false}.
\apiend

\apiitem{bool {\ce get_pixel_channels} (int xbegin, int xend, int ybegin, int yend, \\
  \bigspc\bigspc            int zbegin, int zend, int chbegin, int chend,\\
  \bigspc\bigspc            TypeDesc format, void *result,\\
  \bigspc\bigspc            stride_t xstride=AutoStride,\\
  \bigspc\bigspc            stride_t ystride=AutoStride,\\
  \bigspc\bigspc            stride_t zstride=AutoStride) const}

Retrieve the rectangle of pixels spanning {\cf [xbegin..xend)} $\times$
{\cf [ybegin..yend)} $\times$ {\cf [zbegin..zend)}, channels 
{\cf [chbegin,chend)} (all with exclusive
end), specified as integer pixel coordinates, at the current subimage and
MIP-map level, storing the pixel values beginning at the address
specified by {\cf result} and with the given strides (by default,
{\cf AutoStride} means the usual contiguous packing of pixels) and
converting into the data type described by {\cf format}.  It is
up to the caller to ensure that {\cf result} points to an area of
memory big enough to accommodate the requested rectangle.
Return {\cf true} if the operation could be completed, otherwise
return {\cf false}.
\apiend


\apiitem{bool {\ce get_pixels} (int xbegin, int xend, int ybegin, int yend, \\
  \bigspc\bigspc                   int zbegin, int zend, TypeDesc format, \\
  \bigspc\bigspc                   void *result, stride_t xstride=AutoStride,\\
  \bigspc\bigspc                   stride_t ystride=AutoStride, \\
  \bigspc\bigspc                   stride_t zstride=AutoStride) const}
Retrieve the rectangle of pixels spanning {\cf [xbegin..xend)} $\times$
{\cf [ybegin..yend)} $\times$ {\cf [zbegin..zend)} (all with exclusive
end), specified as integer pixel coordinates, at the current subimage and
MIP-map level, storing the pixel values beginning at the address
specified by {\cf result} and with the given strides (by default,
{\cf AutoStride} means the usual contiguous packing of pixels) and
converting into the data type described by {\cf format}.  It is
up to the caller to ensure that {\cf result} points to an area of
memory big enough to accommodate the requested rectangle.
Return {\cf true} if the operation could be completed, otherwise
return {\cf false}.
\apiend

\apiitem{bool {\ce set_pixels} (ROI roi, TypeDesc format, \\
  \bigspc\bigspc                const void *result, stride_t xstride=AutoStride,\\
  \bigspc\bigspc                stride_t ystride=AutoStride, \\
  \bigspc\bigspc                stride_t zstride=AutoStride)}
Copy the rectangle of data into the specified ROI of the ImageBuf. The data
points to values specified by {\cf format}, with layout detailed by the
stride values (in bytes, with {\cf AutoStride} indicating ``contiguous''
layout). It is up to the caller to ensure that data points to an area of
memory big enough to account for the ROI. Return {\cf true} if the operation
could be completed, otherwise return {\cf false}.
\apiend



\section{Getting and setting individual pixel values -- simple but slow}

\apiitem{float {\ce getchannel} (int x, int y, int z, int c, \\
  \bigspc\spc WrapMode wrap=WrapBlack) const}
Returns the value of pixel {\cf x, y, z}, channel {\cf c}.  

The {\cf wrap} describes what value should be returned if the {\cf x, y, z}
coordinates are outside the pixel data window, and may be one of:
{\cf WrapBlack}, {\cf WrapClamp}, {\cf WrapPeriodic}, or {\cf WrapMirror}.
\apiend


\apiitem{void {\ce getpixel} (int x, int y, int z, float *pixel, \\
  \bigspc\spc int maxchannels=1000, WrapMode wrap=WrapBlack) const}
Retrieves pixel ({\cf x, y, z}), placing its contents in
{\cf pixel[0..n-1]}, where $n$ is the smaller of {\cf maxchannels}
or the actual number of channels stored in the buffer.  It is up to
the application to ensure that {\cf pixel} points to enough memory
to hold the required number of channels.

The {\cf wrap} describes what value should be returned if the {\cf x, y, z}
coordinates are outside the pixel data window, and may be one of:
{\cf WrapBlack}, {\cf WrapClamp}, {\cf WrapPeriodic}, or {\cf WrapMirror}.
\apiend

\apiitem{void {\ce interppixel} (float x, float y, float *pixel, \\
  \bigspc\bigspc                            WrapMode wrap=WrapBlack) const \\
void {\ce interppixel_bicubic} (float x, float y, float *pixel, \\
  \bigspc\bigspc                            WrapMode wrap=WrapBlack) const}
Sample the image plane at coordinates $(x,y)$,
using linear interpolation between pixels by default, or B-spline
bicubic interpolation for the {\cf _bicubic} varieties, placing the result in
{\cf pixel[0..n-1]}, where $n$ is the smaller of {\cf maxchannels}
or the actual number of channels stored in the buffer.  It is up to
the application to ensure that {\cf pixel} points to enough memory
to hold the required number of channels.
The sampling location is specified in the floating-point pixel coordinate
system, where pixel $(i,j)$ is centered at image plane coordinate $(i+0.5,
j+0.5)$.

The {\cf wrap} describes how the image function should be computed
outside the boundaries of the pixel data window, and may be one of:
{\cf WrapBlack}, {\cf WrapClamp}, {\cf WrapPeriodic}, or {\cf WrapMirror}.
\apiend

\apiitem{void {\ce interppixel_NDC} (float s, float t, float *pixel, \\
  \bigspc\bigspc                            WrapMode wrap=WrapBlack) const \\
void {\ce interppixel_bicubic_NDC} (float s, float t, float *pixel, \\
  \bigspc\bigspc                            WrapMode wrap=WrapBlack) const}
Sample the image plane at coordinates $(s,t)$, similar to the
{\cf\small interppixel} and {\cf\small interppixel_bicubic} methods, but
specifying location using the ``NDC'' (normalized
device coordinate) system where (0,0) is the upper left corner of the full
(a.k.a. ``display'') window and (1,1) is the lower right corner of the
full/display window.
\apiend

\apiitem{void {\ce setpixel} (int x, int y, int z, const float *pixel, int maxchannels=1000)}
Set the pixel with coordinates {\cf (x, y, z)} to have the values
{\cf pixel[0..n-1]}.  The number of channels, {\cf n}, is the minimum of
{\cf minchannels} and the actual number of channels in the image.
\apiend


\subsection*{Deep data in an \ImageBuf}

\apiitem{bool {\ce deep} () const}
Returns {\cf true} if the \ImageBuf holds a ``deep'' image, {\cf false}
if the \ImageBuf holds an ordinary pixel-based image.
\apiend

\apiitem{int {\ce deep_samples} (int x, int y, int z=0) const}
Returns the number of deep samples for the given pixel, or 0 if there
are no deep samples for that pixel (including if the pixel coordinates
are outside the data area).  For non-deep images, it will always return 0.
\apiend

\apiitem{void {\ce set_deep_samples} (int x, int y, int z, int nsamples)}
Set the number of samples for pixel {\cf (x,y,z)}. If data has already been
allocated, this is equivalent to inserting or erasing samples.
\apiend

\apiitem{void {\ce deep_insert_samples} (int x, int y, int z, int samplepos, int nsamples)}
Insert {\cf nsamples} new samples, starting at position {\cf samplepos} of
pixel {\cf (x,y,z)}.
\apiend

\apiitem{void {\ce deep_erase_samples} (int x, int y, int z, int samplepos, int nsamples)}
Remove {\cf nsamples} new samples, starting at position {\cf samplepos} of
pixel {\cf (x,y,z)}.
\apiend

\apiitem{float {\ce deep_value} (int x, int y, int z, int c, int s) const \\
uint32_t {\ce deep_value_uint} (int x, int y, int z, int c, int s) const}
Return the value of sample {\cf s} of channel {\cf c}
of pixel {\cf (x,y,z)}.  Return {\cf 0} if not a deep image or if the
pixel coordinates, channel number, or sample number are out of range, or
if it has no deep samples.  You are expected to call the {\cf float} or
{\cf uint32_t} version based on the data type of channel {\cf c}.
\apiend

\apiitem{void {\ce set_deep_value} (int x, int y, int z, int c, int s, float value) const \\
void {\ce set_deep_value} (int x, int y, int z, int c, int s, uint32_t value) const}
Set the value of sample {\cf s} of channel {\cf c}
of pixel {\cf (x,y,z)}. It is expected that you choose the {\cf float}
or {\cf uint32_t} variety of the call based on the data type of channel {\cf c}.
\apiend

\apiitem{const void *{\ce deep_pixel_ptr} (int x, int y, int z, int c, int s=0) const}
Returns a pointer to the raw pixel data pixel {\cf (x,y,z)}, channel {\cf c},
sample {\cf s}.  This will return {\cf NULL} if the pixel
coordinates or channel number are out of range, if the pixel/channel has
no deep samples, or if the image is not deep. Use with caution --- these
pointers may be invalidated by calls that adjust the number of samples in
any pixel.
\apiend

\apiitem{DeepData\& {\ce deepdata} () \\
const DeepData\& {\ce deepdata} () const}
Returns a reference to the underlying {\cf DeepData} for a deep image.
\apiend


\section{Miscellaneous}

\apiitem{void {\ce error} (const char *format, ...) const}
This can be used to register an error associated with this \ImageBuf.
\apiend

\apiitem{bool {\ce has_error} (void) const}
Returns {\cf true} if the \ImageBuf has had an error and has an error
message to retrieve via {\cf geterror()}.
\apiend

\apiitem{std::string {\ce geterror} (void) const}
Return the text of all error messages issued since {\cf geterror()} was
called (or an empty string if no errors are pending).  This also
clears the error message for next time.
\apiend

\apiitem{void *{\ce localpixels} (); \\
    const void *{\ce localpixels} () const;}
Returns a raw pointer to the ``local'' pixel memory, if they are fully
in RAM and not backed by an \ImageCache (in which case, {\cf nullptr} will
be returned).  You can also test it like a {\cf bool} to find out if
pixels are local.
\apiend

\apiitem{const void *{\ce pixeladdr} (int x, int y, int z=0, int ch=0) const \\
void *{\ce pixeladdr} (int x, int y, int z=0, int ch=0)}
Return the address where pixel {\cf (x,y,z)}, channel {\cf ch} is stored in
the local image buffer memory.
Use with extreme caution!  Will return {\cf nullptr} if the pixel values
aren't local (for example, if backed by an \ImageCache).
\apiend

\apiitem{int {\ce pixelindex} (int x, int y, int z, bool check_range=false) const}
Return the index of pixel (x,y,z). If {\cf check_range} is {\cf true},
return -1 for an invalid coordinate that is not within the data window.
\apiend

\apiitem{static WrapMode {\ce WrapMode_from_string} (string_view name)}
Return the {\cf WrapMode} corresponding to the name (\qkw{default},
\qkw{black}, \qkw{clamp}, \qkw{periodic}, \qkw{mirror}). For an unknown
name, this will return {\cf WrapDefault}.
\apiend



\section{Iterators -- the fast way of accessing individual pixels}

Sometimes you need to visit every pixel in an \ImageBuf (or at least,
every pixel in a large region).  Using the {\cf getpixel} and {\cf
  setpixel} for this purpose is simple but very slow.  But \ImageBuf
provides templated {\cf Iterator} and {\cf ConstIterator} types
that are very inexpensive and hide all the details of local versus
cached storage.

An {\cf Iterator} is associated with a particular \ImageBuf.  
The {\cf Iterator} has a \emph{current pixel} coordinate that it is
visiting, and an \emph{iteration range} that describes a rectangular
region of pixels that it will visits as it advances.  It always starts
at the upper left corner of the iteration region.  We say that
the iterator is \emph{done} after it has visited every pixel in its
iteration range.  We say that a pixel coordinate \emph{exists} if it is
within the pixel data window of the \ImageBuf.  We say that a pixel
coordinate is \emph{valid} if it is within the iteration range of the
iterator.

The {\cf ImageBuf::ConstIterator} is identical to the {\cf Iterator},
except that {\cf ConstIterator} may be used on a {\cf const ImageBuf}
and may not be used to alter the contents of the \ImageBuf.  For 
simplicity, the remainder of this section will only discuss the 
{\cf Iterator}.

The {\cf Iterator<BUFT,USERT>} is templated based on two types: {\cf
  BUFT} the type of the data stored in the \ImageBuf, and {\cf USERT}
type type of the data that you want to manipulate with your code.  {\cf
  USERT} defaults to {\cf float}, since usually you will want to do all
your pixel math with {\cf float}.  We will thus use {\cf Iterator<T>}
synonymously with {\cf Iterator<T,float>}.

For the remainder of this section, we will assume that you have a
{\cf float}-based \ImageBuf, for example, if it were set up like this:

\begin{code}
ImageBuf buf ("myfile.exr");
buf.read (0, 0, true, TypeDesc::FLOAT);
\end{code}


\apiitem{Iterator<BUFT> (ImageBuf \&buf, WrapMode wrap=WrapDefault)}
Initialize an iterator that will visit every pixel in the data window
of {\cf buf}, and start it out pointing to the upper left corner of
the data window.  The {\cf wrap} describes what values will be retrieved
if the iterator is positioned outside the data window of the buffer.
\apiend

\apiitem{Iterator<BUFT> (ImageBuf \&buf, const ROI \&roi, WrapMode wrap=WrapDefault)}
Initialize an iterator that will visit every pixel of {\cf buf} 
within the region
described by {\cf roi}, and start it out pointing to pixel ({\cf roi.xbegin, roi.ybegin, roi.zbegin}).
The {\cf wrap} describes what values will be retrieved
if the iterator is positioned outside the data window of the buffer.
\apiend

\apiitem{Iterator<BUFT> (ImageBuf \&buf, int x, int y, int z, WrapMode wrap=WrapDefault)}
Initialize an iterator that will visit every pixel in the data window
of {\cf buf}, and start it out pointing to pixel ({\cf x, y, z}).
The {\cf wrap} describes what values will be retrieved
if the iterator is positioned outside the data window of the buffer.
\apiend

\apiitem{Iterator::operator++ ()}
The {\cf ++} operator advances the iterator to the next pixel in its
iteration range.  (Both prefix and postfix increment operator are
supported.)
\apiend

\apiitem{bool Iterator::done () const}
Returns {\cf true} if the iterator has completed its visit of all pixels
in its iteration range.
\apiend

\apiitem{ROI Iterator::range () const}
Returns the iteration range of the iterator, expressed as an \ROI.
\apiend

\apiitem{int Iterator::x () const \\
int Iterator::y () const \\
int Iterator::z () const}
Returns the $x$, $y$, and $z$ pixel coordinates, respectively, of the
pixel that the iterator is currently visiting.
\apiend

\apiitem{bool Iterator::valid () const}
Returns {\cf true} if the iterator's current pixel coordinates 
are within its iteration range.
\apiend

\apiitem{bool Iterator::valid (int x, int y, int z=0) const}
Returns {\cf true} if pixel coordinate ({\cf x, y, z}) are within the
iterator's iteration range (regardless of where the iterator itself
is currently pointing).
\apiend

\apiitem{bool Iterator::exists () const}
Returns {\cf true} if the iterator's current pixel coordinates 
are within the data window of the \ImageBuf.
\apiend

\apiitem{bool {\ce Iterator}::exists (int x, int y, int z=0) const}
Returns {\cf true} if pixel coordinate ({\cf x, y, z}) are within the
pixel data window of the \ImageBuf (regardless of where the iterator itself
is currently pointing).
\apiend

\apiitem{USERT\& Iterator::operator[] (int i)}
The value of channel {\cf i} of the current pixel.  (The wrap
mode, set up when the iterator was constructed, determines what value
is returned if the iterator points outside the pixel data window of
its buffer.)
\apiend

\apiitem{int Iterator::deep_samples () const}
For deep images only, retrieves the number of deep samples for the
current pixel.
\apiend

\apiitem{void Iterator::set_deep_samples ()}
For deep images only (and non-const \ImageBuf), set the number of deep
samples for the current pixel. This only is useful if the \ImageBuf has
not yet had the {\cf deep_alloc()} method called.
\apiend

\apiitem{USERT Iterator::deep_value (int c, int s) const \\
uint32_t Iterator::deep_value_int (int c, int s) const}
For deep images only, returns the value of channel {\cf c}, sample
number {\cf s}, at the current pixel.
\apiend

\apiitem{void Iterator::set_deep_value (int c, int s, float value) \\
void Iterator::set_deep_value (int c, int s, uint32_t value)}
For deep images only (and non-cconst \ImageBuf, sets the value of channel
{\cf c}, sample number {\cf s}, at the current pixel. This only is useful
if the \ImageBuf has already had the {\cf deep_alloc()} method called.
\apiend

\subsection*{Example: Visiting all pixels to compute an average color}

\begin{code}
void print_channel_averages (const std::string &filename)
{
    // Set up the ImageBuf and read the file
    ImageBuf buf (filename);
    bool ok = buf.read (0, 0, true, TypeDesc::FLOAT);  // Force a float buffer
    if (! ok)
        return;

    // Initialize a vector to contain the running total
    int nc = buf.nchannels();
    std::vector<float> total (n, 0.0f);

    // Iterate over all pixels of the image, summing channels separately
    for (ImageBuf::ConstIterator<float> it (buf);  ! it.done();  ++it)
        for (int c = 0;  c < nc;  ++c)
            total[c] += it[c];

    // Print the averages
    imagesize_t npixels = buf.spec().image_pixels();
    for (int c = 0;  c < nc;  ++c)
        std::cout << "Channel " << c << " avg = " (total[c] / npixels) << "\n";
}
\end{code}


\subsection*{Example: Set all pixels in a region to black}
\label{makeblackexample}

\begin{code}
bool make_black (ImageBuf &buf, ROI region)
{
    if (buf.spec().format != TypeDesc::FLOAT)
        return false;    // Assume it's a float buffer

    // Clamp the region's channel range to the channels in the image
    roi.chend = std::min (roi.chend, buf.nchannels);

    // Iterate over all pixels in the region...
    for (ImageBuf::Iterator<float> it (buf, region);  ! it.done();  ++it) {
        if (! it.exists())   // Make sure the iterator is pointing
            continue;        //   to a pixel in the data window
        for (int c = roi.chbegin;  c < roi.chend;  ++c)
            it[c] = 0.0f;  // clear the value
    }
    return true;
}
\end{code}


\section{Dealing with buffer data types}

The previous section on iterators presented examples and discussion
based on the assumption that the \ImageBuf was guaranteed to store {\cf
float} data and that you wanted all math to also be done as {\cf float}
computations.  Here we will explain how to deal with buffers and files
that contain different data types.

\subsection*{Strategy 1: Only have {\cf float} data in your \ImageBuf}

\noindent When creating your own buffers, make sure they are {\cf float}:

\begin{code}
    ImageSpec spec (640, 480, 3, TypeDesc::FLOAT); // <-- float buffer
    ImageBuf buf ("mybuf", spec);
\end{code}

\noindent When using \ImageCache-backed buffers, force the \ImageCache
to convert everything to {\cf float}:

\begin{code}
    // Just do this once, to set up the cache:
    ImageCache *cache = ImageCache::create (true /* shared cache */);
    cache->attribute ("forcefloat", 1);
    ...
    ImageBuf buf ("myfile.exr");   // Backed by the shared cache
\end{code}

\noindent Or force the read to convert to {\cf float} in the buffer if
it's not a native type that would automatically stored as a {\cf float}
internally to the \ImageCache:\footnote{\ImageCache only supports a
limited set of types internally, currently only FLOAT and UINT8, and all
other data types are converted to these automatically as they are read
into the cache.}

\begin{code}
    ImageBuf buf ("myfile.exr");   // Backed by the shared cache
    buf.read (0, 0, false /* don't force read to local mem */,
              TypeDesc::FLOAT /* but do force conversion to float*/);
\end{code}

\noindent Or force a read into local memory unconditionally (rather
than relying on the \ImageCache), and convert to {\cf float}:

\begin{code}
    ImageBuf buf ("myfile.exr");
    buf.read (0, 0, true /*force read*/,
              TypeDesc::FLOAT /* force conversion */);
\end{code}

\subsection*{Strategy 2: Template your iterating functions based on
buffer type}

Consider the following alternate version of the {\cf make_black} function
from Section~\ref{makeblackexample}:

\begin{code}
template<type BUFT>
static bool make_black_impl (ImageBuf &buf, ROI region)
{
    // Clamp the region's channel range to the channels in the image
    roi.chend = std::min (roi.chend, buf.nchannels);

    // Iterate over all pixels in the region...
    for (ImageBuf::Iterator<BUFT> it (buf, region);  ! it.done();  ++it) {
        if (! it.exists())   // Make sure the iterator is pointing
            continue;        //   to a pixel in the data window
        for (int c = roi.chbegin;  c < roi.chend;  ++c)
            it[c] = 0.0f;  // clear the value
    }
    return true;
}

bool make_black (ImageBuf &buf, ROI region)
{
    if (buf.spec().format == TypeDesc::FLOAT)
        return make_black_impl<float> (buf, region);
    else if (buf.spec().format == TypeDesc::HALF)
        return make_black_impl<half> (buf, region);
    else if (buf.spec().format == TypeDesc::UINT8)
        return make_black_impl<unsigned char> (buf, region);
    else if (buf.spec().format == TypeDesc::UINT16)
        return make_black_impl<unsigned short> (buf, region);
    else {
        buf.error ("Unsupported pixel data format %s", buf.spec().format);
        retrn false;
    }
}
\end{code}

In this example, we make an implementation that is templated on
the buffer type, and then a wrapper that calls the appropriate
template specialization for each of 4 common types (and logs
an error in the buffer for any other types it encounters).

In fact, {\cf imagebufalgo_util.h} provides a macro to do this (and
several variants, which will be discussed in more detail in the next
chapter).  You could rewrite the example even more simply:

\begin{code}
#include <OpenImageIO/imagebufalgo_util.h>

template<type BUFT>
static bool make_black_impl (ImageBuf &buf, ROI region)
{
    ... same as before ...
}

bool make_black (ImageBuf &buf, ROI region)
{
    bool ok;
    OIIO_DISPATCH_COMMON_TYPES (ok, "make_black", make_black_impl,
                                 buf.spec().format, buf, region);
    return ok;
}
\end{code}

\noindent This other type-dispatching helper macros will be discussed in more
detail in Chapter~\ref{chap:imagebufalgo}.

\index{ImageBuf|)}
\index{Image Buffers|)}

\chapwidthend
