Skip to content

Allow Cimg::get_warp output CImg to be provided #414

@rtobar

Description

@rtobar

While doing some profiling on our R imager package that uses CImg underneath, I found that the fundamental CImg::get_warp operation allocates the output CImg object internally, then returns it. This prevents us from saving an allocation when returning the data back to R, which needs to be done on a different buffer.

Locally I have the following patch that allows me to avoid this, and I was wondering whether this would be something that would be considered as a desired feature upstream. In other words: would such a PR be welcome?

diff --git a/inst/include/CImg.h b/inst/include/CImg.h
index 9bb8997..59162fa 100644
--- a/inst/include/CImg.h
+++ b/inst/include/CImg.h
@@ -38609,8 +38609,26 @@ namespace cimg_library {
                                     "have different XYZ dimensions.",
                                     cimg_instance,
                                     p_warp._width,p_warp._height,p_warp._depth,p_warp._spectrum,p_warp._data);
 
       CImg<T> res(p_warp._width,p_warp._height,p_warp._depth,_spectrum);
+      do_warp(p_warp, res, mode, interpolation, boundary_conditions);
+      return res;
+    }
+
+    //! Warp image content by a warping field, with the user providing the output image \newinstance
+    template<typename t>
+    void do_warp(const CImg<t>& p_warp, CImg<t> &res, const unsigned int mode=0,
+                     const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const {
+      if (is_empty() || !p_warp) return;
+      if (mode && !is_sameXYZ(p_warp))
+        throw CImgArgumentException(_cimg_instance
+                                    "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) "
+                                    "have different XYZ dimensions.",
+                                    cimg_instance,
+                                    p_warp._width,p_warp._height,p_warp._depth,p_warp._spectrum,p_warp._data);
+      if (!res.is_sameXYZ(p_warp) || res._spectrum != _spectrum)
+        throw CImgArgumentException("warp(): output buffer has XYZ dimensions different warping field (%u,%u,%u) "
+                                    "or different spectrum than source image (%u)",
+                                    p_warp._width, p_warp._height, p_warp._depth, _spectrum);
 
       if (p_warp._spectrum==1) { // 1D warping
         if (mode>=3) { // Forward-relative warp
@@ -39422,7 +39440,6 @@ namespace cimg_library {
             }
         }
       }
-      return res;
     }
 
     //! Generate a 2D representation of a 3D image, with XY,XZ and YZ views.

The way I'm then using this is (very roughly) like this:

// inputs
unsigned int mode = ...;
unsigned int interpolation = ...;
unsigned int boundary_conditions = ...;
CImg<double> img = ...;
CImg<double> wrp = ...;
double *my_r_buffer = ...;

// Create a shared CImg object with the R buffer, and the `warp` result there
CImg<double> output {my_r_buffer, wrp.width(), wrp.height(), wrp.depth(), img.spectrum(), true};
img.do_warp(wrp, output, mode, interpolation, boundary_conditions);
return my_r_buffer;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions