Yalantis/uCrop · warning

save_pnk(): Instance is multispectral, only the first…

Error message

save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.

What it means

save_pnk() writes a single-channel PNM (portable any-map) file; CImg warns when the instance has more than one spectral channel because only channel 0 is written and channels 1..n are silently discarded. It is emitted via cimg::warn() and does not stop the save.

Solutions

  1. Convert to a single channel first, e.g. img.get_channels(0,0) or RGB->luminance via img.get_norm().normalize(0,255)
  2. Call a multi-channel saver: save_ppm() or save_png() for RGB data
  3. If only channel 0 is wanted explicitly, pass get_channel(0) so intent is clear

Example fix

// before
rgbImage.save_pnk("out.pgm");       // only R channel written
// after
rgbImage.get_norm().normalize(0,255).save_pnk("out.pgm");
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum() > 1) img = img.get_norm().normalize(0,255); // or img.get_channels(0,0)
img.save_pnk("out.pgm");

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling save_pnk() (or save_pnm on a pnk-formatted path) on an image with _spectrum>1, e.g. an RGB or RGBA image loaded from PNG/JPEG, or a 3D volumetric image with multiple channels.

Common situations: Converting color images to grayscale-map files without converting channels first; pipelines that assume grayscale input but receive RGB frames (webcam or video frames); accidentally calling save_pnk instead of a color-capable saver like save_ppm or save_png.

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/574774b4072bb443. Report an issue: GitHub.

Appendix: source

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

      \param filename Filename, as a C-string.
    **/
    const CImg<T>& save_pnk(const char *const filename) const {
      return _save_pnk(0,filename);
    }

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

    const CImg<T>& _save_pnk(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_pnk(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_spectrum>1)
        cimg::warn(_cimg_instance
                   "save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      const ulongT buf_size = std::min((ulongT)1024*1024,(ulongT)_width*_height*_depth);
      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      const T *ptr = data(0,0,0,0);

      if (!cimg::type<T>::is_float() && sizeof(T)==1 && _depth<2) // Can be saved as regular PNM file
        _save_pnm(file,filename,0);
      else if (!cimg::type<T>::is_float() && sizeof(T)==1) { // Save as extended P5 file: Binary byte-valued 3D
        std::fprintf(nfile,"P5\n%u %u %u\n255\n",_width,_height,_depth);
        CImg<ucharT> buf((unsigned int)buf_size);
        for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) {
          const ulongT N = std::min((ulongT)to_write,buf_size);
          unsigned char *ptrd = buf._data;
          for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++);
          cimg::fwrite(buf._data,N,nfile);

View on GitHub (pinned to f788b534b4)