Yalantis/uCrop · warning

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

Error message

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

What it means

After a successful LU factorization, CImg::invert() calls LAPACK dgetri_() to compute the inverse; nonzero INFO means the inversion step failed (dgetri_ reports an invalid argument or an internal pivot problem). CImg then fills the matrix with zeros rather than throwing.

Source

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

        _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);
          cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16*16))
          cimg_forX(*this,j) {
            CImg<Tfloat> col(1,_width,1,1,0);
            col(j) = 1;
            col._solve(A,indx);
            cimg_forX(*this,i) (*this)(j,i) = (T)col(i);
          }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Verify the matrix is square and reasonably sized before calling invert()
  2. Use a consistent, complete LAPACK build in the NDK project (check that dgetrf_/dgetri_ come from the same library)
  3. Check the zero-filled result and fall back to an alternative inversion (e.g. solve-based or eigen-based)
  4. Reduce matrix dimensions or use block-wise inversion for huge matrices

Example fix

// before
CImg<float> inv = A.invert(true);
// after
if (A.width() != A.height() || A.width() == 0) throw std::runtime_error("invert needs a non-empty square matrix");
CImg<float> inv = A.invert(true);
Defensive patterns

Strategy: validation

Validate before calling

bool okForInvert(const CImg<float>& A) {
  return A.width() == A.height() && A.width() > 0 && A.width() < 100000;
}

Prevention

When it happens

Trigger: Calling invert(use_LU=true) when dgetri_ receives bad parameters — typically caused by an inconsistent matrix size, a corrupted IPIV pivot array, or insufficient WORK space on unusual builds.

Common situations: Very large matrices exceeding LAPACK integer ranges; custom/incomplete LAPACK builds in the JNI/NDK environment with mismatched dgetri_ signatures.

Related errors


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