Yalantis/uCrop · error · CImgInstanceException

invert(): Instance is not a matrix.

Error message

invert(): Instance is not a matrix.

What it means

The in-place CImg::invert() inverts the image viewed as a matrix; a matrix requires _depth==1 and _spectrum==1. It throws CImgInstanceException when the instance is volumetric (depth>1) or multi-channel (spectrum>1), since matrix inversion is defined only for 2D single-channel data.

Source

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

    }

    //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors \newinstance.
    template<typename t>
    CImg<_cimg_Tt> get_cross(const CImg<t>& img) const {
      return CImg<_cimg_Tt>(*this).cross(img);
    }

    //! Invert the instance image, viewed as a matrix.
    /**
       If the instance matrix is not square, the Moore-Penrose pseudo-inverse is computed instead.
       \param use_LU Choose the inverting algorithm. Can be:
       - \c true: LU solver (faster but sometimes less precise).
       - \c false: SVD solver (more precise but slower).
       \param lambda is used only in the Moore-Penrose pseudoinverse for estimating A^t.(A^t.A + lambda.Id)^-1.
    **/
    CImg<T>& invert(const bool use_LU=false, const float lambda=0) {
      if (_depth!=1 || _spectrum!=1)
        throw CImgInstanceException(_cimg_instance
                                    "invert(): Instance is not a matrix.",
                                    cimg_instance);
      if (lambda<0)
        throw CImgArgumentException(_cimg_instance
                                    "invert(): Specified lambda (%g) should be >=0.",
                                    cimg_instance);

      if (_width!=_height) return get_invert(use_LU,lambda).move_to(*this); // Non-square matrix: Pseudoinverse

      // Square matrix.
      const double dete = _width>3?-1.:det();
      if (dete!=0. && _width==2) {
        const double
          a = _data[0], c = _data[1],
          b = _data[2], d = _data[3];
        _data[0] = (T)(d/dete); _data[1] = (T)(-c/dete);
        _data[2] = (T)(-b/dete); _data[3] = (T)(a/dete);
      } else if (dete!=0. && _width==3) {

View on GitHub (pinned to f788b534b4)

Solutions

  1. Extract a single 2D plane first, e.g. img.get_slice(0) or img.get_channel(0), then invert().
  2. Loop over channels/planes and invert each separately.
  3. Ensure the pipeline that produced the image yields depth=1, spectrum=1.

Example fix

// before
CImg<float> rgb = img.get_resize(...,3); // spectrum=3
rgb.invert();
// after
CImg<float> m = img.get_channel(0); // single-channel 2D matrix
m.invert();
Defensive patterns

Strategy: validation

Validate before calling

if (img.depth()!=1 || img.spectrum()!=1) img = img.get_channel(0).get_slice(0); img.invert();

Type guard

bool is2DMatrix(const CImg<T>& m){ return m.depth()==1 && m.spectrum()==1; }

Try / catch

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

Prevention

When it happens

Trigger: Calling img.invert() on a color image (spectrum=3) or a 3D volume (depth>1), regardless of squareness.

Common situations: Loading an RGB image and trying to invert it as a matrix; calling invert() on a sequence of matrices stacked along depth or spectrum instead of one 2D matrix; passing an animated/image-sequence container.

Related errors


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