Yalantis/uCrop · warning

invert(): LAPACK function dgetrf_() returned error code %d.

Error message

invert(): LAPACK function dgetrf_() returned error code %d.

What it means

CImg::invert() with LU decomposition calls LAPACK dgetrf_() to factor the matrix before inverting; a nonzero INFO from dgetrf_ means the LU factorization failed, typically because a diagonal pivot was exactly zero (singular matrix). On failure CImg warns and fills the matrix with zeros instead of throwing.

Source

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

      } else if (dete!=0. && _width==3) {
        const double
          a = _data[0], d = _data[1], g = _data[2],
          b = _data[3], e = _data[4], h = _data[5],
          c = _data[6], f = _data[7], i = _data[8];
        _data[0] = (T)((i*e - f*h)/dete), _data[1] = (T)((g*f - i*d)/dete), _data[2] = (T)((d*h - g*e)/dete);
        _data[3] = (T)((h*c - i*b)/dete), _data[4] = (T)((i*a - c*g)/dete), _data[5] = (T)((g*b - a*h)/dete);
        _data[6] = (T)((b*f - e*c)/dete), _data[7] = (T)((d*c - a*f)/dete), _data[8] = (T)((a*e - d*b)/dete);
      } else {

#ifdef cimg_use_lapack
        int INFO = (int)use_LU, N = _width, LWORK = 4*N, *const IPIV = new int[N];
        Tfloat
          *const lapA = new Tfloat[N*N],
          *const WORK = new Tfloat[LWORK];
        cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l));
        cimg::getrf(N,lapA,IPIV,INFO);
        if (INFO)
          cimg::warn(_cimg_instance
                     "invert(): LAPACK function dgetrf_() returned error code %d.",
                     cimg_instance,
                     INFO);
        else {
          cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO);
          if (INFO)
            cimg::warn(_cimg_instance
                       "invert(): LAPACK function dgetri_() returned error code %d.",
                       cimg_instance,
                       INFO);
        }
        if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)(lapA[k*N + l]); else fill(0);
        delete[] IPIV; delete[] lapA; delete[] WORK;
#else
        if (use_LU) { // LU solver
          CImg<Tfloat> A(*this,false), indx;
          bool d;
          A._LU(indx,d);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Check the determinant or rank of the matrix before inverting; reject/regularize singular inputs
  2. Use double-precision data (CImg<double>) so near-singular matrices still factor
  3. Add a small regularization term (e.g. A + eps*I) before inverting
  4. Handle the zero-filled result: check INFO behavior and fall back to a pseudo-inverse (e.g. solve via SVD/symmetric eigen)
  5. Avoid inverting at all — solve A*x=b with solve() instead of computing A^-1

Example fix

// before
CImg<float> inv = A.invert(true);
// after
if (std::fabs(A.determinant()) < 1e-10f) {
  // singular: regularize instead of inverting
  for (int i = 0; i < A.width(); ++i) A(i,i) += 1e-6f;
}
CImg<float> inv = A.invert(true);
Defensive patterns

Strategy: validation

Validate before calling

bool invertible(const CImg<float>& A) {
  if (A.width() != A.height() || A.width() == 0) return false;
  return std::fabs(A.determinant()) > 1e-10f;
}

Prevention

When it happens

Trigger: Calling invert(use_LU=true) on a square matrix that is singular or numerically rank-deficient; also possible if N exceeds LAPACK integer limits.

Common situations: Inverting covariance/geometry matrices built from degenerate input data (collinear points, duplicate rows); float32 precision issues making an ill-conditioned matrix effectively singular.

Related errors


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