Yalantis/uCrop · error · CImgArgumentException

CImg< >::streamline(): Invalid specified integration length…

Error message

CImg<%s>::streamline(): Invalid specified integration length %g (should be >0).

What it means

CImg<T>::streamline() validates the integration step length dl and throws CImgArgumentException if dl<=0, since a positive step is required for the RK-style integration. It also silently returns an empty image if the total length L<=0 or the seed point lies outside the optional bounding box.

Solutions

  1. Pass a strictly positive dl (e.g. 0.1, the default) to streamline().
  2. Validate/normalize the step length before the call: if (dl <= 0) dl = 0.1f; or throw your own descriptive error.
  3. Also ensure L > 0 and the seed point is inside the bounding box (x0..x1, y0..y1, z0..z1) when using the bounded variant, otherwise the call silently returns an empty image.
  4. Derive dl defensively, e.g. dl = L / std::max(1u, nb_steps), to avoid division producing 0 or negative values.

Example fix

// before
float dl = L / steps;               // steps could be 0
img.streamline(func, x, y, z, L, dl);
// after
float dl = steps > 0 ? L / steps : 0.1f;
if (dl <= 0) dl = 0.1f;
img.streamline(func, x, y, z, L, dl);
Defensive patterns

Strategy: validation

Validate before calling

if (!(dl > 0)) throw std::invalid_argument("streamline dl must be > 0");
if (!(L > 0)) throw std::invalid_argument("streamline L must be > 0");

Try / catch

try { img.streamline(func, x, y, z, L, dl); }
catch (CImgArgumentException& e) { /* clamp dl to 0.1f and retry */ }

Prevention

When it happens

Trigger: Calling the functor-based streamline(...) overload with dl=0, a negative dl, or NaN, e.g. passing a user-supplied step length without validation.

Common situations: Computing dl from a user parameter or a division (e.g. L/steps with steps=0 or negative) that yields 0 or negative values; configuration default of 0 meaning 'unset'; float precision pushing dl to 0.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/c5c59b6b74c0280b. Report an issue: GitHub.

Appendix: source

Thrown at ucrop/src/main/jni/CImg.h:41329

       \param is_backward_tracking Tells if the streamline is estimated forward or backward.
       \param is_oriented_only Tells if the direction of the vectors must be ignored.
       \param x0 X-coordinate of the first bounding-box vertex.
       \param y0 Y-coordinate of the first bounding-box vertex.
       \param z0 Z-coordinate of the first bounding-box vertex.
       \param x1 X-coordinate of the second bounding-box vertex.
       \param y1 Y-coordinate of the second bounding-box vertex.
       \param z1 Z-coordinate of the second bounding-box vertex.
    **/
    template<typename tfunc>
    static CImg<floatT> streamline(const tfunc& func,
                                   const float x, const float y, const float z,
                                   const float L=256, const float dl=0.1f,
                                   const unsigned int interpolation_type=2, const bool is_backward_tracking=false,
                                   const bool is_oriented_only=false,
                                   const float x0=0, const float y0=0, const float z0=0,
                                   const float x1=0, const float y1=0, const float z1=0) {
      if (dl<=0)
        throw CImgArgumentException("CImg<%s>::streamline(): Invalid specified integration length %g "
                                    "(should be >0).",
                                    pixel_type(),
                                    dl);

      const bool is_bounded = (x0!=x1 || y0!=y1 || z0!=z1);
      if (L<=0 || (is_bounded && (x<x0 || x>x1 || y<y0 || y>y1 || z<z0 || z>z1))) return CImg<floatT>();
      const unsigned int size_L = (unsigned int)cimg::round(L/dl + 1);
      CImg<floatT> coordinates(size_L,3);
      const float dl2 = dl/2;
      float
        *ptr_x = coordinates.data(0,0),
        *ptr_y = coordinates.data(0,1),
        *ptr_z = coordinates.data(0,2),
        pu = (float)(dl*func(x,y,z,0)),
        pv = (float)(dl*func(x,y,z,1)),
        pw = (float)(dl*func(x,y,z,2)),
        X = x, Y = y, Z = z;

View on GitHub (pinned to f788b534b4)