Yalantis/uCrop · warning

save_dlm(): Instance is multispectral, values along C will…

Error message

save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.

What it means

save_dlm() writes a plain 2D value table; multispectral images (_spectrum>1, e.g. RGB or vector-valued pixels) do not fit. The library warns that the C (channel/spectrum) axis will be unrolled into the file and proceeds, so channel structure is only implicitly encoded in the output rows.

Solutions

  1. Split channels first and save each one: img.get_channel(c).save_dlm(...).
  2. Use a format supporting multispectral data (save_cimg, save_pnm for RGB, save_tiff).
  3. Convert to grayscale (get_norm or channel 0) if a single-channel export is intended.
  4. If unrolled layout is acceptable, document/parse the row-major (x, then y, then c) ordering explicitly on the consumer side.

Example fix

// before
rgb.save_dlm("rgb.dlm");
// after
for (int c = 0; c < rgb.spectrum(); ++c)
  rgb.get_channel(c).save_dlm(cimg::format("rgb_c%d.dlm", c));
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum() > 1) splitAndSaveChannels(img, base);
else img.save_dlm(path);

Type guard

bool isSingleChannel(const CImg<T>& im) { return im.spectrum() == 1; }

Prevention

When it happens

Trigger: CImg::save_dlm() (or save() with a .dlm filename) on an image with _spectrum > 1, such as an RGB image loaded from PNG/JPEG or a multi-channel feature image.

Common situations: Exporting RGB images to DLM for spreadsheet/numeric tools; forgetting DLM is single-channel; save() dispatching on a .dlm extension on color images.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

    //! Save image as a DLM file \overloading.
    const CImg<T>& save_dlm(std::FILE *const file) const {
      return _save_dlm(file,0);
    }

    const CImg<T>& _save_dlm(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_dlm(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_dlm(): Instance is volumetric, values along Z will be unrolled in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");
      if (_spectrum>1)
        cimg::warn(_cimg_instance
                   "save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      std::FILE *const nfile = file?file:cimg::fopen(filename,"w");
      const T* ptrs = _data;
      cimg_forYZC(*this,y,z,c) {
        cimg_forX(*this,x) std::fprintf(nfile,"%.17g%s",(double)*(ptrs++),(x==width() - 1)?"":",");
        std::fputc('\n',nfile);
      }
      if (!file) cimg::fclose(nfile);
      return *this;
    }

    //! Save image as a BMP file.
    /**
      \param filename Filename, as a C-string.
    **/

View on GitHub (pinned to f788b534b4)