Yalantis/uCrop · error · CImgArgumentException

"[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()':

Error message

"[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': Mask vector (%lu values) and specified sprite geometry (%u,%u,%u,%u) (%lu values) do not match."

What it means

When draw() is called with an opacity-mask vector, the mask must contain at least dx*dy*dz values (one per sprite spatial position). This error is thrown when the mask vector length (sizM) is smaller than the sprite's spatial geometry requires.

Source

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

        dx = dx==~0U?img._width:(unsigned int)_mp_arg(8);
        dy = dy==~0U?img._height:(unsigned int)_mp_arg(9);
        dz = dz==~0U?img._depth:(unsigned int)_mp_arg(10);
        dc = dc==~0U?img._spectrum:(unsigned int)_mp_arg(11);

        const ulongT sizS = mp.opcode[2];
        if (sizS<(ulongT)dx*dy*dz*dc)
          throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': "
                                      "Sprite vector (%lu values) and its specified geometry (%u,%u,%u,%u) "
                                      "(%lu values) do not match.",
                                      mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc);
        const CImg<doubleT> S(&_mp_arg(1) + 1,dx,dy,dz,dc,true);
        const float opacity = (float)_mp_arg(12);

        if (img._data) {
          if (mp.opcode[13]!=~0U) { // Opacity mask specified
            const ulongT sizM = mp.opcode[14];
            if (sizM<(ulongT)dx*dy*dz)
              throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': "
                                          "Mask vector (%lu values) and specified sprite geometry (%u,%u,%u,%u) "
                                          "(%lu values) do not match.",
                                          mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc);
            const CImg<doubleT> M(&_mp_arg(13) + 1,dx,dy,dz,(unsigned int)(sizM/(dx*dy*dz)),true);
            img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(15));
          } else img.draw_image(x,y,z,c,S,opacity);
        }
        return cimg::type<double>::nan();
      }

      static double mp_image_h(_cimg_math_parser& mp) {
        unsigned int ind = (unsigned int)mp.opcode[2];
        if (ind!=~0U) {
          if (!mp.imglist.width()) return cimg::type<double>::nan();
          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.imglist.width());
        }
        const CImg<T> &img = ind==~0U?mp.imgout:mp.imglist[ind];
        return (double)img.height();

View on GitHub (pinned to f788b534b4)

Solutions

  1. Regenerate the mask so it has at least dx*dy*dz values matching the sprite geometry.
  2. Shrink the sprite geometry (dx,dy,dz) to fit the available mask values.
  3. Remove the mask argument if uniform opacity is sufficient.
  4. Compute mask size from the same variables used for geometry to keep them in sync.

Example fix

// before: mask sized for 4x4 sprite but geometry is 8x8
 draw(#0,sprite,8,8,1,3,x,y,z,c,opacity,mask64)
// after: mask sized to 8x8
 draw(#0,sprite,8,8,1,3,x,y,z,c,opacity,mask256)
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the mask covers the sprite's spatial extent before draw()
function checkMask(sizM, dx, dy, dz) { if (sizM < dx * dy * dz) throw new Error('mask has ' + sizM + ' values, needs ' + dx * dy * dz); }

Type guard

function maskCoversSprite(sizM, dx, dy, dz) { return sizM >= dx * dy * dz; }

Try / catch

try { evalMath(drawExpr); } catch (e) { if (String(e).includes('Mask vector') && String(e).includes('do not match')) { regenerateMask(); retry(); } else throw e; }

Prevention

When it happens

Trigger: Calling draw() with a mask argument (opcode[13] set) whose vector size sizM < dx*dy*dz for the sprite geometry in use.

Common situations: Reusing a mask computed for a smaller sprite; geometry defaults changed because the target image was resized; mask and sprite generated in separate steps with inconsistent dimensions.

Understand the failure class

Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.

Related errors


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