Yalantis/uCrop · warning

save_bmp(): Instance is multispectral, only the three first…

Error message

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

What it means

BMP supports at most 4 channels and CImg's save_bmp() writes RGB(A) at most 3 used channels; images with _spectrum>3 (e.g. CMYK, RGBA+extra, spectral data) trigger this warning and only the first three channels are written. Extra channels are silently dropped.

Solutions

  1. Save only the channels you need explicitly: img.get_channel(c) per channel, or get_channels(0,2) for RGB.
  2. Use a format that preserves all channels: save_cimg, save_tiff, save_pfm, or save_pnm (for 3/4-channel).
  3. Reduce the image to RGB/grayscale deliberately before export so the output matches intent.
  4. Verify spectrum<=3 when a viewable image is the goal; otherwise pick a data format.

Example fix

// before
rgba_plus.save_bmp("out.bmp"); // channels 3.. dropped
// after
if (rgba_plus.spectrum() > 3) rgba_plus.get_channels(0, 2).save_bmp("out.bmp");
else rgba_plus.save_bmp("out.bmp");
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum() > 3) img = img.get_channels(0, 2);
img.save_bmp(path);

Type guard

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

Prevention

When it happens

Trigger: CImg::save_bmp() or save("file.bmp") on an image with _spectrum > 3, e.g. 4+ channel images produced by feature extraction, CMYK data, or spectral stacks.

Common situations: Saving multispectral/feature images to BMP; processing pipelines that keep N channels then export to a viewer format; confusion between RGBA (which is fine at spectrum 4 for other formats but still truncated to RGB here).

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

Appendix: source

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

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

    const CImg<T>& _save_bmp(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_bmp(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_bmp(): 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_bmp(): 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");
      CImg<ucharT> header(54,1,1,1,0);
      unsigned char align_buf[4] = {};
      const unsigned int
        align = (4 - (3*_width)%4)%4,
        buf_size = (3*_width + align)*height(),
        file_size = 54 + buf_size;
      header[0] = 'B'; header[1] = 'M';
      header[0x02] = file_size&0xFF;
      header[0x03] = (file_size>>8)&0xFF;
      header[0x04] = (file_size>>16)&0xFF;
      header[0x05] = (file_size>>24)&0xFF;
      header[0x0A] = 0x36;
      header[0x0E] = 0x28;

View on GitHub (pinned to f788b534b4)