Skip to content

Commit

Permalink
ImageBufAlgo: Initial implementation of st_warp transform function (A…
Browse files Browse the repository at this point in the history
…cademySoftwareFoundation#3379)

* Initial implementation of `ImageBufAlgo::st_warp`

* Simplify default filter logic, and share it with `ImageBufAlgo::warp`

* Add st_warp to oiiotool

* Add tests for bespoke `st_warp` validations that are done before IBAprep

* Add st_warp test to oiiotool-xform testsuite

* Address review notes

- Remove ST buffer datatype guard
- Simplify additional ROI prep
- Remove unnecessary buffer reallocation

* Use sample accumulator type for source/dest iterator USERT

* Add `--st_warp` section to `oiiotool.rst`
  • Loading branch information
nrusch authored and lgritz committed Apr 15, 2022
1 parent 594776d commit 074f70e
Show file tree
Hide file tree
Showing 9 changed files with 447 additions and 16 deletions.
35 changes: 35 additions & 0 deletions src/doc/oiiotool.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3081,6 +3081,41 @@ current top image.
oiiotool mandrill.tif --warp "0.707,0.707,0,-0.707,0.707,0,128,-53.02,1" -o warped.tif


.. option:: --st_warp

Use the top image as a set of normalized `st` image coordinates to warp the
second image in the stack.

Optional appended modifiers include:

`filter=` *name*
Filter name. The default is `lanczos3`.

`chan_s=` *index*
The index of the `s` channel in the `st` image (default=0).

`chan_t=` *index*
The index of the `t` channel in the `st` image (default=1).

`flip_s=` *bool*
If nonzero, mirror the `s` coordinates along the horizontal axis. Useful
for coordinates authored in terms of an origin other than the upper-left
corner (default=0).

`flip_t=` *bool*
If nonzero, mirror the `t` coordinates along the vertical axis. Useful
for coordinates authored in terms of an origin other than the upper-left
corner (default=0).

Examples::

oiiotool mandrill.tif distortion_st.tif --st_warp -o mandrill_distorted.tif

# Using an `st` map authored in terms of a lower-left origin (e.g. by
# Nuke), so flip the vertical (`t`) coordinate.
oiiotool mandrill.tif st_from_nuke.tif --st_warp:filter=triangle:flip_t=1 -o mandrill_distorted.tif


.. option:: --convolve

Use the top image as a kernel to convolve the next image farther down
Expand Down
62 changes: 62 additions & 0 deletions src/include/OpenImageIO/imagebufalgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,68 @@ bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, const Imath::M33f &M,
/// @}


/// @defgroup st_warp (st_warp: warp an image using per-pixel st coordinates)
/// @{
///
/// Warp the `src` image using "st" coordinates from a secondary `stbuf` image.
///
/// Each pixel in the `stbuf` image is used as a normalized image-space
/// coordinate in the `src` image, which is then sampled at that position using
/// the given reconstruction filter to produce an output pixel.
///
/// The transform is only defined over the area of the `stbuf` image, and thus
/// the given `roi` argument will be intersected with its geometry.
///
/// \b NOTE: The current behavior of this transform is modeled to match Nuke's
/// STMap node.
///
/// @param dst
/// The output ImageBuf. If an initialized buffer is provided, its
/// full-size dimensions must match those of `stbuf`.
/// @param src
/// The source ImageBuf to warp.
/// @param stbuf
/// The ImageBuf holding the st coordinates. This must be holding
/// a floating-point pixel data type.
/// @param chan_s
/// The index of the "s" channel in the `stbuf` image. This defaults
/// to its first channel.
/// @param chan_t
/// The index of the "t" channel in the `stbuf` image. This defaults
/// to its second channel.
/// @param flip_s
/// Whether to mirror the "s" coordinate along the horizontal axis
/// when computing source pixel positions. This is useful if the
/// coordinates are defined in terms of a different image origin
/// than OpenImageIO's.
/// @param flip_t
/// Whether to mirror the "t" coordinate along the vertical axis
/// when computing source pixel positions. This is useful if the
/// coordinates are defined in terms of a different image origin
/// than OpenImageIO's.

ImageBuf OIIO_API st_warp (const ImageBuf &src, const ImageBuf& stbuf,
string_view filtername=string_view(),
float filterwidth=0.0f, int chan_s=0, int chan_t=1,
bool flip_s=false, bool flip_t=false, ROI roi={},
int nthreads=0);
ImageBuf OIIO_API st_warp (const ImageBuf &src, const ImageBuf& stbuf,
const Filter2D *filter, int chan_s=0, int chan_t=1,
bool flip_s=false, bool flip_t=false, ROI roi={},
int nthreads=0);
bool OIIO_API st_warp (ImageBuf &dst, const ImageBuf &src,
const ImageBuf& stbuf,
string_view filtername=string_view(),
float filterwidth=0.0f, int chan_s=0, int chan_t=1,
bool flip_s=false, bool flip_t=false, ROI roi={},
int nthreads=0);
bool OIIO_API st_warp (ImageBuf &dst, const ImageBuf &src,
const ImageBuf& stbuf, const Filter2D *filter,
int chan_s=0, int chan_t=1, bool flip_s=false,
bool flip_t=false, ROI roi={}, int nthreads=0);
/// @}


/// Compute per-pixel sum `A + B`, returning the result image.
///
/// `A` and `B` may each either be an `ImageBuf&`, or a `cspan<float>`
Expand Down
38 changes: 38 additions & 0 deletions src/libOpenImageIO/imagebufalgo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,43 @@ test_IBAprep()



// Test extra validation checks done by `st_warp`
void
test_validate_st_warp_checks()
{
// using namespace ImageBufAlgo;
std::cout << "test st_warp validation checks" << std::endl;

const int size = 16;
ImageSpec srcSpec(size, size, 3, TypeDesc::FLOAT);
ImageBuf SRC(srcSpec);
ImageBuf ST;
ImageBuf DST;

ImageBufAlgo::zero(SRC);

// Fail: Uninitialized ST buffer
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST));

ROI disjointROI(size, size, size * 2, size * 2, 0, 1, 0, 2);
ImageSpec stSpec(disjointROI, TypeDesc::HALF);
ST.reset(stSpec);
// Fail: Non-intersecting ST and output ROIs
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST));

stSpec = ImageSpec(size, size, 2, TypeDesc::HALF);
ST.reset(stSpec);

DST.reset();
// Fail: Out-of-range chan_s
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST, nullptr, 2));
// Fail: Out-of-range chan_t
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST, nullptr, 0, 2));
// Success
OIIO_CHECK_ASSERT(ImageBufAlgo::st_warp(DST, SRC, ST, nullptr));
}


void
benchmark_parallel_image(int res, int iters)
{
Expand Down Expand Up @@ -988,6 +1025,7 @@ main(int argc, char** argv)
histogram_computation_test();
test_maketx_from_imagebuf();
test_IBAprep();
test_validate_st_warp_checks();
test_opencv();

benchmark_parallel_image(64, iterations * 64);
Expand Down
Loading

0 comments on commit 074f70e

Please sign in to comment.