Yalantis/uCrop · warning

save_pfm(): image instance is multispectral, only the three…

Error message

save_pfm(): image instance is multispectral, only the three first channels will be saved in file '%s'.

What it means

save_pfm() stores single-channel (gray) or RGB float data; CImg warns when _spectrum>3 because extra spectral channels beyond the first three cannot be represented in PFM and are silently dropped. Emitted via cimg::warn(), non-fatal.

Solutions

  1. Keep only the channels that fit: img.get_channels(0,2) before saving
  2. Split channels and save each separately with get_channel(c)
  3. Use a format that supports arbitrary channel counts (TIFF via save_tiff, or save_cimg for raw dumps)
  4. If the alpha channel is unwanted, drop it explicitly: img.get_channels(0,2)

Example fix

// before
rgbaImage.save_pfm("out.pfm");      // alpha dropped silently
// after
rgbaImage.get_channels(0, 2).save_pfm("out.pfm");
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum() > 3) img = img.get_channels(0, 2);
img.save_pfm("out.pfm");

Type guard

bool has_at_most_3_channels(const cimg_library::CImg<T>& img) { return img.spectrum() <= 3; }

Try / catch

try { img.save_pfm("out.pfm"); } catch (CImgException& e) { /* handle */ }

Prevention

When it happens

Trigger: Calling save_pfm() on an image with more than 3 channels (_spectrum>3), e.g. RGBA images, hyperspectral data, or 4+ channel feature maps.

Common situations: Saving RGBA data where only RGB is expected (forgetting to drop the alpha channel); hyperspectral or multi-band scientific data written to a 3-channel-capable format.

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/75e9d35d7824c322. Report an issue: GitHub.

Appendix: source

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

    //! Save image as a PFM file \overloading.
    const CImg<T>& save_pfm(std::FILE *const file) const {
      get_mirror('y')._save_pfm(file,0);
      return *this;
    }

    const CImg<T>& _save_pfm(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_pfm(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");
      if (_spectrum>3)
        cimg::warn(_cimg_instance
                   "save_pfm(): image instance is multispectral, only the three first channels will be saved "
                   "in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      const T
        *ptr_r = data(0,0,0,0),
        *ptr_g = (_spectrum>=2)?data(0,0,0,1):0,
        *ptr_b = (_spectrum>=3)?data(0,0,0,2):0;
      const unsigned int buf_size = std::min(1024*1024U,_width*_height*(_spectrum==1?1:3));

      std::fprintf(nfile,"P%c\n%u %u\n1.0\n",
                   (_spectrum==1?'f':'F'),_width,_height);

      switch (_spectrum) {
      case 1 : { // Scalar image
        CImg<floatT> buf(buf_size);

View on GitHub (pinned to f788b534b4)