Yalantis/uCrop · error · CImgInstanceException

det(): Instance is not a square matrix.

Error message

det(): Instance is not a square matrix.

What it means

CImg::det() computes the determinant of the image viewed as a matrix, which requires a 2D square matrix: _width==_height and _depth==1 and _spectrum==1. The library throws CImgInstanceException when the instance is empty or its dimensions do not form a single-channel square matrix, because the determinant is undefined otherwise.

Source

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

    //! Compute the trace of the image, viewed as a matrix.
    /**
     **/
    double trace() const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "trace(): Empty instance.",
                                    cimg_instance);
      double res = 0;
      cimg_forX(*this,k) res+=(double)(*this)(k,k);
      return res;
    }

    //! Compute the determinant of the image, viewed as a matrix.
    /**
     **/
    double det() const {
      if (is_empty() || _width!=_height || _depth!=1 || _spectrum!=1)
        throw CImgInstanceException(_cimg_instance
                                    "det(): Instance is not a square matrix.",
                                    cimg_instance);

      switch (_width) {
      case 1 : return (double)((*this)(0,0));
      case 2 : return (double)((*this)(0,0))*(double)((*this)(1,1)) - (double)((*this)(0,1))*(double)((*this)(1,0));
      case 3 : {
        const double
          a = (double)_data[0], d = (double)_data[1], g = (double)_data[2],
          b = (double)_data[3], e = (double)_data[4], h = (double)_data[5],
          c = (double)_data[6], f = (double)_data[7], i = (double)_data[8];
        return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e;
      }
      default : {
        CImg<Tfloat> lu(*this,false);
        CImg<uintT> indx;
        bool d;
        lu._LU(indx,d);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Ensure the instance is square and single-channel before calling det(): img.assign(n,n,1,1).
  2. Extract one channel/plane first: img.get_channel(0).det() or img.get_slice(0).det().
  3. For rectangular matrices, use a decomposition-based approach (e.g. SVD via get_SVD()) instead of det().

Example fix

// before
CImg<float> img(3,4); // rectangular -> det() throws
double d = img.det();
// after
if (img.width()==img.height() && img.depth()==1 && img.spectrum()==1)
  double d = img.det();
Defensive patterns

Strategy: validation

Validate before calling

bool isSquareMatrix = !img.is_empty() && img.width()==img.height() && img.depth()==1 && img.spectrum()==1; if (!isSquareMatrix) img = img.get_channel(0).get_crop(0,0,img.height()-1,img.height()-1);

Type guard

bool isSquareMatrix(const CImg<T>& m){ return !m.is_empty() && m.width()==m.height() && m.depth()==1 && m.spectrum()==1; }

Try / catch

try { double d = img.det(); } catch (CImgInstanceException& e) { std::cerr << e.what() << '\n'; }

Prevention

When it happens

Trigger: Calling img.det() on a non-square width x height image, on an image with depth>1 (volumetric) or spectrum>1 (multi-channel color), or on an empty instance.

Common situations: Passing a color image (spectrum=3) instead of extracting a single channel; passing a volumetric image; passing an N x M rectangular matrix; forgetting that CImg treats an image as width x height x depth x spectrum, not rows x columns.

Related errors


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