Yalantis/uCrop · warning

save_bmp(): Instance is volumetric, only the first slice…

Error message

save_bmp(): Instance is volumetric, only the first slice will be saved in file '%s'.

What it means

save_bmp() can only write a single 2D bitmap; BMP has no volume representation. When _depth>1 the library warns that only the first slice (z=0) will be written and proceeds, silently discarding the rest of the volume.

Solutions

  1. Save a specific slice: volume.get_slice(z).save_bmp("slice.bmp").
  2. Use a multi-slice capable format: save_tiff (pages), save_cimg, or save_analyze for volumes.
  3. Write one BMP per z via a loop if BMP is required for downstream tooling.
  4. Check depth before saving and fail fast if volume data would be dropped.

Example fix

// before
volume.save_bmp("out.bmp"); // only slice 0 written
// after
for (int z = 0; z < volume.depth(); ++z)
  volume.get_slice(z).save_bmp(cimg::format("out_z%04d.bmp", z));
Defensive patterns

Strategy: validation

Validate before calling

if (img.depth() > 1) throw std::logic_error("BMP stores one slice; save slices individually or use TIFF");
img.save_bmp(path);

Type guard

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

Prevention

When it happens

Trigger: CImg::save_bmp() or save("file.bmp") on a volumetric image (_depth>1), e.g. output of volume processing or a 3D crop.

Common situations: Saving 3D results with a .bmp extension; generic save() dispatch on filename; exporting the wrong variable (volume instead of one slice) from 3D code.

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

Appendix: source

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

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

    //! 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;

View on GitHub (pinned to f788b534b4)