Yalantis/uCrop · error · CImgArgumentException
distance_eikonal(): image instance and metric map…
Error message
distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have incompatible dimensions.
What it means
CImg::get_distance_eikonal() computes an eikonal (fast-marching) distance map to pixels equal to `value`, using `metric` as the local speed map. It requires metric to have identical width, height and depth as the image (checked via is_sameXYZ); otherwise it throws CImgArgumentException before running the fast-marching solver.
Solutions
- Check img.is_sameXYZ(metric) (or compare width/height/depth) before the call.
- Regenerate the metric from the same image instance passed as `this`, after all preprocessing.
- Resize/crop the metric to the image geometry, or pad the smaller one to match.
- Confirm depth matches: a 2D image needs a depth-1 metric.
Example fix
// before CImg<> metric = speed.get_crop(0,0,w/2,h/2); // cropped metric CImg<Tfloat> d = img.get_distance_eikonal(0, metric); // after CImg<> metric = speed.get_crop(0,0,img.width()-1,img.height()-1); CImg<Tfloat> d = img.get_distance_eikonal(0, metric);
Defensive patterns
Strategy: validation
Validate before calling
if (!img.is_sameXYZ(metric)) throw std::invalid_argument("metric must match image XYZ dims"); Type guard
bool eikonalMetricOk(const CImg<T>& img, const CImg<t>& metric) {
return img.is_sameXYZ(metric);
} Try / catch
try {
d = img.get_distance_eikonal(seedValue, metric);
} catch (const CImgArgumentException& e) {
metric.resize(img.width(), img.height(), img.depth(), -1, 0);
d = img.get_distance_eikonal(seedValue, metric);
} Prevention
- Build the speed/metric map at the exact resolution of the input image.
- Re-check dims after any multiscale/pyramid downsampling.
- Prefer letting resize/crop helpers keep image and metric in lockstep.
When it happens
Trigger: Calling get_distance_eikonal(value, metric) where the metric map's width, height, or depth differs from the calling image — e.g. a downsampled speed map, a metric for a neighboring tile, or a 3D metric used with a 2D image.
Common situations: Building the metric at a different resolution (pyramid/multiscale code), cropping one image but not the metric, video frames of varying sizes, or accidentally passing the metric of a previous iteration's image.
Related errors
- blur_anisotropic(): Invalid specified diffusion tensor…
- blur_bilateral(): Invalid size for specified guide image…
- blur_guided(): Invalid size for specified guide image…
- blur_patch(): Invalid size for specified guide image…
- distance_dijkstra(): image instance and metric map…
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/86afa7f4819b3e55.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:47156
return get_distance_dijkstra(value,metric,is_high_connectivity,return_path);
}
//! Compute distance map to one source point, according to a custom metric (use fast marching algorithm).
/**
\param value Reference value.
\param metric Field of distance potentials.
**/
template<typename t>
CImg<T>& distance_eikonal(const T& value, const CImg<t>& metric) {
return get_distance_eikonal(value,metric).move_to(*this);
}
//! Compute distance map to one source point, according to a custom metric (use fast marching algorithm).
template<typename t>
CImg<Tfloat> get_distance_eikonal(const T& value, const CImg<t>& metric) const {
if (is_empty()) return *this;
if (!is_sameXYZ(metric))
throw CImgArgumentException(_cimg_instance
"distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have "
"incompatible dimensions.",
cimg_instance,
metric._width,metric._height,metric._depth,metric._spectrum);
CImg<Tfloat> result(_width,_height,_depth,_spectrum,cimg::type<Tfloat>::max()), Q;
CImg<charT> state(_width,_height,_depth); // -1=far away, 0=narrow, 1=frozen
cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2) firstprivate(Q,state))
cimg_forC(*this,c) {
const CImg<T> img = get_shared_channel(c);
const CImg<t> met = metric.get_shared_channel(c%metric._spectrum);
CImg<Tfloat> res = result.get_shared_channel(c);
unsigned int sizeQ = 0;
state.fill(-1);
// Detect initial seeds.
Tfloat *ptr1 = res._data; char *ptr2 = state._data;
cimg_for(img,ptr0,T) { if (*ptr0==value) { *ptr1 = 0; *ptr2 = 1; } ++ptr1; ++ptr2; }View on GitHub (pinned to f788b534b4)