Yalantis/uCrop · error · CImgArgumentException
draw_quiver(): Invalid dimensions of specified flow (%u,%u,%
Error message
draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).
What it means
draw_quiver() draws a vector flow field and requires the flow image to have exactly 2 values per location (spectrum==2: x and y components) and to be non-empty. When flow is empty (null data) or flow._spectrum!=2, the library cannot interpret the field as 2D vectors and throws CImgArgumentException with the flow's full dimensions.
Source
Thrown at ucrop/src/main/jni/CImg.h:53103
//! Draw a 2D vector field, using a field of colors.
/**
\param flow Image of 2D vectors used as input data.
\param color Image of spectrum()-D vectors corresponding to the color of each arrow.
\param opacity Opacity of the drawing.
\param sampling Length (in pixels) between each arrow.
\param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length).
\param is_arrow Tells if arrows must be drawn, instead of oriented segments.
\param pattern Used pattern to draw lines.
\note Clipping is supported.
**/
template<typename t1, typename t2>
CImg<T>& draw_quiver(const CImg<t1>& flow,
const CImg<t2>& color, const float opacity=1,
const unsigned int sampling=25, const float factor=-20,
const bool is_arrow=true, const unsigned int pattern=~0U) {
if (is_empty()) return *this;
if (!flow || flow._spectrum!=2)
throw CImgArgumentException(_cimg_instance
"draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).",
cimg_instance,
flow._width,flow._height,flow._depth,flow._spectrum,flow._data);
if (sampling<=0)
throw CImgArgumentException(_cimg_instance
"draw_quiver(): Invalid sampling value %g "
"(should be >0)",
cimg_instance,
sampling);
const bool colorfield = (color._width==flow._width && color._height==flow._height &&
color._depth==1 && color._spectrum==_spectrum);
if (is_overlapped(flow)) return draw_quiver(+flow,color,opacity,sampling,factor,is_arrow,pattern);
float vmax,fact;
if (factor<=0) {
float m, M = (float)flow.get_norm(2).max_min(m);
vmax = (float)std::max(cimg::abs(m),cimg::abs(M));
if (!vmax) vmax = 1;
fact = -factor;View on GitHub (pinned to f788b534b4)
Solutions
- Build the flow as a CImg with spectrum 2: CImg<t> flow(w,h,1,2); flow.set_at(xy_component...).
- If components are separate images, merge them: flow = flowX | flowY is wrong — use flow.append(flowY,'c') after reshaping each to (w,h,1,1), giving spectrum 2.
- Check flow.spectrum()==2 and !flow.is_empty() before calling draw_quiver.
- If you loaded flow from disk, re-save/verify with the two vector components in the spectrum dimension.
Example fix
// before CImg<float> flow = flowX.get_append(flowY,'x'); // depth stacking, spectrum stays 1 img.draw_quiver(flow,color); // after CImg<float> flow = flowX.get_append(flowY,'c'); // channels -> spectrum 2 img.draw_quiver(flow,color);
Defensive patterns
Strategy: validation
Validate before calling
if (flow.is_empty() || flow.spectrum()!=2)
throw std::invalid_argument("flow must be non-empty with 2 channels (dx,dy)");
img.draw_quiver(flow,color); Type guard
bool isFlowField(const CImg<float>& f){ return !f.is_empty() && f.spectrum()==2; } Try / catch
try { img.draw_quiver(flow,color,sampling); }
catch (CImgArgumentException& e) { log_error("draw_quiver flow invalid: %s", e.what()); } Prevention
- Store flow fields with spectrum=2 (dx,dy in channels), not as stacked volumes.
- Merge per-component flow images with append(...,'c').
- Validate channel count right after loading flow data from disk/network.
- Document the (w,h,1,2) layout in your flow-producing APIs.
When it happens
Trigger: Calling img.draw_quiver(flow,color) with a grayscale flow image (spectrum=1), an RGB flow (spectrum=3), a flow split into two separate images and passed concatenated along the wrong axis, or an unassigned/empty CImg as flow.
Common situations: Optical-flow results stored per-component in separate images and combined incorrectly; loading flow from file where channels were collapsed; constructing the flow CImg with spectrum defaulted to 1.
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
- _cimg_instance "MSE(): Instance and specified image (%u,%u,%
- draw_polygon(): Invalid specified point set (%u,%u,%u,%u).
- draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,
- draw_mandelbrot(): Instance and specified colormap (%u,%u,%u
- atXYZC(): Empty instance.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/1ad5c6a85ed0861f.
Report an issue: GitHub.