Yalantis/uCrop · error · CImgArgumentException

cimg::mod(): Specified modulo value is 0.

Error message

cimg::mod(): Specified modulo value is 0.

What it means

CImg's cimg::mod(x, m) computes x modulo m; for non-floating-point types a zero modulus is invalid, so it throws CImgArgumentException('cimg::mod(): Specified modulo value is 0.'). For float/double it returns NaN instead of throwing. This guards against a degenerate modulo (division by zero) inside image arithmetic.

Source

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

    //! Return the nearest power of 2 higher than given value.
    template<typename T>
    inline cimg_uint64 nearest_pow2(const T& x) {
      cimg_uint64 i = 1;
      while (x>i) i<<=1;
      return i;
    }

    //! Return the modulo of a value.
    /**
       \param x Input value.
       \param m Modulo value.
       \note This modulo function accepts negative and floating-points modulo numbers, as well as variables of any type.
    **/
    template<typename T>
    inline T mod(const T& x, const T& m) {
      if (!m) {
        if (cimg::type<T>::is_float()) return cimg::type<T>::nan();
        else throw CImgArgumentException("cimg::mod(): Specified modulo value is 0.");
      }
      const double dx = (double)x, dm = (double)m;
      if (!cimg::type<double>::is_finite(dm)) return x;
      if (cimg::type<double>::is_finite(dx)) return (T)(dx - dm * std::floor(dx / dm));
      return (T)0;
    }
    inline int mod(const bool x, const bool m) {
      if (!m) throw CImgArgumentException("cimg::mod(): Specified modulo value is 0.");
      return x?1:0;
    }
    inline int mod(const unsigned char x, const unsigned char m) {
      if (!m) throw CImgArgumentException("cimg::mod(): Specified modulo value is 0.");
      return x%m;
    }
    inline int mod(const char x, const char m) {
      if (!m) throw CImgArgumentException("cimg::mod(): Specified modulo value is 0.");
#if defined(CHAR_MAX) && CHAR_MAX==255
      return x%m;

View on GitHub (pinned to f788b534b4)

Solutions

  1. Validate the modulus before calling: if (m == 0) handle/skip, otherwise call cimg::mod(x, m).
  2. Use floating-point types (float/double) if NaN-on-zero is acceptable semantics for your code.
  3. Ensure upstream values (image width/height, user input) are nonzero before they reach mod().
  4. Replace the call with an explicit branch: m != 0 ? cimg::mod(x, m) : fallbackValue.

Example fix

// before
const int r = cimg::mod(offset, step); // step may be 0
// after
if (step == 0) throw std::invalid_argument("step must be non-zero");
const int r = cimg::mod(offset, step);
Defensive patterns

Strategy: validation

Validate before calling

if (m == T(0)) {
    throw std::invalid_argument("cimg::mod: modulo value must be non-zero");
}
const T r = cimg::mod(x, m);

Type guard

template<typename T>
bool is_valid_modulus(const T& m) {
    return m != T(0);
}

Try / catch

try {
    result = cimg::mod(x, m);
} catch (cimg_library::CImgArgumentException& e) {
    std::fprintf(stderr, "Zero modulus: %s\n", e.what());
    result = fallback_value;
}

Prevention

When it happens

Trigger: Calling cimg::mod(x, 0) or mod(x, m) where m is a computed expression that evaluated to 0 (e.g. an image pixel value, a divisor from user data, or an uninitialized variable), with an integer/char/short/int type.

Common situations: Dividing/masking image coordinates by a value taken from image metadata or user input that is 0; template code where T is instantiated as an integer type while the caller assumed float NaN semantics; loop bounds computed as width/height of an empty image (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/6254063b4a1e1819. Report an issue: GitHub.