Skip to content

Commit fdafe1c

Browse files
authored
ImageBufAlgo: Initial implementation of st_warp transform function (#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`
1 parent 092b6af commit fdafe1c

File tree

9 files changed

+447
-16
lines changed

9 files changed

+447
-16
lines changed

src/doc/oiiotool.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,6 +3268,41 @@ current top image.
32683268
oiiotool mandrill.tif --warp "0.707,0.707,0,-0.707,0.707,0,128,-53.02,1" -o warped.tif
32693269

32703270

3271+
.. option:: --st_warp
3272+
3273+
Use the top image as a set of normalized `st` image coordinates to warp the
3274+
second image in the stack.
3275+
3276+
Optional appended modifiers include:
3277+
3278+
`filter=` *name*
3279+
Filter name. The default is `lanczos3`.
3280+
3281+
`chan_s=` *index*
3282+
The index of the `s` channel in the `st` image (default=0).
3283+
3284+
`chan_t=` *index*
3285+
The index of the `t` channel in the `st` image (default=1).
3286+
3287+
`flip_s=` *bool*
3288+
If nonzero, mirror the `s` coordinates along the horizontal axis. Useful
3289+
for coordinates authored in terms of an origin other than the upper-left
3290+
corner (default=0).
3291+
3292+
`flip_t=` *bool*
3293+
If nonzero, mirror the `t` coordinates along the vertical axis. Useful
3294+
for coordinates authored in terms of an origin other than the upper-left
3295+
corner (default=0).
3296+
3297+
Examples::
3298+
3299+
oiiotool mandrill.tif distortion_st.tif --st_warp -o mandrill_distorted.tif
3300+
3301+
# Using an `st` map authored in terms of a lower-left origin (e.g. by
3302+
# Nuke), so flip the vertical (`t`) coordinate.
3303+
oiiotool mandrill.tif st_from_nuke.tif --st_warp:filter=triangle:flip_t=1 -o mandrill_distorted.tif
3304+
3305+
32713306
.. option:: --convolve
32723307

32733308
Use the top image as a kernel to convolve the next image farther down

src/include/OpenImageIO/imagebufalgo.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,68 @@ bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, M33fParam M,
790790
/// @}
791791

792792

793+
/// @defgroup st_warp (st_warp: warp an image using per-pixel st coordinates)
794+
/// @{
795+
///
796+
/// Warp the `src` image using "st" coordinates from a secondary `stbuf` image.
797+
///
798+
/// Each pixel in the `stbuf` image is used as a normalized image-space
799+
/// coordinate in the `src` image, which is then sampled at that position using
800+
/// the given reconstruction filter to produce an output pixel.
801+
///
802+
/// The transform is only defined over the area of the `stbuf` image, and thus
803+
/// the given `roi` argument will be intersected with its geometry.
804+
///
805+
/// \b NOTE: The current behavior of this transform is modeled to match Nuke's
806+
/// STMap node.
807+
///
808+
/// @param dst
809+
/// The output ImageBuf. If an initialized buffer is provided, its
810+
/// full-size dimensions must match those of `stbuf`.
811+
/// @param src
812+
/// The source ImageBuf to warp.
813+
/// @param stbuf
814+
/// The ImageBuf holding the st coordinates. This must be holding
815+
/// a floating-point pixel data type.
816+
/// @param chan_s
817+
/// The index of the "s" channel in the `stbuf` image. This defaults
818+
/// to its first channel.
819+
/// @param chan_t
820+
/// The index of the "t" channel in the `stbuf` image. This defaults
821+
/// to its second channel.
822+
/// @param flip_s
823+
/// Whether to mirror the "s" coordinate along the horizontal axis
824+
/// when computing source pixel positions. This is useful if the
825+
/// coordinates are defined in terms of a different image origin
826+
/// than OpenImageIO's.
827+
/// @param flip_t
828+
/// Whether to mirror the "t" coordinate along the vertical axis
829+
/// when computing source pixel positions. This is useful if the
830+
/// coordinates are defined in terms of a different image origin
831+
/// than OpenImageIO's.
832+
833+
ImageBuf OIIO_API st_warp (const ImageBuf &src, const ImageBuf& stbuf,
834+
string_view filtername=string_view(),
835+
float filterwidth=0.0f, int chan_s=0, int chan_t=1,
836+
bool flip_s=false, bool flip_t=false, ROI roi={},
837+
int nthreads=0);
838+
ImageBuf OIIO_API st_warp (const ImageBuf &src, const ImageBuf& stbuf,
839+
const Filter2D *filter, int chan_s=0, int chan_t=1,
840+
bool flip_s=false, bool flip_t=false, ROI roi={},
841+
int nthreads=0);
842+
bool OIIO_API st_warp (ImageBuf &dst, const ImageBuf &src,
843+
const ImageBuf& stbuf,
844+
string_view filtername=string_view(),
845+
float filterwidth=0.0f, int chan_s=0, int chan_t=1,
846+
bool flip_s=false, bool flip_t=false, ROI roi={},
847+
int nthreads=0);
848+
bool OIIO_API st_warp (ImageBuf &dst, const ImageBuf &src,
849+
const ImageBuf& stbuf, const Filter2D *filter,
850+
int chan_s=0, int chan_t=1, bool flip_s=false,
851+
bool flip_t=false, ROI roi={}, int nthreads=0);
852+
/// @}
853+
854+
793855
/// Compute per-pixel sum `A + B`, returning the result image.
794856
///
795857
/// `A` and `B` may each either be an `ImageBuf&`, or a `cspan<float>`

src/libOpenImageIO/imagebufalgo_test.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,43 @@ test_IBAprep()
872872

873873

874874

875+
// Test extra validation checks done by `st_warp`
876+
void
877+
test_validate_st_warp_checks()
878+
{
879+
// using namespace ImageBufAlgo;
880+
std::cout << "test st_warp validation checks" << std::endl;
881+
882+
const int size = 16;
883+
ImageSpec srcSpec(size, size, 3, TypeDesc::FLOAT);
884+
ImageBuf SRC(srcSpec);
885+
ImageBuf ST;
886+
ImageBuf DST;
887+
888+
ImageBufAlgo::zero(SRC);
889+
890+
// Fail: Uninitialized ST buffer
891+
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST));
892+
893+
ROI disjointROI(size, size, size * 2, size * 2, 0, 1, 0, 2);
894+
ImageSpec stSpec(disjointROI, TypeDesc::HALF);
895+
ST.reset(stSpec);
896+
// Fail: Non-intersecting ST and output ROIs
897+
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST));
898+
899+
stSpec = ImageSpec(size, size, 2, TypeDesc::HALF);
900+
ST.reset(stSpec);
901+
902+
DST.reset();
903+
// Fail: Out-of-range chan_s
904+
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST, nullptr, 2));
905+
// Fail: Out-of-range chan_t
906+
OIIO_CHECK_ASSERT(!ImageBufAlgo::st_warp(DST, SRC, ST, nullptr, 0, 2));
907+
// Success
908+
OIIO_CHECK_ASSERT(ImageBufAlgo::st_warp(DST, SRC, ST, nullptr));
909+
}
910+
911+
875912
void
876913
benchmark_parallel_image(int res, int iters)
877914
{
@@ -988,6 +1025,7 @@ main(int argc, char** argv)
9881025
histogram_computation_test();
9891026
test_maketx_from_imagebuf();
9901027
test_IBAprep();
1028+
test_validate_st_warp_checks();
9911029
test_opencv();
9921030

9931031
benchmark_parallel_image(64, iterations * 64);

0 commit comments

Comments
 (0)