ImageBufAlgo: Image Processing¶
ImageBufAlgo is a set of image processing functions that operate on
ImageBuf’s. The functions are declared in the header file
OpenImageIO/imagebufalgo.h
and are declared in the
namespace ImageBufAlgo
.
ImageBufAlgo common principles¶
This section explains the general rules common to all ImageBufAlgo functions. Only exceptions to these rules will be explained in the subsequent listings of all the individual ImageBufAlgo functions.
Return values and error messages¶
Most ImageBufAlgo functions that produce image data come in two forms:
Return an ImageBuf.
The return value is a new ImageBuf containing the result image. In this case, an entirely new image will be created to hold the result. In case of error, the result image returned can have any error conditions checked with
has_error()
andgeterror()
.// Method 1: Return an image result ImageBuf dst = ImageBufAlgo::over (fg, bg); if (dst.has_error()) std::cout << "error: " << dst.geterror() << "\n";
# Method 1: Return an image result fg = ImageBuf("fg.exr") bg = ImageBuf("bg.exr") dst = ImageBufAlgo.over (fg, bg) if dst.has_error() : print("error:", dst.geterror())
Pass a destination ImageBuf reference as the first parameter.
The function is passed a destination ImageBuf where the results will be stored, and the return value is a
bool
that istrue
if the function succeeds orfalse
if the function fails. Upon failure, the destination ImageBuf (the one that is being altered) will have an error message set.// Method 2: Write into an existing image ImageBuf fg ("fg.exr"), bg ("bg.exr"); ImageBuf dst; // will be the output image bool ok = ImageBufAlgo::over (dst, fg, bg); if (! ok) std::cout << "error: " << dst.geterror() << "\n";
# Method 2: Write into an existing image fg = ImageBuf("fg.exr") bg = ImageBuf("bg.exr") dst = ImageBuf() # will be the output image ok = ImageBufAlgo.over (dst, fg, bg) if not ok : print("error:", dst.geterror())
The first option (return an ImageBuf directly) is a more compact and
intuitive notation that is natural for most simple uses. But the second
option (pass an ImageBuf&
referring to an existing destination) offers
additional flexibility, including more careful control over allocations, the
ability to partially overwrite regions of an existing image, and the ability
for the destination image to also be one of the input images (for example,
add(A,A,B)
adds B into existing image A, with no third image allocated at
all).
For a small minority of ImageBufAlgo functions, there are only input images,
and no image outputs (e.g., isMonochrome()
). In such cases, the error
message should be retrieved from the first input image.
Region of interest¶
Most ImageBufAlgo functions take an optional ROI parameter that restricts
the operation to a range in x, y, z, and channels. The default-constructed
ROI (also known as ROI::All()
) means no region restriction – the whole
image will be copied or altered.
For ImageBufAlgo functions that write into a destination ImageBuf parameter and it is already initialized (i.e. allocated with a particular size and data type), the operation will be performed on the pixels in the destination that overlap the ROI, leaving pixels in the destination which are outside the ROI unaltered.
For ImageBufAlgo functions that return an ImageBuf directly, or if their
dst
parameter is an uninitialized ImageBuf, the ROI (if set) determines
the size of the result image. If the ROI is the default All
, the result
image size will be the union of the pixel data windows of the input images
and have a data type determind by the data types of the input images.
Most ImageBufAlgo functions also respect the chbegin
and chend
members
of the ROI, thus restricting the channel range on which the operation is
performed. The default ROI constructor sets up the ROI to specify that the
operation should be performed on all channels of the input image(s).
Constant and per-channel values¶
Many ImageBufAlgo functions take per-channel constant-valued arguments (for
example, a fill color). These parameters are passed as cspan<float>
. These
are generally expected to have length equal to the number of channels. But
you may also pass a single float which will be used as the value for all
channels. (More generally, what is happening is that the last value supplied
is replicated for any missing channel.)
Some ImageBufAlgo functions have parameters of type Image_or_Const
, which
may take either an ImageBuf reference, or a per-channel constant, or a
single constant to be used for all channels.
Multithreading¶
All ImageBufAlgo functions take an optional nthreads
parameter that
signifies the maximum number of threads to use to parallelize the
operation. The default value for nthreads
is 0, which signifies
that the number of thread should be the OIIO global default set by
OIIO::attribute()
(see Section~ref{sec:attribute:threads}), which
itself defaults to be the detected level of hardware concurrency (number
of cores available).
Generally you can ignore this parameter (or pass 0), meaning to use all the cores available in order to perform the computation as quickly as possible. The main reason to explicitly pass a different number (generally 1) is if the application is multithreaded at a high level, and the thread calling the ImageBufAlgo function just wants to continue doing the computation without spawning additional threads, which might tend to crowd out the other application threads.
Pattern generation¶
For the ImageBufAlgo functions in this section, there is no “source” image.
Therefore, either an initialized dst
must be supplied (to give a pre-
allocated size and data type of the image), or else it is strictly necessary
to supply an ROI parameter to specify the size of the new image (the data
type in this case will always be float
). It is an error if one of the
pattern generation ImageBufAlgo functions is neither supplied a
pre-allocated dst
nor a non-default ROI.
zero() – create a black image¶
-
ImageBuf
OIIO::ImageBufAlgo
::
zero
(ROI roi, int nthreads = 0)¶ Create an all-black
float
image of size and channels as described by the ROI.
Examples:
// Create a new 3-channel, 512x512 float image filled with 0.0 values. ImageBuf zero = ImageBufAlgo::zero (ROI(0,512,0,512,0,1,0,3)); // Zero out an existing buffer, keeping it the same size and data type ImageBuf A = ...; ... ImageBufAlgo::zero (A); // Zero out a rectangular region of an existing buffer ImageBufAlgo::zero (A, ROI (0, 100, 0, 100)); // Zero out just the green channel, leave everything else the same ROI roi = A.roi (); roi.chbegin = 1; // green roi.chend = 2; // one past the end of the channel region ImageBufAlgo::zero (A, roi);Result-as-parameter version:
fill() – fill a region with a solid color or gradient¶
-
group
fill
Fill an image region with given channel values, either returning a new image or altering the existing
dst
image within the ROI. Note that the values arrays start with channel 0, even if the ROI indicates that a later channel is the first to be changed.Three varieties of fill() exist: (a) a single set of channel values that will apply to the whole ROI, (b) two sets of values that will create a linearly interpolated gradient from top to bottom of the ROI, (c) four sets of values that will be bilinearly interpolated across all four corners of the ROI.
Examples:
// Create a new 640x480 RGB image, with a top-to-bottom gradient // from red to pink float pink[3] = { 1, 0.7, 0.7 }; float red[3] = { 1, 0, 0 }; ImageBuf A = ImageBufAlgo::fill (red, pink, ROI(0, 640, 0, 480, 0, 1, 0, 3)); // Draw a filled red rectangle overtop existing image A. ImageBufAlgo::fill (A, red, ROI(50,100, 75, 175));
checker() – make a checker pattern¶
-
ImageBuf
OIIO::ImageBufAlgo
::
checker
(int width, int height, int depth, cspan<float> color1, cspan<float> color2, int xoffset, int yoffset, int zoffset, ROI roi, int nthreads = 0)¶ Create a checkerboard pattern of size given by
roi
, with origin given by theoffset
values, checker size given by thewidth
,height
,depth
values, and alternating betweencolor1[]
andcolor2[]
. The pattern is defined in abstract “image space” independently of the pixel data window ofdst
or the ROI.
Examples:
// Create a new 640x480 RGB image, fill it with a two-toned gray // checkerboard, the checkers being 64x64 pixels each. ImageBuf A (ImageSpec(640, 480, 3, TypeDesc::FLOAT); float dark[3] = { 0.1, 0.1, 0.1 }; float light[3] = { 0.4, 0.4, 0.4 }; ImageBufAlgo::checker (A, 64, 64, 1, dark, light, 0, 0, 0);Result-as-parameter version:
noise() – make a noise pattern¶
-
ImageBuf
OIIO::ImageBufAlgo
::
noise
(string_view noisetype, float A = 0.0f, float B = 0.1f, bool mono = false, int seed = 0, ROI roi = {}, int nthreads = 0)¶ Return an image of “noise” in every pixel and channel specified by the roi. There are several noise types to choose from, and each behaves differently and has a different interpretation of the
A
andB
parameters:“gaussian” adds Gaussian (normal distribution) noise values with mean value A and standard deviation B.
”uniform” adds noise values uniformly distributed on range [A,B).
”salt” changes to value A a portion of pixels given by B.
If the
mono
flag is true, a single noise value will be applied to all channels specified byroi
, but ifmono
is false, a separate noise value will be computed for each channel in the region.The random number generator is actually driven by a hash on the “image
space” coordinates and channel, independently of the pixel data window of
dst
or the ROI. Choosing different seed values will result in a different pattern, but for the same seed value, the noise at a given pixel coordinate (x,y,z) channel c will is completely deterministic and repeatable.
Examples:
// Create a new 256x256 field of grayscale uniformly distributed noise on [0,1) ImageBuf A = ImageBufAlgo::noise ("uniform", 0.0f /*min*/, 1.0f /*max*/, true /*mono*/, 1 /*seed*/, ROI(0,256,0,256,0,1,0,3)); // Add color Gaussian noise to an existing image ImageBuf B ("tahoe.jpg"); ImageBufAlgo::noise (B, "gaussian", 0.0f /*mean*/, 0.1f /*stddev*/, false /*mono*/, 1 /*seed*/); // Use salt and pepper noise to make occasional random dropouts ImageBuf C ("tahoe.jpg"); ImageBufAlgo::noise (C, "salt", 0.0f /*value*/, 0.01f /*portion*/, true /*mono*/, 1 /*seed*/);Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
noise
(ImageBuf &dst, string_view noisetype, float A = 0.0f, float B = 0.1f, bool mono = false, int seed = 0, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
Drawing shapes: points, lines, boxes¶
-
bool
OIIO::ImageBufAlgo
::
render_point
(ImageBuf &dst, int x, int y, cspan<float> color = 1.0f, ROI roi = {}, int nthreads = 0)¶ Render a single point at (x,y) of the given color “over” the existing image
dst
. If there is no alpha channel, the color will be written unconditionally (as if the alpha is 1.0).
Examples:
ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); float red[4] = { 1, 0, 0, 1 }; ImageBufAlgo::render_point (A, 50, 100, red);
-
bool
OIIO::ImageBufAlgo
::
render_line
(ImageBuf &dst, int x1, int y1, int x2, int y2, cspan<float> color = 1.0f, bool skip_first_point = false, ROI roi = {}, int nthreads = 0)¶ Render a line from pixel (
x1
,y1
) to (x2
,y2
) intodst
, doing an “over” of the color (if it includes an alpha channel) onto the existing data indst
. Thecolor
should include as many values asroi.chend-1
. The ROI can be used to limit the pixel area or channels that are modified, and default to the entirety ofdst
. Ifskip_first_point
istrue
, the first point (x1
,y1
) will not be drawn (this can be helpful when drawing poly-lines, to avoid double-rendering of the vertex positions).
-
bool
OIIO::ImageBufAlgo
::
render_box
(ImageBuf &dst, int x1, int y1, int x2, int y2, cspan<float> color = 1.0f, bool fill = false, ROI roi = {}, int nthreads = 0)¶ Render a filled or unfilled box with corners at pixels (
x1
,y1
) and (x2
,y2
) intodst
, doing an “over” of the color (if it includes an alpha channel) onto the existing data indst
. Thecolor
must include as many values asroi.chend-1
. The ROI can be used to limit the pixel area or channels that are modified, and default to the entirety ofdst
. Iffill
istrue
, the box will be completely filled in, otherwise only its outlien will be drawn.
Drawing text¶
-
bool
OIIO::ImageBufAlgo
::
render_text
(ImageBuf &dst, int x, int y, string_view text, int fontsize = 16, string_view fontname = "", cspan<float> textcolor = 1.0f, TextAlignX alignx = TextAlignX::Left, TextAlignY aligny = TextAlignY::Baseline, int shadow = 0, ROI roi = {}, int nthreads = 0)¶ Render a text string (encoded as UTF-8) into image
dst
. If thedst
image is not yet initialized, it will be initialized to be a black background exactly large enough to contain the rasterized text. Ifdst
is already initialized, the text will be rendered into the existing image by essentially doing an “over” of the character into the existing pixel data.- Parameters
dst
: Destination ImageBuf text is rendered into this image.x/y
: The position to place the text.text
: The text to draw.fontsize/fontname
: Size and name of the font. If the name is not a full pathname to a font file, it will search for a matching font, defaulting to some reasonable system font if not supplied at all), and with a nominal height of fontsize (in pixels).textcolor
: Color for drawing the text, defaulting to opaque white (1.0,1.0,…) in all channels if not supplied. If provided, it is expected to point to a float array of length at least equal toR.spec().nchannels
, or defaults will be chosen for you).alignx/aligny
: The default behavior is to align the left edge of the character baseline to (x
,y
). Optionally,alignx
andaligny
can override the alignment behavior, with horizontal alignment choices of TextAlignX::Left, Right, and Center, and vertical alignment choices of Baseline, Top, Bottom, or Center.shadow
: If nonzero, a “drop shadow” of this radius will be used to make the text look more clear by dilating the alpha channel of the composite (makes a black halo around the characters).
Examples:
ImageBufAlgo::render_text (ImgA, 50, 100, "Hello, world"); float red[] = { 1, 0, 0, 1 }; ImageBufAlgo::render_text (ImgA, 100, 200, "Go Big Red!", 60, "Arial Bold", red); float white[] = { 1, 1, 1, 1 }; ImageBufAlgo::render_text (ImgB, 320, 240, "Centered", 60, "Arial Bold", white, TextAlignX::Center, TextAlignY::Center);
-
ROI
OIIO::ImageBufAlgo
::
text_size
(string_view text, int fontsize = 16, string_view fontname = "")¶ The helper function
text_size()
merely computes the dimensions of the text, returning it as an ROI relative to the left side of the baseline of the first character. Only thex
andy
dimensions of the ROI will be used. The x dimension runs from left to right, and y runs from top to bottom (image coordinates). For a failure (such as an invalid font name), the ROI will returnfalse
if you call itsdefined()
method.
Example:
// Render text centered in the image, using text_size to find out // the size we will need and adjusting the coordinates. ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); ROI Aroi = A.roi(); ROI size = ImageBufAlgo::text_size ("Centered", 48, "Courier New"); if (size.defined()) { int x = Aroi.xbegin + Aroi.width()/2 - (size.xbegin + size.width()/2); int y = Aroi.ybegin + Aroi.height()/2 - (size.ybegin + size.height()/2); ImageBufAlgo::render_text (A, x, y, "Centered", 48, "Courier New"); }
Image transformations and data movement¶
Shuffling channels¶
-
ImageBuf
OIIO::ImageBufAlgo
::
channels
(const ImageBuf &src, int nchannels, cspan<int> channelorder, cspan<float> channelvalues = {}, cspan<std::string> newchannelnames = {}, bool shuffle_channel_names = false, int nthreads = 0)¶ Generic channel shuffling: return (or store in
dst
) a copy ofsrc
, but with channels in the orderchannelorder[0..nchannels-1]
(or set to a constant value, designated bychannelorder[0] = -1
and having the fill value inchannelvalues[i]
. In-place operation is allowed (i.e.,dst
andsrc
the same image, but an extra copy will occur).- Parameters
nchannels
: The total number of channels that will be set up in thedst
image.channelorder
: For each channel indst
, the index of hesrc
channel from which to copy. Anychannelorder[i]
< 0 indicates that the channeli
should be filled with constant valuechannelvalues[i]
rather than copy any channel fromsrc
. Ifchannelorder
itself is empty, the implied channel order will be{0, 1, ..., nchannels-1}
, meaning that it’s only renaming channels, not reordering them.channelvalues
: Fill values for color channels in whichchannelorder[i]
< 0.newchannelnames
: An array of new channel names. Channels for which this specifies an empty string will have their name taken from thesrc
channel that was copied. Ifnewchannelnames
is entirely empty, all channel names will simply be copied fromsrc
.shuffle_channel_names
: If true, the channel names will be taken from the corresponding channels of the source image be careful with this, shuffling both channel ordering and their names could result in no semantic change at all, if you catch the drift. If false (the default), If false, the resultingdst
image will have default channel names in the usual order (“R”, “G”, etc.), but i
Examples:
// Copy the first 3 channels of an RGBA, drop the alpha ImageBuf RGBA (...); // assume it's initialized, 4 chans ImageBuf RGB = ImageBufAlgo::channels (RGBA, 3, {} /*default ordering*/); // Copy just the alpha channel, making a 1-channel image ImageBuf Alpha = ImageBufAlgo::channels (RGBA, 1, 3 /*alpha_channel*/); // Swap the R and B channels into an existing image ImageBuf BRGA; int channelorder[] = { 2 /*B*/, 1 /*G*/, 0 /*R*/, 3 /*A*/ }; ImageBufAlgo::channels (BRGA, RGBA, 4, channelorder); // Add an alpha channel with value 1.0 everywhere to an RGB image, // keep the other channels with their old ordering, values, and // names. int channelorder[] = { 0, 1, 2, -1 /*use a float value*/ }; float channelvalues[] = { 0 /*ignore*/, 0 /*ignore*/, 0 /*ignore*/, 1.0 }; std::string channelnames[] = { "", "", "", "A" }; ImageBuf RGBA = ImageBufAlgo::channels (RGB, 4, channelorder, channelvalues, channelnames); // Simple copying of channels from dst to src but fixing the number // of channels dropping those in excess, or adding 0.0-filled channels // if there is a shortfall) ImageBuf out = ImageBufAlgo::channels (RGBA, nchannels, {}, {}, {}, true);Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
channels
(ImageBuf &dst, const ImageBuf &src, int nchannels, cspan<int> channelorder, cspan<float> channelvalues = {}, cspan<std::string> newchannelnames = {}, bool shuffle_channel_names = false, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
ImageBuf
OIIO::ImageBufAlgo
::
channel_append
(const ImageBuf &A, const ImageBuf &B, ROI roi = {}, int nthreads = 0)¶ Append the channels of
A
andB
together intodst
over the region of interest. If the region passed is uninitialized (the default), it will be interpreted as being the union of the pixel windows ofA
andB
(and all channels of both images). Ifdst
is not already initialized, it will be resized to be big enough for the region.
Examples:
ImageBuf RGBA (...); // assume initialized, 4 channels ImageBuf Z (...); // assume initialized, 1 channel ImageBuf RGBAZ = ImageBufAlgo::channel_append (RGBA, Z);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
copy
(const ImageBuf &src, TypeDesc convert = TypeUnknown, ROI roi = {}, int nthreads = 0)¶ Return the specified region of pixels of
src
as specified byroi
(which will default to the whole ofsrc
, optionally with the pixel type overridden by convert (if it is notTypeUnknown
).
Examples:
// Set B to be A, but converted to float ImageBuf A (...); // Assume initialized ImageBuf B = ImageBufAlgo::copy (A, TypeDesc::FLOAT);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
crop
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Return the specified region of
src
as an image, without altering its position in the image plane.Pixels from
src
which are outsideroi
will not be copied, and new black pixels will be added for regions ofroi
which were outside the data window ofsrc
.Note that the
crop
operation does not actually move the pixels on the image plane or adjust the full/display window; it merely restricts which pixels are copied fromsrc
todst
. (Note the difference compared tocut()
).
Examples:
// Set B to be the upper left 200x100 region of A ImageBuf A (...); // Assume initialized ImageBuf B = ImageBufAlgo::crop (A, ROI(0,200,0,100));Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
cut
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Return the designated region of
src
, but repositioned to the image origin and with the full/display window set to exactly cover the new pixel data window. (Note the difference compared tocrop()
).
Examples:
// Set B to be the 100x100 region of A with origin (50,200). ImageBuf A (...); // Assume initialized ImageBuf B = ImageBufAlgo::cut (A, ROI(50,250,200,300)); // Note: B will have origin 0,0, NOT (50,200).Result-as-parameter version:
-
bool
OIIO::ImageBufAlgo
::
paste
(ImageBuf &dst, int xbegin, int ybegin, int zbegin, int chbegin, const ImageBuf &src, ROI srcroi = {}, int nthreads = 0)¶ Copy
src
pixels withinsrcroi
into thedst
image, offset so that source location (0,0,0) will be copied to destination location (xbegin
,ybegin
,zbegin
). If thesrcroi
isROI::All()
, the entirety of the data window ofsrc
will be used. It will copy intochannels[chbegin...]
, as many channels as are described by srcroi. Pixels or channels ofsrc
insidesrcroi
will replace the corresponding destination pixels entirely, whereassrc
pixels outside ofsrcroi
will not be copied and the corresponding offset pixels ofdst
will not be altered.
Examples:
// Paste small.exr on top of big.exr, offset by (100,100) ImageBuf Big ("big.exr"); ImageBuf Small ("small.exr"); ImageBufAlgo::paste (Big, 100, 100, 0, 0, Small);
-
group
rotateN
Return (or copy into
dst
) a rotated copy of the image pixels ofsrc
, in 90 degree increments. Pictorially:rotate90 rotate180 rotate270 ----------- ----------- ----------- AB --> CA AB --> DC AB --> BD CD DB CD BA CD AC
Functions
-
ImageBuf
rotate90
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
rotate180
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
rotate270
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate90
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate180
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate270
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
ImageBuf A ("grid.jpg"); ImageBuf R90 = ImageBufAlgo::rotate90 (A); ImageBuf R170 = ImageBufAlgo::rotate180 (A); ImageBuf R270 = ImageBufAlgo::rotate270 (A);
-
group
flip-flop-transpose
Return (or copy into
dst
) a subregion ofsrc
, but with the scanlines exchanged vertically (flip), or columns exchanged horizontally (flop), or transposed across the diagonal by swapping rows for columns (transpose) within the display/full window. In other words,flip flop transpose ----------- ----------- ----------- AB --> CD AB --> BA AB --> AC CD AB CD DC CD BD
Functions
-
ImageBuf
flip
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
flop
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
transpose
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
flip
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
flop
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
transpose
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
ImageBuf A ("grid.jpg"); ImageBuf B; B = ImageBufAlgo::flip (A); B = ImageBufAlgo::flop (A); B = ImageBufAlgo::transpose (A);
-
ImageBuf
OIIO::ImageBufAlgo
::
reorient
(const ImageBuf &src, int nthreads = 0)¶ Return (or store into
dst
) a copy ofsrc
, but with whatever seties of rotations, flips, or flops are necessary to transform the pixels into the configuration suggested by the “Orientation” metadata of the image (and the “Orientation” metadata is then set to 1, ordinary orientation).
Examples:
ImageBuf A ("tahoe.jpg"); A = ImageBufAlgo::reorient (A);Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
reorient
(ImageBuf &dst, const ImageBuf &src, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
ImageBuf
OIIO::ImageBufAlgo
::
circular_shift
(const ImageBuf &src, int xshift, int yshift, int zshift = 0, ROI roi = {}, int nthreads = 0)¶ Return a subregion of
src
, but circularly shifting by the given amount. To clarify, the circular shift of [0,1,2,3,4,5] by +2 is [4,5,0,1,2,3].
Examples:
ImageBuf A ("grid.jpg"); ImageBuf B = ImageBufAlgo::circular_shift (A, 70, 30);
-
group
rotate
Rotate the
src
image by theangle
(in radians, with positive angles clockwise). Whencenter_x
andcenter_y
are supplied, they denote the center of rotation; in their absence, the rotation will be about the center of the image’s display window.Only the pixels (and channels) of
dst
that are specified byroi
will be copied from the rotatedsrc
; the defaultroi
is to alter all the pixels indst
. Ifdst
is uninitialized, it will be resized to be an ImageBuf large enough to hold the rotated image if recompute_roi is true, or will have the same ROI assrc
ifrecompute_roi
isfalse
. It is an error to pass both an uninitializeddst
and an undefinedroi
.The filter is used to weight the
src
pixels falling underneath it for eachdst
pixel. The caller may specify a reconstruction filter by name and width (expressed in pixels units of thedst
image), orrotate()
will choose a reasonable default high-quality default filter (lanczos3) if the empty string is passed, and a reasonable filter width iffilterwidth
is 0. (Note that some filter choices only make sense with particular width, in which case this filterwidth parameter may be ignored.)Functions
-
ImageBuf
rotate
(const ImageBuf &src, float angle, string_view filtername = string_view(), float filterwidth = 0.0f, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
rotate
(const ImageBuf &src, float angle, Filter2D *filter, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
rotate
(const ImageBuf &src, float angle, float center_x, float center_y, string_view filtername = string_view(), float filterwidth = 0.0f, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
rotate
(const ImageBuf &src, float angle, float center_x, float center_y, Filter2D *filter, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate
(ImageBuf &dst, const ImageBuf &src, float angle, string_view filtername = string_view(), float filterwidth = 0.0f, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate
(ImageBuf &dst, const ImageBuf &src, float angle, Filter2D *filter, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate
(ImageBuf &dst, const ImageBuf &src, float angle, float center_x, float center_y, string_view filtername = string_view(), float filterwidth = 0.0f, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
bool
rotate
(ImageBuf &dst, const ImageBuf &src, float angle, float center_x, float center_y, Filter2D *filter, bool recompute_roi = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
ImageBuf Src ("tahoe.exr"); ImageBuf Dst = ImageBufAlgo::rotate (Src, 45.0);
-
group
resize
Set
dst
, over the region of interest, to be a resized version of the corresponding portion ofsrc
(mapping such that the “full” image window of each correspond to each other, regardless of resolution). Ifdst
is not yet initialized, it will be sized according toroi
.The caller may either (a) explicitly pass a reconstruction
filter
, or (b) specify one byfiltername
andfilterwidth
. Iffilter
isnullptr
or iffiltername
is the empty stringresize()
will choose a reasonable high-quality default (blackman-harris when upsizing, lanczos3 when downsizing). The filter is used to weight thesrc
pixels falling underneath it for eachdst
pixel; the filter’s size is expressed in pixel units of thedst
image.Functions
-
ImageBuf
resize
(const ImageBuf &src, string_view filtername = "", float filterwidth = 0.0f, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
resize
(const ImageBuf &src, Filter2D *filter, ROI roi = {}, int nthreads = 0)¶
-
bool
resize
(ImageBuf &dst, const ImageBuf &src, string_view filtername = "", float filterwidth = 0.0f, ROI roi = {}, int nthreads = 0)¶
-
bool
resize
(ImageBuf &dst, const ImageBuf &src, Filter2D *filter, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
// Resize the image to 640x480, using the default filter ImageBuf Src ("tahoe.exr"); ROI roi (0, 640, 0, 480, 0, 1, /*chans:*/ 0, Src.nchannels()); ImageBuf Dst = ImageBufAlgo::resize (Src, "", 0, roi);
-
ImageBuf
OIIO::ImageBufAlgo
::
resample
(const ImageBuf &src, bool interpolate = true, ROI roi = {}, int nthreads = 0)¶ Set
dst
, over the region of interest, to be a resized version of the corresponding portion ofsrc
(mapping such that the “full” image window of each correspond to each other, regardless of resolution). Ifdst
is not yet initialized, it will be sized according toroi
.Unlike
ImageBufAlgo::resize()
,resample()
does not take a filter; it just samples either with a bilinear interpolation (ifinterpolate
istrue
, the default) or uses the single “closest” pixel (ifinterpolate
isfalse
). This makes it a lot faster than a properresize()
, though obviously with lower quality (aliasing when downsizing, pixel replication when upsizing).For “deep” images, this function returns copies the closest source pixel needed, rather than attempting to interpolate deep pixels (regardless of the value of
interpolate
).
Examples:
// Resample quickly to 320x240, using the default filter ImageBuf Src ("tahoe.exr"); ROI roi (0, 320, 0, 240, 0, 1, /*chans:*/ 0, Src.nchannels()); ImageBuf Dst = ImageBufAlgo::resample (Src, false, roi);Result-as-parameter version:
-
group
fit
Fit src into
dst
(to a size specified byroi
, ifdst
is not initialized), resizing but preserving its original aspect ratio. Thus, it will resize so be the largest size with the same aspect ratio that can fix inside the region, but will not stretch to completely fill it in both dimensions.If
exact
is true, will result in an exact match on aspect ratio and centering (partial pixel shift if necessary), whereas exact=false will only preserve aspect ratio and centering to the precision of a whole pixel.The filter is used to weight the
src
pixels falling underneath it for eachdst
pixel. The caller may specify a reconstruction filter by name and width (expressed in pixels units of thedst
image), orrotate()
will choose a reasonable default high-quality default filter (lanczos3) if the empty string is passed, and a reasonable filter width iffilterwidth
is 0. (Note that some filter choices only make sense with particular width, in which case this filterwidth parameter may be ignored.)Functions
-
ImageBuf
fit
(const ImageBuf &src, string_view filtername = "", float filterwidth = 0.0f, bool exact = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
fit
(const ImageBuf &src, Filter2D *filter, bool exact = false, ROI roi = {}, int nthreads = 0)¶
-
bool
fit
(ImageBuf &dst, const ImageBuf &src, string_view filtername = "", float filterwidth = 0.0f, bool exact = false, ROI roi = {}, int nthreads = 0)¶
-
bool
fit
(ImageBuf &dst, const ImageBuf &src, Filter2D *filter, bool exact = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
// Resize to fit into a max of 640x480, preserving the aspect ratio ImageBuf Src ("tahoe.exr"); ROI roi (0, 640, 0, 480, 0, 1, /*chans:*/ 0, Src.nchannels()); ImageBuf Dst = ImageBufAlgo::fit (Src, "", 0, true, roi);
-
group
warp
Warp the
src
image using the supplied 3x3 transformation matrix.Only the pixels (and channels) of
dst
that are specified byroi
will be copied from the warpedsrc
; the default roi is to alter all the pixels in dst. Ifdst
is uninitialized, it will be sized to be an ImageBuf large enough to hold the warped image if recompute_roi is true, or will have the same ROI as src if recompute_roi is false. It is an error to pass both an uninitializeddst
and an undefinedroi
.The caller may explicitly pass a reconstruction filter, or specify one by name and size, or if the name is the empty string
resize()
will choose a reasonable high-quality default ifnullptr
is passed. The filter is used to weight thesrc
pixels falling underneath it for eachdst
pixel; the filter’s size is expressed in pixel units of thedst
image.Functions
-
ImageBuf
warp
(const ImageBuf &src, const Imath::M33f &M, string_view filtername = string_view(), float filterwidth = 0.0f, bool recompute_roi = false, ImageBuf::WrapMode wrap = ImageBuf::WrapDefault, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
warp
(const ImageBuf &src, const Imath::M33f &M, const Filter2D *filter, bool recompute_roi = false, ImageBuf::WrapMode wrap = ImageBuf::WrapDefault, ROI roi = {}, int nthreads = 0)¶
-
bool
warp
(ImageBuf &dst, const ImageBuf &src, const Imath::M33f &M, string_view filtername = string_view(), float filterwidth = 0.0f, bool recompute_roi = false, ImageBuf::WrapMode wrap = ImageBuf::WrapDefault, ROI roi = {}, int nthreads = 0)¶
-
bool
warp
(ImageBuf &dst, const ImageBuf &src, const Imath::M33f &M, const Filter2D *filter, bool recompute_roi = false, ImageBuf::WrapMode wrap = ImageBuf::WrapDefault, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
Imath::M33f M ( 0.7071068, 0.7071068, 0, -0.7071068, 0.7071068, 0, 20, -8.284271, 1); ImageBuf Src ("tahoe.exr"); ImageBuf Dst = ImageBufAlgo::warp (dst, src, M, "lanczos3");
Image arithmetic¶
-
ImageBuf
OIIO::ImageBufAlgo
::
add
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel sum
A + B
, returning the result image.A
andB
may each either be anImageBuf&
, or acspan<float>
giving a per- channel constant, or a single constant used for all channels. (But at least one must be an image.)
Examples:
// Add images A and B, assign to Sum ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf Sum = ImageBufAlgo::add (Sum, A, B); // Add 0.2 to channels 0-2 of A ImageBuf A ("a.exr"); ROI roi = get_roi (A.spec()); roi.chbegin = 0; roi.chend = 3; ImageBuf Sum = ImageBufAlgo::add (Sum, A, 0.2f, roi);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
sub
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel signed difference
A - B
, returning the result image.A
andB
may each either be anImageBuf&
, or acspan<float>
giving a per-channel constant, or a single constant used for all channels. (But at least one must be an image.)
Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf Diff = ImageBufAlgo::sub (A, B);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
absdiff
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel absolute difference
abs(A - B)
, returning the result image.A
andB
may each either be anImageBuf&
, or acspan<float>
giving a per- channel constant, or a single constant used for all channels. (But at least one must be an image.)
Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf Diff = ImageBufAlgo::absdiff (A, B);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
abs
(const ImageBuf &A, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel absolute value
abs(A)
, returning the result image.
-
ImageBuf
OIIO::ImageBufAlgo
::
mul
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel product
A * B
, returning the result image.Either both
A
andB
are images, or one is an image and the other is acspan<float>
giving a per-channel constant or a single constant used for all channels.
Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf Product = ImageBufAlgo::mul (Product, A, B); // Reduce intensity of A's channels 0-2 by 50% ROI roi = get_roi (A.spec()); roi.chbegin = 0; roi.chend = 3; ImageBufAlgo::mul (A, A, 0.5f, roi);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
div
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel division
A / B
, returning the result image. Division by zero is defined to result in zero.A
is always an image, andB
is either an image or acspan<float>
giving a per-channel constant or a single constant used for all channels.
Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf Result = ImageBufAlgo::div (Result, A, B); // Reduce intensity of A's channels 0-2 by 50% ROI roi = get_roi (A.spec()); roi.chbegin = 0; roi.chend = 3; ImageBufAlgo::div (A, A, 2.0f, roi);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
mad
(Image_or_Const A, Image_or_Const B, Image_or_Const C, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel multiply-and-add
A * B + C
, returning the result image.A
,B
, andC
are each either an image, or acspan<float>
giving a per-channel constant or a single constant used for all channels. (Note: at least one must be an image.)
Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf C ("c.exr"); ImageBuf Result = ImageBufAlgo::mad (A, B, C); // Compute the "inverse" A, which is 1.0-A, as A*(-1) + 1 // Do this in-place, and only for the first 3 channels (leave any // alpha channel, if present, as it is). ROI roi = get_roi (A.spec()); roi.chbegin = 0; roi.chend = 3; ImageBufAlgo::mad (A, A, -1.0, 1.0, roi);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
over
(const ImageBuf &A, const ImageBuf &B, ROI roi = {}, int nthreads = 0)¶ Return the composite of
A
overB
using the Porter/Duff definition of “over”, returning true upon success and false for any of a variety of failures (as described below).A
andB
(and dst, if already defined/allocated) must have valid alpha channels identified by their ImageSpecalpha_channel
field. IfA
orB
do not have alpha channels (as determined by those rules) or if the number of non-alpha channels do not match betweenA
andB
,over()
will fail, returning false.If
dst
is not already an initialized ImageBuf, it will be sized to encompass the minimal rectangular pixel region containing the union of the defined pixels ofA
andB
, and with a number of channels equal to the number of non-alpha channels ofA
andB
, plus an alpha channel. However, ifdst
is already initialized, it will not be resized, and the “over” operation will apply to its existing pixel data window. In this case, dst must have an alpha channel designated and must have the same number of non-alpha channels asA
andB
, otherwise it will fail, returning false.A
,B
, anddst
need not perfectly overlap in their pixel data windows; pixel values ofA
orB
that are outside their respective pixel data window will be treated as having “zero” (0,0,0…) value.
Examples:
ImageBuf A ("fg.exr"); ImageBuf B ("bg.exr"); ImageBuf Composite = ImageBufAlgo::over (A, B);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
zover
(const ImageBuf &A, const ImageBuf &B, bool z_zeroisinf = false, ROI roi = {}, int nthreads = 0)¶ Just like
ImageBufAlgo::over()
, but inputsA
andB
must have designated ‘z’ channels, and on a pixel-by-pixel basis, the z values will determine which ofA
orB
will be considered the foreground or background (lower z is foreground). Ifz_zeroisinf
is true, then z=0 values will be treated as if they are infinitely far away.
Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf Composite = ImageBufAlgo::zover (Composite, A, B);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
invert
(const ImageBuf &A, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel value inverse
1.0 - A
(which you can think of as roughly meaning switching white and black), returning the result image.Tips for callers: (1) You probably want to set
roi
to restrict the operation to only the color channels, and not accidentally include alpha, z, or others. (2) There may be situations where you want tounpremult()
before the invert, thenpremult()
the result, so that you are computing the inverse of the unmasked color.
Examples:
ImageBuf A ("a.exr"); ImageBuf Inverse = ImageBufAlgo::invert (Inverse, A); // In this example, we are careful to deal with alpha in an RGBA image. // First we copy A to Inverse, un-premultiply the color values by alpha, // invert just the color channels in-place, and then re-premultiply the // colors by alpha. roi = A.roi(); roi.chend = 3; // Restrict roi to only R,G,B ImageBuf Inverse = ImageBufAlgo::unpremult (A); ImageBufAlgo::invert (Inverse, Inverse, roi); ImageBufAlgo::premult (Inverse, Inverse);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
pow
(const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel raise-to-power
A ^ B
. returning the result image. It is permitted fordst
andA
to be the same image.A
is always an image, andB
is either an image or acspan<float>
giving a per-channel constant or a single constant used for all channels.
Examples:
// Gamma-correct by 2.2 channels 0-2 of the image, in-place ROI roi = get_roi (A.spec()); roi.chbegin = 0; roi.chend = 3; ImageBufAlgo::pow (A, A, 1.0f/2.2f, roi);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
channel_sum
(const ImageBuf &src, cspan<float> weights = 1.0f, ROI roi = {}, int nthreads = 0)¶ Converts a multi-channel image into a one-channel image via a weighted sum of channels:
(channel[0]*weight[0] + channel[1]*weight[1] + ...)
returning the resulting one-channel image. The
weights
, if not supplied, default to{ 1, 1, 1, ... }
).
Examples:
// Compute luminance via a weighted sum of R,G,B // (assuming Rec709 primaries and a linear scale) float luma_weights[3] = { .2126, .7152, .0722, 0.0 }; ImageBuf A ("a.exr"); ImageBuf lum = ImageBufAlgo::channel_sum (A, luma_weights);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
max
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel
max(A, B)
, returning the result image.Either both
A
andB
are images, or one is an image and the other is acspan<float>
giving a per-channel constant or a single constant used for all channels.
-
ImageBuf
OIIO::ImageBufAlgo
::
min
(Image_or_Const A, Image_or_Const B, ROI roi = {}, int nthreads = 0)¶ Compute per-pixel
min(A, B)
, returning the result image.Either both
A
andB
are images, or one is an image and the other is acspan<float>
giving a per-channel constant or a single constant used for all channels.
Examples:
// min of images A and B, assign to MinMimage ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBuf MinImage = ImageBufAlgo::min (Sum, A, B); // Squash negative values in A by taking max(A, 0.0) for channels 0-2 of A ImageBuf A ("a.exr"); ROI roi = get_roi (A.spec()); roi.chbegin = 0; roi.chend = 3; ImageBuf Sum = ImageBufAlgo::max (Sum, A, 0.0f, roi);Result-as-parameter version:
-
ImageBuf
OIIO::ImageBufAlgo
::
clamp
(const ImageBuf &src, cspan<float> min = -std::numeric_limits<float>::max(), cspan<float> max = std::numeric_limits<float>::max(), bool clampalpha01 = false, ROI roi = {}, int nthreads = 0)¶ Return pixels of
src
with pixel values clamped as follows:min
specifies the minimum clamp value for each channel (if min is empty, no minimum clamping is performed).max
specifies the maximum clamp value for each channel (ifmax
is empty, no maximum clamping is performed).If
clampalpha01
is true, then additionally any alpha channel is clamped to the 0-1 range.
Examples:
// Clamp image buffer A in-place to the [0,1] range for all pixels. ImageBufAlgo::clamp (A, A, 0.0f, 1.0f); // Just clamp alpha to [0,1] in-place ImageBufAlgo::clamp (A, A, -std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), true); // Clamp R & G to [0,0.5], leave other channels alone std::vector<float> min (A.nchannels(), -std::numeric_limits<float>::max()); std::vector<float> max (A.nchannels(), std::numeric_limits<float>::max()); min[0] = 0.0f; max[0] = 0.5f; min[1] = 0.0f; max[1] = 0.5f; ImageBufAlgo::clamp (A, A, &min[0], &max[0], false);Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
clamp
(ImageBuf &dst, const ImageBuf &src, cspan<float> min = -std::numeric_limits<float>::max(), cspan<float> max = std::numeric_limits<float>::max(), bool clampalpha01 = false, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
ImageBuf
OIIO::ImageBufAlgo
::
contrast_remap
(const ImageBuf &src, cspan<float> black = 0.0f, cspan<float> white = 1.0f, cspan<float> min = 0.0f, cspan<float> max = 1.0f, cspan<float> scontrast = 1.0f, cspan<float> sthresh = 0.5f, ROI = {}, int nthreads = 0)¶ Return pixel values that are a contrast-remap of the corresponding values of the
src
image, transforming pixel value domain [black, white] to range [min, max], either linearly or with optional application of a smooth sigmoidal remapping (ifscontrast
!= 1.0).The following steps are performed, in order:
Linearly rescale values [
black
,white
] to [0, 1].If
scontrast
!= 1, apply a sigmoidal remapping where a largerscontrast
value makes a steeper slope, and the steepest part is at valuesthresh
(relative to the new remapped value after steps 1 & 2; the default is 0.5).Rescale the range of that result: 0.0 ->
min
and 1.0 ->max
.
Values outside of the [black,white] range will be extrapolated to outside [min,max], so it may be prudent to apply a clamp() to the results.
The black, white, min, max, scontrast, sthresh parameters may each either be a single float value for all channels, or a span giving per-channel values.
You can use this function for a simple linear contrast remapping of [black, white] to [min, max] if you use the default values for sthresh. Or just a simple sigmoidal contrast stretch within the [0,1] range if you leave all other parameters at their defaults, or a combination of these effects. Note that if
black
==white
, the result will be a simple binary thresholding where values <black
map tomin
and values >=black
map tomax
.
Examples:
ImageBuf A ("tahoe.tif"); // Simple linear remap that stretches input 0.1 to black, and input // 0.75 to white. ImageBuf linstretch = ImageBufAlgo::contrast_remap (A, 0.1f, 0.75f); // Remapping 0->1 and 1->0 inverts the colors of the image, // equivalent to ImageBufAlgo::invert(). ImageBuf inverse = ImageBufAlgo::contrast_remap (A, 1.0f, 0.0f); // Use a sigmoid curve to add contrast but without any hard cutoffs. // Use a contrast parameter of 5.0. ImageBuf sigmoid = ImageBufAlgo::contrast_remap (a, 0.0f, 1.0f, 0.0f, 1.0f, 5.0f);
original
linstretch
inverse
sigmoid
Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
contrast_remap
(ImageBuf &dst, const ImageBuf &src, cspan<float> black = 0.0f, cspan<float> white = 1.0f, cspan<float> min = 0.0f, cspan<float> max = 1.0f, cspan<float> scontrast = 1.0f, cspan<float> sthresh = 0.5f, ROI = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
group
color_map
Remap value range by spline or name
Return (or copy into
dst
) pixel values determined by looking up a color map using values of the source image, using either the channel specified bysrcchannel
, or the luminance ofsrc
’s RGB ifsrcchannel
is -1. This happens for all pixels within the ROI (which defaults to all ofsrc
), and ifdst
is not already initialized, it will be initialized to the ROI and with color channels equal tochannels
.In the variant that takes a
knots
parameter, this specifies the values of a linearly-interpolated color map given byknots[nknots*channels]
. An input value of 0.0 is mapped toknots[0..channels-1]
(one value for each color channel), and an input value of 1.0 is mapped toknots[(nknots-1)*channels..knots.size()-1]
.In the variant that takes a
mapname
parameter, this is the name of a color map. Recognized map names include: “inferno”, “viridis”, “magma”, “plasma”, all of which are perceptually uniform, strictly increasing in luminance, look good when converted to grayscale, and work for people with all types of colorblindness. Also “turbo” has most of these properties (except for being strictly increasing in luminance) and is a nice rainbow-like pattern. Also supported are the following color maps that do not have those desirable qualities (and are thus not recommended, but are present for back-compatibility or for use by clueless people): “blue-red”, “spectrum”, and “heat”. In all cases, the impliedchannels
is 3.Functions
-
ImageBuf
color_map
(const ImageBuf &src, int srcchannel, int nknots, int channels, cspan<float> knots, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
color_map
(const ImageBuf &src, int srcchannel, string_view mapname, ROI roi = {}, int nthreads = 0)¶
-
bool
color_map
(ImageBuf &dst, const ImageBuf &src, int srcchannel, int nknots, int channels, cspan<float> knots, ROI roi = {}, int nthreads = 0)¶
-
bool
color_map
(ImageBuf &dst, const ImageBuf &src, int srcchannel, string_view mapname, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
// Use luminance of a.exr (assuming Rec709 primaries and a linear // scale) and map to a spectrum-like palette.: ImageBuf A ("a.exr"); ImageBuf B = ImageBufAlgo::color_map (A, -1, "turbo"); float mymap[] = { 0.25, 0.25, 0.25, 0, 0.5, 0, 1, 0, 0 }; B = ImageBufAlgo::color_map (A, -1 /* use luminance */, 3 /* num knots */, 3 /* channels */, mymap);
-
group
range
Nonlinear range remapping for contrast preservation
rangecompress()
returns (or copy intodst
) all pixels and color channels ofsrc
within regionroi
(defaulting to all the defined pixels ofdst
), rescaling their range with a logarithmic transformation. Alpha and z channels are not transformed.rangeexpand()
performs the inverse transformation (logarithmic back into linear).If
useluma
is true, the luma of channels [roi.chbegin..roi.chbegin+2] (presumed to be R, G, and B) are used to compute a single scale factor for all color channels, rather than scaling all channels individually (which could result in a color shift).The purpose of these function is as follows: Some image operations (such as resizing with a “good” filter that contains negative lobes) can have objectionable artifacts when applied to images with very high-contrast regions involving extra bright pixels (such as highlights in HDR captured or rendered images). By compressing the range pixel values, then performing the operation, then expanding the range of the result again, the result can be much more pleasing (even if not exactly correct).
Functions
-
ImageBuf
rangecompress
(const ImageBuf &src, bool useluma = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
rangeexpand
(const ImageBuf &src, bool useluma = false, ROI roi = {}, int nthreads = 0)¶
-
bool
rangecompress
(ImageBuf &dst, const ImageBuf &src, bool useluma = false, ROI roi = {}, int nthreads = 0)¶
-
bool
rangeexpand
(ImageBuf &dst, const ImageBuf &src, bool useluma = false, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
// Resize the image to 640x480, using a Lanczos3 filter, which // has negative lobes. To prevent those negative lobes from // producing ringing or negative pixel values for HDR data, // do range compression, then resize, then re-expand the range. // 1. Read the original image ImageBuf Src ("tahoeHDR.exr"); // 2. Range compress to a logarithmic scale ImageBuf Compressed = ImageBufAlgo::rangecompress (Src); // 3. Now do the resize ImageBuf Dst = ImageBufAlgo::resize (Comrpessed, "lanczos3", 6.0, ROI(0, 640, 0, 480)); // 4. Expand range to be linear again (operate in-place) ImageBufAlgo::rangeexpand (Dst, Dst);
Image comparison and statistics¶
-
PixelStats
OIIO::ImageBufAlgo
::
computePixelStats
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Compute statistics about the ROI of the
src
image, returning a PixelStats structure. Upon success, the returned vectors in the result structure will have size == src.nchannels(). If there is a failure, the vector sizes will be 0 and an error will be set in src.
The PixelStats structure is defined as follows:
struct PixelStats { std::vector<float> min; std::vector<float> max; std::vector<float> avg; std::vector<float> stddev; std::vector<imagesize_t> nancount; std::vector<imagesize_t> infcount; std::vector<imagesize_t> finitecount; };Examples:
ImageBuf A ("a.exr"); ImageBufAlgo::PixelStats stats; ImageBufAlgo::computePixelStats (stats, A); for (int c = 0; c < A.nchannels(); ++c) { std::cout << "Channel " << c << ":\n"; std::cout << " min = " << stats.min[c] << "\n"; std::cout << " max = " << stats.max[c] << "\n"; std::cout << " average = " << stats.avg[c] << "\n"; std::cout << " standard deviation = " << stats.stddev[c] << "\n"; std::cout << " # NaN values = " << stats.nancount[c] << "\n"; std::cout << " # Inf values = " << stats.infcount[c] << "\n"; std::cout << " # finite values = " << stats.finitecount[c] << "\n"; }
-
CompareResults
OIIO::ImageBufAlgo
::
compare
(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi = {}, int nthreads = 0)¶ Numerically compare two images. The difference threshold (for any individual color channel in any pixel) for a “failure” is failthresh, and for a “warning” is warnthresh. The results are stored in result. If roi is defined, pixels will be compared for the pixel and channel range that is specified. If roi is not defined, the comparison will be for all channels, on the union of the defined pixel windows of the two images (for either image, undefined pixels will be assumed to be black).
The CompareResults structure is defined as follows:
struct CompareResults { double meanerror, rms_error, PSNR, maxerror; int maxx, maxy, maxz, maxc; imagesize_t nwarn, nfail; bool error; };Examples:
ImageBuf A ("a.exr"); ImageBuf B ("b.exr"); ImageBufAlgo::CompareResults comp; ImageBufAlgo::compare (A, B, 1.0f/255.0f, 0.0f, comp); if (comp.nwarn == 0 && comp.nfail == 0) { std::cout << "Images match within tolerance\n"; } else { std::cout << "Image differed: " << comp.nfail << " failures, " << comp.nwarn << " warnings.\n"; std::cout << "Average error was " << comp.meanerror << "\n"; std::cout << "RMS error was " << comp.rms_error << "\n"; std::cout << "PSNR was " << comp.PSNR << "\n"; std::cout << "largest error was " << comp.maxerror << " on pixel (" << comp.maxx << "," << comp.maxy << "," << comp.maxz << "), channel " << comp.maxc << "\n"; }
-
int
OIIO::ImageBufAlgo
::
compare_Yee
(const ImageBuf &A, const ImageBuf &B, CompareResults &result, float luminance = 100, float fov = 45, ROI roi = {}, int nthreads = 0)¶ Compare two images using Hector Yee’s perceptual metric, returning the number of pixels that fail the comparison. Only the first three channels (or first three channels specified by
roi
) are compared. Free parameters are the ambient luminance in the room and the field of view of the image display; our defaults are probably reasonable guesses for an office environment. The ‘result’ structure will store the maxerror, and the maxx, maxy, maxz of the pixel that failed most severely. (The other fields of the CompareResults are not used for Yee comparison.)Works for all pixel types. But it’s basically meaningless if the first three channels aren’t RGB in a linear color space that sort of resembles AdobeRGB.
Return true on success, false on error.
-
bool
OIIO::ImageBufAlgo
::
isConstantColor
(const ImageBuf &src, float threshold = 0.0f, span<float> color = {}, ROI roi = {}, int nthreads = 0)¶ Do all pixels within the ROI have the same values for channels
[roi.chbegin..roi.chend-1]
, within a tolerance of +/-threshold
? If so, returntrue
and store that color incolor[chbegin...chend-1]
(ifcolor
is not empty); otherwise returnfalse
. Ifroi
is not defined (the default), it will be understood to be all of the defined pixels and channels of source.
Examples:
ImageBuf A ("a.exr"); std::vector<float> color (A.nchannels()); if (ImageBufAlgo::isConstantColor (A, color)) { std::cout << "The image has the same value in all pixels: "; for (int c = 0; c < A.nchannels(); ++c) std::cout << (c ? " " : "") << color[c]; std::cout << "\n"; } else { std::cout << "The image is not a solid color.\n"; }
-
bool
OIIO::ImageBufAlgo
::
isConstantChannel
(const ImageBuf &src, int channel, float val, float threshold = 0.0f, ROI roi = {}, int nthreads = 0)¶ Does the requested channel have a given value (within a tolerance of +/-
threshold
) for every channel within the ROI? (For this function, the ROI’s chbegin/chend are ignored.) Returntrue
if so, otherwise returnfalse
. Ifroi
is not defined (the default), it will be understood to be all of the defined pixels and channels of source.
Examples:
ImageBuf A ("a.exr"); int alpha = A.spec().alpha_channel; if (alpha < 0) std::cout << "The image does not have an alpha channel\n"; else if (ImageBufAlgo::isConstantChannel (A, alpha, 1.0f)) std::cout << "The image has alpha = 1.0 everywhere\n"; else std::cout << "The image has alpha < 1 in at least one pixel\n";
-
bool
OIIO::ImageBufAlgo
::
isMonochrome
(const ImageBuf &src, float threshold = 0.0f, ROI roi = {}, int nthreads = 0)¶ Is the image monochrome within the ROI, i.e., for every pixel within the region, do all channels [roi.chbegin, roi.chend) have the same value (within a tolerance of +/- threshold)? If roi is not defined (the default), it will be understood to be all of the defined pixels and channels of source.
Examples:
ImageBuf A ("a.exr"); ROI roi = get_roi (A.spec()); roi.chend = std::min (3, roi.chend); // only test RGB, not alpha if (ImageBufAlgo::isMonochrome (A, roi)) std::cout << "a.exr is really grayscale\n";
-
bool
OIIO::ImageBufAlgo
::
color_count
(const ImageBuf &src, imagesize_t *count, int ncolors, cspan<float> color, cspan<float> eps = 0.001f, ROI roi = {}, int nthreads = 0)¶ Count how many pixels in the ROI match a list of colors. The colors to match are in::
colors[0 ... nchans-1] colors[nchans ... 2*nchans-1] ... colors[(ncolors-1)*nchans ... (ncolors*nchans)-1]
and so on, a total of
ncolors
consecutively stored colors ofnchans
channels each (nchans
is the number of channels in the image, itself, it is not passed as a parameter).eps[0..nchans-1]
are the error tolerances for a match, for each channel. Settingeps[c]
=numeric_limits<float>max()
will effectively make it ignore the channel. The defaulteps
is 0.001 for all channels (this value is chosen because it requires exact matches for 8 bit images, but allows a wee bit of imprecision for float images.Upon success, return
true
and store the number of pixels that matched each colorcount[..ncolors-1]
. If there is an error, returnsfalse
and sets an appropriate error message set insrc
.
Examples:
ImageBuf A ("a.exr"); int n = A.nchannels(); // Try to match two colors: pure red and green std::vector<float> colors (2*n, numeric_limits<float>::max()); colors[0] = 1.0f; colors[1] = 0.0f; colors[2] = 0.0f; colors[n+0] = 0.0f; colors[n+1] = 1.0f; colors[n+2] = 0.0f; const int ncolors = 2; imagesize_t count[ncolors]; ImageBufAlgo::color_count (A, count, ncolors); std::cout << "Number of red pixels : " << count[0] << "\n"; std::cout << "Number of green pixels : " << count[1] << "\n";
-
bool
OIIO::ImageBufAlgo
::
color_range_check
(const ImageBuf &src, imagesize_t *lowcount, imagesize_t *highcount, imagesize_t *inrangecount, cspan<float> low, cspan<float> high, ROI roi = {}, int nthreads = 0)¶ Count how many pixels in the image (within the ROI) are outside the value range described by
low[roi.chbegin..roi.chend-1]
andhigh[roi.chbegin..roi.chend-1]
as the low and high acceptable values for each color channel.The number of pixels containing values that fall below the lower bound will be stored in
*lowcount
, the number of pixels containing values that fall above the upper bound will be stored in*highcount
, and the number of pixels for which all channels fell within the bounds will be stored in*inrangecount
. Any of these may be NULL, which simply means that the counts need not be collected or stored.
Examples:
ImageBuf A ("a.exr"); ROI roi = get_roi (A.spec()); roi.chend = std::min (roi.chend, 4); // only compare RGBA float low[] = {0, 0, 0, 0}; float high[] = {1, 1, 1, 1}; imagesize_t lowcount, highcount, inrangecount; ImageBufAlgo::color_range_check (A, &lowcount, &highcount, &inrangecount, low, high, roi); std::cout << lowcount << " pixels had components < 0\n"; std::cout << highcount << " pixels had components > 1\n"; std::cout << inrangecount << " pixels were fully within [0,1] range\n";
-
ROI
OIIO::ImageBufAlgo
::
nonzero_region
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Find the minimal rectangular region within
roi
(which defaults to the entire pixel data window ofsrc
) that consists of nonzero pixel values. In other words, gives the region that is a “shrink-wraps” ofsrc
to exclude black border pixels. Note that if the entire image was black, the ROI returned will contain no pixels.For “deep” images, this function returns the smallest ROI that contains all pixels that contain depth samples, and excludes the border pixels that contain no depth samples at all.
Examples:
ImageBuf A ("a.exr"); ROI shrunk = ImageBufAlgo::nonzero_region (A); if (shrunk.undefined()) std::cout << "All pixels were empty\n"; else std::cout << "Non-empty region was " << shrunk << "\n";
-
std::string
OIIO::ImageBufAlgo
::
computePixelHashSHA1
(const ImageBuf &src, string_view extrainfo = "", ROI roi = {}, int blocksize = 0, int nthreads = 0)¶ Compute the SHA-1 byte hash for all the pixels in the specifed region of the image. If
blocksize
> 0, the function will compute separate SHA-1 hashes of eachblocksize
batch of scanlines, then return a hash of the individual hashes. This is just as strong a hash, but will NOT match a single hash of the entire image (blocksize==0
). But by breaking up the hash into independent blocks, we can parallelize across multiple threads, given bynthreads
(ifnthreads
is 0, it will use the global OIIO thread count). Theextrainfo
provides additional text that will be incorporated into the hash.
Examples:
ImageBuf A ("a.exr"); std::string hash; hash = ImageBufAlgo::computePixelHashSHA1 (A, "", ROI::All(), 64);
-
std::vector<imagesize_t>
OIIO::ImageBufAlgo
::
histogram
(const ImageBuf &src, int channel = 0, int bins = 256, float min = 0.0f, float max = 1.0f, bool ignore_empty = false, ROI roi = {}, int nthreads = 0)¶ Compute a histogram of
src
, for the given channel and ROI. Return a vector of lengthbins
that contains the counts of how many pixel values were in each ofbins
equally spaced bins covering the range of values[min,max]
. Values <min
count for bin 0, values >max
count for binnbins-1
. Ifignore_empty
istrue
, no counts will be incremented for any pixels whose value is 0 in all channels.
Examples:
ImageBuf Src ("tahoe.exr"); const int bins = 4; std::vector<imagesize_t> hist = ImageBufAlgo::histogram (Src, 0, bins, 0.0f, 1.0f); std::cout << "Channel 0 of the image had:\n"; float binsize = (max-min)/nbins; for (int i = 0; i < nbins; ++i) hist[i] << " pixels that are >= " << (min+i*binsize) << " and " << (i == nbins-1 ? " <= " : " < ") << (min+(i+1)*binsize) << "\n";
Convolutions and frequency-space algorithms¶
-
ImageBuf
OIIO::ImageBufAlgo
::
make_kernel
(string_view name, float width, float height, float depth = 1.0f, bool normalize = true)¶ Make a 1-channel
float
image of the named kernel. The size of the image will be big enough to contain the kernel given its size (width
xheight
) and rounded up to odd resolution so that the center of the kernel can be at the center of the middle pixel. The kernel image will be offset so that its center is at the (0,0) coordinate. Ifnormalize
is true, the values will be normalized so that they sum to 1.0. Ifdepth
> 1, a volumetric kernel will be created. Use with caution!Kernel names can be: “gaussian”, “sharp-gaussian”, “box”, “triangle”, “blackman-harris”, “mitchell”, “b-spline”, “catmull-rom”, “lanczos3”, “disk”, “binomial”, “laplacian”.
Note that “catmull-rom” and “lanczos3” are fixed-size kernels that don’t scale with the width, and are therefore probably less useful in most cases.
Examples:
ImageBuf K = ImageBufAlgo::make_kernel ("gaussian", 5.0f, 5.0f);
-
ImageBuf
OIIO::ImageBufAlgo
::
convolve
(const ImageBuf &src, const ImageBuf &kernel, bool normalize = true, ROI roi = {}, int nthreads = 0)¶ Return the convolution of
src
and akernel
. Ifroi
is not defined, it defaults to the full sizesrc
. Ifnormalized
is true, the kernel will be normalized for the convolution, otherwise the original values will be used.
Examples:
// Blur an image with a 5x5 Gaussian kernel ImageBuf Src ("tahoe.exr"); ImageBuf K = ImageBufAlgo::make_kernel ("gaussian", 5.0f, 5.0f); ImageBuf Blurred = ImageBufAlgo::convolve (Src, K);
original
blurred
Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
convolve
(ImageBuf &dst, const ImageBuf &src, const ImageBuf &kernel, bool normalize = true, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized). Ifroi
is not defined, it defaults to the full size ofdst
(orsrc
, ifdst
was uninitialized). Ifdst
is uninitialized, it will be allocated to be the size specified byroi
.
-
ImageBuf
OIIO::ImageBufAlgo
::
laplacian
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Return the Laplacian of the corresponding region of
src
. The Laplacian is the generalized second derivative of the image\[ \frac{\partial^2 s}{\partial x^2} + \frac{\partial^2 s}{\partial y^2} \]which is approximated by convolving the image with a discrete 3x3 Laplacian kernel,[ 0 1 0 ] [ 1 -4 1 ] [ 0 1 0 ]
Examples:
ImageBuf src ("tahoe.exr"); ImageBuf lap = ImageBufAlgo::laplacian (src);
-
group
fft-ifft
Fast Fourier Transform and inverse
Return (or copy into
dst
) the discrete Fourier transform (DFT), or its inverse, of the section ofsrc
denoted by roi, If roi is not defined, it will be all ofsrc
’s pixels.fft()
takes the discrete Fourier transform (DFT) of the section ofsrc
denoted byroi
, returning it or storing it indst
. Ifroi
is not defined, it will be all ofsrc
’s pixels. Only one channel ofsrc
may be transformed at a time, so it will be the first channel described byroi
(or, again, channel 0 ifroi
is undefined). If not already in the correct format,dst
will be re-allocated to be a 2-channelfloat
buffer of sizeroi.width()
xroi.height
, with channel 0 being the “real” part and channel 1 being the the “imaginary” part. The values returned are actually the unitary DFT, meaning that it is scaled by 1/sqrt(npixels).ifft()
takes the inverse discrete Fourier transform, transforming a 2-channel complex (real and imaginary) frequency domain image and into a single-channel spatial domain image.src
must be a 2-channel float image, and is assumed to be a complex frequency-domain signal with the “real” component in channel 0 and the “imaginary” component in channel 1.dst
will end up being a float image of one channel (the real component is kept, the imaginary component of the spatial-domain will be discarded). Just as withfft()
, theifft()
function is dealing with the unitary DFT, so it is scaled by 1/sqrt(npixels).Functions
-
ImageBuf
fft
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
ifft
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
fft
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
ifft
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
ImageBuf Src ("tahoe.exr"); // Take the DFT of the first channel of Src ImageBuf Freq = ImageBufAlgo::fft (Src); // At this point, Freq is a 2-channel float image (real, imag) // Convert it back from frequency domain to a spatial image ImageBuf Spatial = ImageBufAlgo::ifft (Freq);
-
group
complex-polar
Converting complex to polar and back
The
polar_to_complex()
function transforms a 2-channel image whose channels are interpreted as complex values (real and imaginary components) into the equivalent values expressed in polar form of amplitude and phase (with phase between 0 and \( 2\pi \).The
complex_to_polar()
function performs the reverse transformation, converting from polar values (amplitude and phase) to complex (real and imaginary).In either case, the section of
src
denoted byroi
is transformed, storing the result indst
. Ifroi
is not defined, it will be all ofsrc
’s pixels. Only the first two channels ofsrc
will be transformed.The transformation between the two representations are:
real = amplitude * cos(phase); imag = amplitude * sin(phase); amplitude = hypot (real, imag); phase = atan2 (imag, real);
Functions
-
ImageBuf
complex_to_polar
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
complex_to_polar
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
polar_to_complex
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
polar_to_complex
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
// Suppose we have a set of frequency space values expressed as // amplitudes and phase... ImageBuf Polar ("polar.exr"); // Convert to complex representation ImageBuf Complex = ImageBufAlgo::complex_to_polar (Polar); // Now, it's safe to take an IFFT of the complex image. // Convert it back from frequency domain to a spatial image. ImageBuf Spatial = ImageBufAlgo::ifft (Complex);
Image Enhancement / Restoration¶
-
ImageBuf
OIIO::ImageBufAlgo
::
fixNonFinite
(const ImageBuf &src, NonFiniteFixMode mode = NONFINITE_BOX3, int *pixelsFixed = nullptr, ROI roi = {}, int nthreads = 0)¶ fixNonFinite()
returns in image containing the values ofsrc
(within the ROI), while repairing any non-finite (NaN/Inf) pixels. If pixelsFixed is not nullptr, store in it the number of pixels that contained non-finite value. It is permissible to operate in-place (withsrc
anddst
referring to the same image).How the non-finite values are repaired is specified by one of the
mode
parameter, which is an enum ofNonFiniteFixMode
.This function works on all pixel data types, though it’s just a copy for images with pixel data types that cannot represent NaN or Inf values.
Examples:
ImageBuf Src ("tahoe.exr"); int pixelsFixed = 0; ImageBufAlgo::fixNonFinite (Src, Src, ImageBufAlgo::NONFINITE_BOX3, &pixelsFixed); std::cout << "Repaired " << pixelsFixed << " non-finite pixels\n";
-
ImageBuf
OIIO::ImageBufAlgo
::
fillholes_pushpull
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Copy the specified ROI of
src
and fill any holes (pixels where alpha < 1) with plausible values using a push-pull technique. Thesrc
image must have an alpha channel. Thedst
image will end up with a copy ofsrc
, but will have an alpha of 1.0 everywhere withinroi
, and any place where the alpha ofsrc
was < 1,dst
will have a pixel color that is a plausible “filling” of the original alpha hole.
Examples:
ImageBuf Src ("holes.exr"); ImageBuf Filled = ImageBufAlgo::fillholes_pushpull (Src);
-
ImageBuf
OIIO::ImageBufAlgo
::
median_filter
(const ImageBuf &src, int width = 3, int height = -1, ROI roi = {}, int nthreads = 0)¶ Return a median-filtered version of the corresponding region of
src
. The median filter replaces each pixel with the median value underneath thewidth
xheight
window surrounding it. Ifheight
<= 0, it will be set towidth
, making a square window.Median filters are good for removing high-frequency detail smaller than the window size (including noise), without blurring edges that are larger than the window size.
Examples:
ImageBuf Noisy ("tahoe.exr"); ImageBuf Clean = ImageBufAlgo::median_filter (Noisy, 3, 3);
-
ImageBuf
OIIO::ImageBufAlgo
::
unsharp_mask
(const ImageBuf &src, string_view kernel = "gaussian", float width = 3.0f, float contrast = 1.0f, float threshold = 0.0f, ROI roi = {}, int nthreads = 0)¶ Return a sharpened version of the corresponding region of
src
using the “unsharp mask” technique. Unsharp masking basically works by first blurring the image (low pass filter), subtracting this from the original image, then adding the residual back to the original to emphasize the edges. Roughly speaking,dst = src + contrast * thresh(src - blur(src))
The specific blur can be selected by kernel name and width (for example, “gaussian” is typical). As a special case, “median” is also accepted as the kernel name, in which case a median filter is performed rather than a blurring convolution (Gaussian and other blurs sometimes over-sharpen edges, whereas using the median filter will sharpen compact high-frequency details while not over-sharpening long edges).
The
contrast
is a multiplier on the overall sharpening effect. The thresholding step causes all differences less thanthreshold
to be squashed to zero, which can be useful for suppressing sharpening of low-contrast details (like noise) but allow sharpening of higher-contrast edges.
Examples:
ImageBuf Blurry ("tahoe.exr"); ImageBuf Sharp = ImageBufAlgo::unsharp_mask (Blurry, "gaussian", 5.0f);
- Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
unsharp_mask
(ImageBuf &dst, const ImageBuf &src, string_view kernel = "gaussian", float width = 3.0f, float contrast = 1.0f, float threshold = 0.0f, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
Morphological filters¶
-
ImageBuf
OIIO::ImageBufAlgo
::
dilate
(const ImageBuf &src, int width = 3, int height = -1, ROI roi = {}, int nthreads = 0)¶ Return a dilated version of the corresponding region of
src
. Dilation is defined as the maximum value of all pixels under nonzero values of the structuring element (which is taken to be a width x height square). If height is not set, it will default to be the same as width. Dilation makes bright features wider and more prominent, dark features thinner, and removes small isolated dark spots.
-
ImageBuf
OIIO::ImageBufAlgo
::
erode
(const ImageBuf &src, int width = 3, int height = -1, ROI roi = {}, int nthreads = 0)¶ Return an eroded version of the corresponding region of
src
. Erosion is defined as the minimum value of all pixels under nonzero values of the structuring element (which is taken to be a width x height square). If height is not set, it will default to be the same as width. Erosion makes dark features wider, bright features thinner, and removes small isolated bright spots.
Dilation and erosion are basic morphological filters, and more complex ones are often constructed from them:
“open” is erode followed by dilate, and it keeps the overall shape while removing small bright regions;
“close” is dilate followed by erode, and it keeps the overall shape while removing small dark regions;
“morphological gradient” is dilate minus erode, which gives a bright perimeter edge;
“tophat” is the original source minus the “open”, which isolates local peaks;
“bottomhat” is the “close” minus the original source, which isolates dark holes.
Examples:
ImageBuf Source ("source.tif");
ImageBuf Dilated = ImageBufAlgo::dilate (Source, 3, 3);
ImageBuf Eroded = ImageBufAlgo::erode (Source, 3, 3);
// Morphological "open" is dilate(erode((source))
ImageBuf Opened = ImageBufAlgo::dilate (Eroded, 3, 3);
// Morphological "close" is erode(dilate(source))
ImageBuf Closed = ImageBufAlgo::erode (Dilated, 3, 3);
// Morphological "gradient" is dilate minus erode
ImageBuf Gradient = ImageBufAlgo::sub (Dilated, Eroded);
// Tophat filter is source minus open
ImageBuf Tophat = ImageBufAlgo::sub (Source, Opened);
// Bottomhat filter is close minus source
ImageBuf Bottomhat = ImageBufAlgo::sub (Close, Source);
Color space conversion¶
-
group
colorconvert
Convert between color spaces
Return (or copy into
dst
) the pixels ofsrc
within the ROI, applying a color space transformation. In-place operations (dst
==src
) are supported.The first three channels are presumed to be the color to be transformed, and the fourth channel (if it exists) is presumed to be alpha. Any additional channels will be simply copied unaltered.
If OIIO was built with OpenColorIO support enabled, then the transformation may be between any two spaces supported by the active OCIO configuration, or may be a “look” transformation created by
ColorConfig::createLookTransform
. If OIIO was not built with OpenColorIO support enabled, then the only transformations available are from “sRGB” to “linear” and vice versa.- Parameters
fromspace/tospace
: For the varieties ofcolorconvert()
that use named color spaces, these specify the color spaces by name.context_key/context_value
: For the varieties ofcolorconvert()
that use named color spaces, these optionally specify a “key” name/value pair to establish a context (for example, a shot-specific transform).processor
: For the varieties ofcolorconvert()
that have aprocessor
paramater, it is a rawColorProcessor*
object that implements the color transformation. This is a special object created by aColorConfig
(seeOpenImageIO/color.h
for details).unpremult
: If true, unpremultiply the image (divide the RGB channels by alpha if it exists and is nonzero) before color conversion, then repremult after the after the color conversion. Passing unpremult=false skips this step, which may be desirable if you know that the image is “unassociated alpha” (a.k.a., “not pre-multiplied colors”).colorconfig
: An optionalColorConfig*
specifying an OpenColorIO configuration. If not supplied, the default OpenColorIO color configuration found by examining the$OCIO
environment variable will be used instead.
Functions
-
ImageBuf
colorconvert
(const ImageBuf &src, string_view fromspace, string_view tospace, bool unpremult = true, string_view context_key = "", string_view context_value = "", ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶ Transform between named color spaces, returning an ImageBuf result.
-
ImageBuf
colorconvert
(const ImageBuf &src, const ColorProcessor *processor, bool unpremult, ROI roi = {}, int nthreads = 0)¶ Transform using a ColorProcessor, returning an ImageBuf result.
-
bool
colorconvert
(ImageBuf &dst, const ImageBuf &src, string_view fromspace, string_view tospace, bool unpremult = true, string_view context_key = "", string_view context_value = "", ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶ Transform between named color spaces, storing reults into an existing ImageBuf.
-
bool
colorconvert
(ImageBuf &dst, const ImageBuf &src, const ColorProcessor *processor, bool unpremult, ROI roi = {}, int nthreads = 0)¶ Transform using a ColorProcessor, storing reults into an existing ImageBuf.
-
bool
colorconvert
(span<float> color, const ColorProcessor *processor, bool unpremult)¶ Apply a color transform in-place to just one color:
color[0..nchannels-1]
.nchannels
should either be 3 or 4 (if 4, the last channel is alpha).
-
inline bool
colorconvert
(float *color, int nchannels, const ColorProcessor *processor, bool unpremult)¶
Examples:
#include <OpenImageIO/imagebufalgo.h> #include <OpenImageIO/color.h> using namespace OIIO; ImageBuf Src ("tahoe.jpg"); ColorConfig cc; ColorProcessor *processor = cc.createColorProcessor ("vd8", "lnf"); ImageBuf dst = ImageBufAlgo::colorconvert (Src, processor, true); ColorProcessor::deleteColorProcessor (processor); // Equivalent, though possibly less efficient if you will be // converting many images using the same transformation: ImageBuf Src ("tahoe.jpg"); ImageBuf Dst = ImageBufAlgo::colorconvert (Src, "vd8", "lnf", true);
-
ImageBuf
OIIO::ImageBufAlgo
::
colormatrixtransform
(const ImageBuf &src, const Imath::M44f &M, bool unpremult = true, ROI roi = {}, int nthreads = 0)¶ Return a copy of the pixels of
src
within the ROI, applying a color transform specified by a 4x4 matrix. In-place operations (dst
==src
) are supported.The first three channels are presumed to be the color to be transformed, and the fourth channel (if it exists) is presumed to be alpha. Any additional channels will be simply copied unaltered.
- Version
2.1+
- Parameters
M
: A 4x4 matrix. Following Imath conventions, the color is a row vector and the matrix has the “translation” part in elements [12..14] (matching the memory layout of OpenGL or RenderMan), so the math iscolor * Matrix
(NOTM*c
).unpremult
: If true, unpremultiply the image (divide the RGB channels by alpha if it exists and is nonzero) before color conversion, then repremult after the after the color conversion. Passing unpremult=false skips this step, which may be desirable if you know that the image is “unassociated alpha” (a.k.a., “not pre-multiplied colors”).
Examples:
ImageBuf Src ("tahoe.jpg"); Imath::M44f M ( .8047379, .5058794, -.3106172, 0, -.3106172, .8047379, .5058794, 0, .5058794, -.3106172, .8047379, 0, 0, 0, 0, 1); ImageBuf dst = ImageBufAlgo::colormatrixtransform (Src, M);
-
ImageBuf
OIIO::ImageBufAlgo
::
ociolook
(const ImageBuf &src, string_view looks, string_view fromspace, string_view tospace, bool unpremult = true, bool inverse = false, string_view context_key = "", string_view context_value = "", ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶ Return a copy of the pixels of
src
within the ROI, applying an OpenColorIO “look” transform to the pixel values. In-place operations (dst
==src
) are supported.The first three channels are presumed to be the color to be transformed, and the fourth channel (if it exists) is presumed to be alpha. Any additional channels will be simply copied unaltered.
- Parameters
looks
: The looks to apply (comma-separated).fromspace/tospace
: For the varieties ofcolorconvert()
that use named color spaces, these specify the color spaces by name.unpremult
: If true, unpremultiply the image (divide the RGB channels by alpha if it exists and is nonzero) before color conversion, then repremult after the after the color conversion. Passing unpremult=false skips this step, which may be desirable if you know that the image is “unassociated alpha” (a.k.a., “not pre-multiplied colors”).inverse
: Iftrue
, it will reverse the color transformation and look application.context_key/context_value
: Optional key/value to establish a context (for example, a shot-specific transform).colorconfig
: An optionalColorConfig*
specifying an OpenColorIO configuration. If not supplied, the default OpenColorIO color configuration found by examining the$OCIO
environment variable will be used instead.
Examples:
ImageBuf Src ("tahoe.jpg"); ImageBuf Dst = ImageBufAlgo::ociolook (Src, "look", "vd8", "lnf", true, false, "SHOT", "pe0012");
- Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
ociolook
(ImageBuf &dst, const ImageBuf &src, string_view looks, string_view fromspace, string_view tospace, bool unpremult = true, bool inverse = false, string_view context_key = "", string_view context_value = "", ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
ImageBuf
OIIO::ImageBufAlgo
::
ociodisplay
(const ImageBuf &src, string_view display, string_view view, string_view fromspace = "", string_view looks = "", bool unpremult = true, string_view context_key = "", string_view context_value = "", ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶ Return the pixels of
src
within the ROI, applying an OpenColorIO “display” transform to the pixel values. In-place operations (dst
==src
) are supported.The first three channels are presumed to be the color to be transformed, and the fourth channel (if it exists) is presumed to be alpha. Any additional channels will be simply copied unaltered.
- Parameters
display
: The OCIO “display” to apply. If this is the empty string, the default display will be used.view
: The OCIO “view” to use. If this is the empty string, the default view for this display will be used.fromspace
: Iffromspace
is not supplied, it will assume that the source color space is whatever is indicated by the source image’s metadata or filename, and if that cannot be deduced, it will be assumed to be scene linear.looks
: The looks to apply (comma-separated). This may be empty, in which case no “look” is used. Note: this parameter value is not used when building against OpenColorIO 2.x.unpremult
: If true, unpremultiply the image (divide the RGB channels by alpha if it exists and is nonzero) before color conversion, then repremult after the after the color conversion. Passing unpremult=false skips this step, which may be desirable if you know that the image is “unassociated alpha” (a.k.a., “not pre-multiplied colors”).inverse
: Iftrue
, it will reverse the color transformation and display application.context_key/context_value
: Optional key/value to establish a context (for example, a shot-specific transform).colorconfig
: An optionalColorConfig*
specifying an OpenColorIO configuration. If not supplied, the default OpenColorIO color configuration found by examining the$OCIO
environment variable will be used instead.
Examples:
ImageBuf Src ("tahoe.exr"); ImageBuf Dst = ImageBufAlgo::ociodisplay (Src, "sRGB", "Film", "lnf", "", true, "SHOT", "pe0012");
- Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
ociodisplay
(ImageBuf &dst, const ImageBuf &src, string_view display, string_view view, string_view fromspace = "", string_view looks = "", bool unpremult = true, string_view context_key = "", string_view context_value = "", ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
ImageBuf
OIIO::ImageBufAlgo
::
ociofiletransform
(const ImageBuf &src, string_view name, bool unpremult = true, bool inverse = false, ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶ Return the pixels of
src
within the ROI, applying an OpenColorIO “file” transform. In-place operations (dst
==src
) are supported.The first three channels are presumed to be the color to be transformed, and the fourth channel (if it exists) is presumed to be alpha. Any additional channels will be simply copied unaltered.
- Parameters
name
: The name of the file containing the transform information.unpremult
: If true, unpremultiply the image (divide the RGB channels by alpha if it exists and is nonzero) before color conversion, then repremult after the after the color conversion. Passing unpremult=false skips this step, which may be desirable if you know that the image is “unassociated alpha” (a.k.a., “not pre-multiplied colors”).inverse
: Iftrue
, it will reverse the color transformation.colorconfig
: An optionalColorConfig*
specifying an OpenColorIO configuration. If not supplied, the default OpenColorIO color configuration found by examining the$OCIO
environment variable will be used instead.
Examples:
ImageBuf Src ("tahoe.jpg"); ImageBuf Dst = ImageBufAlgo::ociofiletransform (Src, "footransform.csp");
- Result-as-parameter version:
- bool
OIIO::ImageBufAlgo
::
ociofiletransform
(ImageBuf &dst, const ImageBuf &src, string_view name, bool unpremult = true, bool inverse = false, ColorConfig *colorconfig = nullptr, ROI roi = {}, int nthreads = 0)¶Write to an existing image
dst
(allocating if it is uninitialized).
-
group
premult
Premultiply or un-premultiply color by alpha
The
unpremult
operation returns (or copies intodst
) the pixels ofsrc
within the ROI, and in the process divides all color channels (those not alpha or z) by the alpha value, to “un-premultiply” them. This presumes that the image starts of as “associated alpha” a.k.a. “premultipled,” and you are converting to “unassociated alpha.” For pixels with alpha == 0, the color values are not modified.The
premult
operation returns (or copies intodst
) the pixels ofsrc
within the ROI, and in the process multiplies all color channels (those not alpha or z) by the alpha value, to “premultiply” them. This presumes that the image starts of as “unassociated alpha” a.k.a. “non-premultipled” and converts it to “associated alpha / premultipled.”The
repremult
operation is likepremult
, but preserves the color values of pixels whose alpha is 0. This is intended for cases where you unpremult, do an operation (such as color transforms), then want to return to associated/premultiplied alpha in that case, you want to make sure that “glow” pixels (those with alpha=0 but RGB > 0) are preserved for the round trip, and not crushed to black. This use case is distinct from a simplepremult
that is a one-time conversion from unassociated to associated alpha.All three operations are simply a copy if there is no identified alpha channel (and a no-op if
dst
andsrc
are the same image).Functions
-
ImageBuf
unpremult
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
unpremult
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
premult
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
premult
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
repremult
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
bool
repremult
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
Examples:
// Convert from unassociated alpha to associated alpha by // straightforward multiplication of color by alpha. ImageBuf Unassoc; // Assume somehow this has unassociated alpha ImageBuf Assoc = ImageBufAlgo::premult (Unassoc); // Convert in-place from associated alpha to unassociated alpha, // preserving the color of alpha==0 pixels. ImageBuf A; ImageBufAlgo::unpremult (A, A); // Finish the round-trip back to associated, still preserving the // color of alpha==0 pixels. This should result in exactly the same // pixel values we started with (within precision limits). ImageBufAlgo::repremult (A, A);
Import / export¶
-
group
make_texture
The
make_texture()
function turns an image into a tiled, MIP-mapped, texture file and write it to disk (outputfilename).Named fields in config:
format : Data format of the texture file (default: UNKNOWN = same format as the input)
tile_width/tile_height/tile_depth : Preferred tile size (default: 64x64x1)
Metadata in
config.extra_attribs
compression
(string) : Default: “zip”fovcot
(float) : Default: aspect ratio of the image resolution.planarconfig
(string) : Default: “separate”worldtocamera
(matrix) : World-to-camera matrix of the view.worldtoscreen
(matrix) : World-to-screen space matrix of the view.worldtoNDC
(matrix) : World-to-NDC space matrix of the view.wrapmodes
(string) : Default: “black,black”maketx:verbose
(int) : How much detail should go to outstream (0).maketx:runstats
(int) : If nonzero, print run stats to outstream (0).maketx:resize
(int) : If nonzero, resize to power of 2. (0)maketx:nomipmap
(int) : If nonzero, only output the top MIP level (0).maketx:updatemode
(int) : If nonzero, write new output only if the output file doesn’t already exist, or is older than the input file, or was created with different command-line arguments. (0)maketx:constant_color_detect
(int) : If nonzero, detect images that are entirely one color, and change them to be low resolution (default: 0).maketx:monochrome_detect
(int) : If nonzero, change RGB images which have R==G==B everywhere to single-channel grayscale (default: 0).maketx:opaque_detect
(int) : If nonzero, drop the alpha channel if alpha is 1.0 in all pixels (default: 0).maketx:compute_average
(int) : If nonzero, compute and store the average color of the texture (default: 1).maketx:unpremult
(int) : If nonzero, unpremultiply color by alpha before color conversion, then multiply by alpha after color conversion (default: 0).maketx:incolorspace
,maketx:outcolorspace
(string) : These two together will apply a color conversion (with OpenColorIO, if compiled). Default: “”maketx:colorconfig
(string) : Specifies a custom OpenColorIO color config file. Default: “”maketx:checknan
(int) : If nonzero, will consider it an error if the input image has any NaN pixels. (0)maketx:fixnan
(string) : If set to “black” or “box3”, will attempt to repair any NaN pixels found in the input image (default: “none”).maketx:set_full_to_pixels
(int) : If nonzero, doctors the full/display window of the texture to be identical to the pixel/data window and reset the origin to 0,0 (default: 0).maketx:filtername
(string) : If set, will specify the name of a high-quality filter to use when resampling for MIPmap levels. Default: “”, use bilinear resampling.maketx:highlightcomp
(int) : If nonzero, performs highlight compensation range compression and expansion around the resize, plus clamping negative pixel values to zero. This reduces ringing when using filters with negative lobes on HDR images.maketx:sharpen
(float) : If nonzero, sharpens details when creating MIPmap levels. The amount is the contrast metric. The default is 0, meaning no sharpening.maketx:nchannels
(int) : If nonzero, will specify how many channels the output texture should have, padding with 0 values or dropping channels, if it doesn’t the number of channels in the input. (default: 0, meaning keep all input channels)maketx:channelnames
(string) : If set, overrides the channel names of the output image (comma-separated).maketx:fileformatname
(string) : If set, will specify the output file format. (default: “”, meaning infer the format from the output filename)maketx:prman_metadata
(int) : If set, output some metadata that PRMan will need for its textures. (0)maketx:oiio_options
(int) : (Deprecated; all are handled by default)maketx:prman_options
(int) : If nonzero, override a whole bunch of settings as needed to make textures that are compatible with PRMan. (0)maketx:mipimages
(string) : Semicolon-separated list of alternate images to be used for individual MIPmap levels, rather than simply downsizing. (default: “”)maketx:full_command_line
(string) : The command or program used to generate this call, will be embedded in the metadata. (default: “”)maketx:ignore_unassoc
(int) : If nonzero, will disbelieve any evidence that the input image is unassociated alpha. (0)maketx:read_local_MB
(int) : If nonzero, will read the full input file locally if it is smaller than this threshold. Zero causes the system to make a good guess at a reasonable threshold (e.g. 1 GB). (0)maketx:forcefloat
(int) : Forces a conversion through float data for the sake of ImageBuf math. (1)maketx:hash
(int) : Compute the sha1 hash of the file in parallel. (1)maketx:allow_pixel_shift
(int) : Allow up to a half pixel shift per mipmap level. The fastest path may result in a slight shift in the image, accumulated for each mip level with an odd resolution. (0)maketx:bumpformat
(string) : For the MakeTxBumpWithSlopes mode, chooses whether to assume the map is a height map (“height”), a normal map (“normal”), or automatically determine it from the number of channels (“auto”, the default).
- Parameters
mode
: Describes what type of texture file we are creating and may be one of:MakeTxTexture
: Ordinary 2D texture.MakeTxEnvLatl
: Latitude-longitude environment mapMakeTxEnvLatlFromLightProbe
: Latitude-longitude environment map constructed from a “light probe” image.MakeTxBumpWithSlopes
: Bump/displacement map with extra slope data channels (6 channels total, containing both the height and 1st and 2nd moments of slope distributions) for bump-to-roughness conversion in shaders.
outputfilename
: Name of the file in which to save the resulting texture.config
: An ImageSpec that contains all the information and special instructions for making the texture. Anything set in config (format, tile size, or named metadata) will take precedence over whatever is specified by the input file itself. Additionally, named metadata that starts with “maketx:” will not be output to the file itself, but may contain instructions controlling how the texture is created. The full list of supported configuration options is listed below.outstream
: If notnullptr
, it should point to a stream (for example,&std::out
, or a pointer to a localstd::stringstream
to capture output), which is where console output and error messages will be deposited.
Functions
-
bool
make_texture
(MakeTextureMode mode, const ImageBuf &input, string_view outputfilename, const ImageSpec &config, std::ostream *outstream = nullptr)¶ Version of make_texture that starts with an ImageBuf.
-
bool
make_texture
(MakeTextureMode mode, string_view filename, string_view outputfilename, const ImageSpec &config, std::ostream *outstream = nullptr)¶ Version of make_texture that starts with a filename and reads the input from that file, rather than being given an ImageBuf directly.
-
bool
make_texture
(MakeTextureMode mode, const std::vector<std::string> &filenames, string_view outputfilename, const ImageSpec &config, std::ostream *outstream = nullptr)¶ Version of make_texture that takes multiple filenames (reserved for future expansion, such as assembling several faces into a cube map).
Examples:
// This command line: // maketx in.exr --hicomp --filter lanczos3 --opaque-detect \ // -o texture.exr // is equivalent to: ImageBuf Input ("in.exr"); ImageSpec config; config.attribute ("maketx:highlightcomp", 1); config.attribute ("maketx:filtername", "lanczos3"); config.attribute ("maketx:opaque_detect", 1); stringstream s; bool ok = ImageBufAlgo::make_texture (ImageBufAlgo::MakeTxTexture, Input, "texture.exr", config, &s); if (! ok) std::cout << "make_texture error: " << s.str() << "\n";
OpenCV interoperability is performed by the from_OpenCV()
and
to_OpenCV()
functions:
-
ImageBuf
OIIO::ImageBufAlgo
::
from_OpenCV
(const cv::Mat &mat, TypeDesc convert = TypeUnknown, ROI roi = {}, int nthreads = 0)¶ Convert an OpenCV cv::Mat into an ImageBuf, copying the pixels (optionally converting to the pixel data type specified by
convert
, if not UNKNOWN, which means to preserve the original data type if possible). Return true if ok, false if it couldn’t figure out how to make the conversion from Mat to ImageBuf. If OpenImageIO was compiled without OpenCV support, this function will return an empty image with error message set.
-
bool
OIIO::ImageBufAlgo
::
to_OpenCV
(cv::Mat &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Construct an OpenCV cv::Mat containing the contents of ImageBuf src, and return true. If it is not possible, or if OpenImageIO was compiled without OpenCV support, then return false. Note that OpenCV only supports up to 4 channels, so >4 channel images will be truncated in the conversion.
-
ImageBuf
OIIO::ImageBufAlgo
::
capture_image
(int cameranum = 0, TypeDesc convert = TypeUnknown)¶ Capture a still image from a designated camera. If able to do so, store the image in dst and return true. If there is no such device, or support for camera capture is not available (such as if OpenCV support was not enabled at compile time), return false and do not alter dst.
Examples:
ImageBuf WebcamImage = ImageBufAlgo::capture_image (0, TypeDesc::UINT8); WebcamImage.write ("webcam.jpg");
Deep images¶
A number of ImageBufAlgo functions are designed to work with “deep” images. These are detailed below. In general, ImageBufAlgo functions not listed in this section should not be expected to work with deep images.
Functions specific to deep images¶
-
ImageBuf
OIIO::ImageBufAlgo
::
deepen
(const ImageBuf &src, float zvalue = 1.0f, ROI roi = {}, int nthreads = 0)¶ Return the “deep” equivalent of the “flat” input
src
. Turning a flat image into a deep one means:If the
src
image has a “Z” channel: if the source pixel’s Z channel value is not infinite, the corresponding pixel ofdst
will get a single depth sample that copies the data from the source pixel; otherwise, dst will get an empty pixel. In other words, infinitely far pixels will not turn into deep samples.If the
src
image lacks a “Z” channel: if any of the source pixel’s channel values are nonzero, the corresponding pixel ofdst
will get a single depth sample that copies the data from the source pixel and uses the zvalue parameter for the depth; otherwise, if all source channels in that pixel are zero, the destination pixel will get no depth samples.
If
src
is already a deep image, it will just copy pixel values fromsrc
.
Examples:
ImageBuf Flat ("RGBAZ.exr"); ImageBuf Deep = ImageBufAlgo::deepen (Flat);
-
ImageBuf
OIIO::ImageBufAlgo
::
flatten
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Return the “flattened” composite of deep image
src
. That is, it converts a deep image to a simple flat image by front-to- back compositing the samples within each pixel. Ifsrc
is already a non-deep/flat image, it will just copy pixel values fromsrc
todst
. Ifdst
is not already an initialized ImageBuf, it will be sized to matchsrc
(but made non-deep).
-
ImageBuf
OIIO::ImageBufAlgo
::
deep_merge
(const ImageBuf &A, const ImageBuf &B, bool occlusion_cull = true, ROI roi = {}, int nthreads = 0)¶ Return the deep merge of the samples of deep images
A
andB
, overwriting any existing samples ofdst
in the ROI. Ifocclusion_cull
is true, any samples occluded by an opaque sample will be deleted.
Examples:
ImageBuf DeepA ("hardsurf.exr"); ImageBuf DeepB ("volume.exr"); ImageBuf Merged = ImageBufAlgo::deep_merge (DeepA, DeepB);
-
ImageBuf
OIIO::ImageBufAlgo
::
deep_holdout
(const ImageBuf &src, const ImageBuf &holdout, ROI roi = {}, int nthreads = 0)¶ Return the samples of deep image
src
that are closer than the opaque frontier of deep image holdout, returning true upon success and false for any failures. Samples ofsrc
that are farther than the first opaque sample of holdout (for the corresponding pixel)will not be copied todst
. Image holdout is only used as the depth threshold; no sample values from holdout are themselves copied todst
.
Examples:
ImageBuf Src ("image.exr"); ImageBuf Holdout ("holdout.exr"); ImageBuf Merged = ImageBufAlgo::deep_holdout (Src, Holdout);
General functions that also work for deep images¶
-
ImageBuf
channels
(const ImageBuf &src, int nchannels, cspan<int> channelorder, cspan<float> channelvalues = NULL, cspan<std::string> newchannelnames = {}, bool shuffle_channel_names = false)¶ -
bool
channels
(ImageBuf &dst, const ImageBuf &src, int nchannels, cspan<int> channelorder, cspan<float> channelvalues = NULL, cspan<std::string> newchannelnames = {}, bool shuffle_channel_names = false)¶ Reorder, rename, remove, or add channels to a deep image.
-
bool
compare
(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, CompareResults &result, ROI roi = {}, int nthreads = 0)¶ Numerically compare two images.
-
bool
computePixelStats
(PixelStats &stats, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Compute per-channel statistics about the image.
-
ImageBuf
crop
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ -
bool
crop
(ImageBuf &dst, const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ Crop the specified region of
src
, discarding samples outside the ROI.
-
ROI
nonzero_region
(const ImageBuf &src, ROI roi = {}, int nthreads = 0)¶ For “deep” images, this function returns the smallest ROI that contains all pixels that contain depth samples, and excludes the border pixels that contain no depth samples at all.
-
ImageBuf
add
(const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶ -
bool
add
(ImageBuf &dst, const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
sub
(const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶ -
bool
sub
(ImageBuf &dst, const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
mul
(const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶ -
bool
mul
(ImageBuf &dst, const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶
-
ImageBuf
div
(const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶ -
bool
div
(ImageBuf &dst, const ImageBuf &A, cspan<float> B, ROI roi = {}, int nthreads = 0)¶ Add, subtract, multiply, or divide all the samples in a deep image
A
by per-channel valuesB[]
.
-
ImageBuf
fixNonFinite
(const ImageBuf &src, NonFiniteFixMode mode = NONFINITE_BOX3, int *pixelsFixed = nullptr, ROI roi = {}, int nthreads = 0)¶ -
bool
fixNonFinite
(ImageBuf &dst, const ImageBuf &src, NonFiniteFixMode mode = NONFINITE_BOX3, int *pixelsFixed = nullptr, ROI roi = {}, int nthreads = 0)¶ Repair nonfinite (
NaN
orInf
) values, setting them to 0.0.
-
ImageBuf
resample
(const ImageBuf &src, bool interpolate = true, ROI roi = {}, int nthreads = 0)¶ -
bool
resample
(ImageBuf &dst, const ImageBuf &src, bool interpolate = true, ROI roi = {}, int nthreads = 0)¶ Compute a resized version of the corresponding portion of
src
(mapping such that the “full” image window of each correspond to each other, regardless of resolution), for each pixel merely copying the closest deep pixel of the source image (no true interpolation is done for deep images).