Yalantis/uCrop · error · CImgArgumentException
draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).
Error message
draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).
What it means
This texture-mapped draw_triangle() overload requires the texture to be a 2D image whose spectrum (channels) is at least as large as the instance's _spectrum. When texture._depth>1 (a volumetric texture) or texture._spectrum<_spectrum (too few channels), the mapping is undefined, so the library throws CImgArgumentException including the texture's (w,h,d,s,ptr).
Source
Thrown at ucrop/src/main/jni/CImg.h:51079
\param ty1 Y-coordinate of the second vertex in the texture image.
\param tx2 X-coordinate of the third vertex in the texture image.
\param ty2 Y-coordinate of the third vertex in the texture image.
\param opacity Drawing opacity.
\param brightness Brightness factor of the drawing (in [0,2]).
**/
template<typename tc>
CImg<T>& draw_triangle(int x0, int y0,
int x1, int y1,
int x2, int y2,
const CImg<tc>& texture,
int tx0, int ty0,
int tx1, int ty1,
int tx2, int ty2,
const float opacity=1,
const float brightness=1) {
if (is_empty()) return *this;
if (texture._depth>1 || texture._spectrum<_spectrum)
throw CImgArgumentException(_cimg_instance
"draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
cimg_instance,
texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
if (is_overlapped(texture))
return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness);
if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1);
if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2);
if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2);
if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this;
const int w1 = width() - 1, h1 = height() - 1, cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1);
const longT
dx01 = (longT)x1 - x0, dx02 = (longT)x2 - x0, dx12 = (longT)x2 - x1,
dy01 = std::max((longT)1,(longT)y1 - y0),
dy02 = std::max((longT)1,(longT)y2 - y0),
dy12 = std::max((longT)1,(longT)y2 - y1),
hdy01 = dy01/2, hdy02 = dy02/2, hdy12 = dy12/2,View on GitHub (pinned to f788b534b4)
Solutions
- Convert the texture to match: texture.resize(-100,-100,1,img._spectrum) before drawing
- If the texture is 3D, select a slice: texture.get_slice(z) and pass that
- Use channel_append/resize to add missing channels to a grayscale texture
- Check texture._depth==1 && texture._spectrum>=img._spectrum before calling
Example fix
// before CImg<unsigned char> tex = atlas.get_slice(z); tex = gray; // spectrum 1 img.draw_triangle(x0,y0,x1,y1,x2,y2,tex,tx0,ty0,tx1,ty1,tx2,ty2); // img is RGB // after CImg<unsigned char> tex = atlas.get_slice(z); tex.resize(-100,-100,1,img._spectrum); // now 3 channels img.draw_triangle(x0,y0,x1,y1,x2,y2,tex,tx0,ty0,tx1,ty1,tx2,ty2);
Defensive patterns
Strategy: validation
Validate before calling
if (!texture.is_empty() && texture._depth==1 && texture._spectrum>=img._spectrum) { img.draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); } Type guard
template<typename T,typename U> bool validTexture(const CImg<T>& tex, const CImg<U>& img) { return tex._depth==1 && tex._spectrum>=img._spectrum && !tex.is_empty(); } Try / catch
try { img.draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); } catch (const CImgArgumentException& e) { /* convert texture and retry */ } Prevention
- Normalize all textures to the render target's channel count at load time
- Slice volumetric textures before use: get_slice(z)
- Keep textures in a fixed format (e.g. RGBA) throughout the pipeline
- Check is_overlapped(texture) awareness — the library auto-copies, but shape must still be valid
When it happens
Trigger: Calling draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,...) with a 3D (depth>1) texture, or a grayscale texture when drawing into an RGB(A) image, or an empty texture.
Common situations: Passing an RGB image instance but a single-channel texture; accidentally passing the whole texture atlas volume instead of a slice; texture image not converted (e.g. L vs RGB) after loading.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- distance_dijkstra(): image instance and metric map (%u,%u,%u
- draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).
- draw_spline(): Invalid specified texture (%u,%u,%u,%u,%p).
- draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%
- draw_triangle(): Invalid specified light texture (%u,%u,%u,%
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/e13d157d91a8f71e.
Report an issue: GitHub.