{"record":{"id":"d2f0e36062dd9075","repo":"Yalantis/uCrop","slug":"draw-image-sprite-u-u-u-u-p-and-mask-u","errorCode":null,"errorMessage":"draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have incompatible dimensions.","messagePattern":"draw_image\\(\\): Sprite \\(%u,%u,%u,%u,%p\\) and mask \\(%u,%u,%u,%u,%p\\) have incompatible dimensions\\.","errorType":"validation","errorClass":"CImgArgumentException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":52751,"sourceCode":"       \\param x0 X-coordinate of the sprite position in the image instance.\n       \\param y0 Y-coordinate of the sprite position in the image instance.\n       \\param z0 Z-coordinate of the sprite position in the image instance.\n       \\param c0 C-coordinate of the sprite position in the image instance.\n       \\param mask_max_value Maximum pixel value of the mask image \\c mask.\n       \\param opacity Drawing opacity.\n       \\note\n       - Pixel values of \\c mask set the opacity of the corresponding pixels in \\c sprite.\n       - Dimensions along x,y and z of \\p sprite and \\p mask must be the same.\n    **/\n    template<typename ti, typename tm>\n    CImg<T>& draw_image(const int x0, const int y0, const int z0, const int c0,\n                        const CImg<ti>& sprite, const CImg<tm>& mask, const float opacity=1,\n                        const float mask_max_value=1) {\n      if (is_empty() || !sprite || !mask) return *this;\n      if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,mask,opacity,mask_max_value);\n      if (is_overlapped(mask)) return draw_image(x0,y0,z0,c0,sprite,+mask,opacity,mask_max_value);\n      if (mask._width!=sprite._width || mask._height!=sprite._height || mask._depth!=sprite._depth)\n        throw CImgArgumentException(_cimg_instance\n                                    \"draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have \"\n                                    \"incompatible dimensions.\",\n                                    cimg_instance,\n                                    sprite._width,sprite._height,sprite._depth,sprite._spectrum,sprite._data,\n                                    mask._width,mask._height,mask._depth,mask._spectrum,mask._data);\n\n      const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0;\n      const int\n        dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0,\n        sx0 = dx0 - x0,  sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0,\n        lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0),\n        ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0),\n        lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0),\n        lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0);\n      const ulongT msize = mask.size();\n\n      if (lx>0 && ly>0 && lz>0 && lc>0) {\n        for (int c = 0; c<lc; ++c)","sourceCodeStart":52733,"sourceCodeEnd":52769,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L52733-L52769","documentation":"draw_image() with a mask requires the mask to have exactly the same width, height and depth as the sprite, and throws CImgArgumentException with both images' full dimensions when they differ. The mask modulates per-pixel blending, so a one-to-one spatial correspondence between sprite and mask pixels is mandatory; spectrum (channels) may differ.","triggerScenarios":"Calling img.draw_image(x,y,z,c,sprite,mask) where mask.width/height/depth != sprite.width/height/depth — e.g. mask generated at a different resolution, mask resized independently, or a single-channel mask built with wrong geometry (transposed or cropped).","commonSituations":"Alpha masks produced by a segmentation or blur pipeline at another scale than the sprite; hardcoding mask dimensions that no longer match after sprite source changed; forgetting to call mask.resize(sprite.width(),sprite.height(),sprite.depth()).","solutions":["Resize the mask to the sprite geometry before drawing: mask.resize(sprite.width(),sprite.height(),sprite.depth(),-100,0,0).","Recreate the mask from the same source dimensions as the sprite.","Log/assert sprite.dimensions()==mask.dimensions() (compare width/height/depth only) before the draw call.","If the mask was meant to be a scalar constant, use the opacity parameter instead of a mask image."],"exampleFix":"// before\nCImg<float> mask = makeMask(); // may differ in size\nimg.draw_image(x,y,sprite,mask);\n// after\nCImg<float> mask = makeMask();\nmask.resize(sprite.width(),sprite.height(),sprite.depth(),-100,0);\nimg.draw_image(x,y,sprite,mask);","handlingStrategy":"validation","validationCode":"if (mask.width()!=sprite.width() || mask.height()!=sprite.height() || mask.depth()!=sprite.depth())\n    mask.resize(sprite.width(),sprite.height(),sprite.depth(),-100,0);\nimg.draw_image(x,y,z,c,sprite,mask,opacity);","typeGuard":"bool maskMatches(const CImg<float>& sprite, const CImg<float>& mask){\n  return !mask.is_empty() && mask.width()==sprite.width() &&\n         mask.height()==sprite.height() && mask.depth()==sprite.depth();\n}","tryCatchPattern":"try { img.draw_image(x,y,sprite,mask); }\ncatch (CImgArgumentException& e) { log_error(\"draw_image sprite/mask mismatch: %s\", e.what()); }","preventionTips":["Resize masks to sprite geometry immediately after generating them.","Keep sprite and mask production in the same pipeline stage so dimensions stay coupled.","Assert dimension equality in debug builds before draw calls.","Never hardcode mask sizes; derive from sprite.dimensions()."],"tags":["cimg","image-processing","shape-mismatch"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}