Yalantis/uCrop · warning

save_rgba(): image instance has not exactly 4 channels, for…

Error message

save_rgba(): image instance has not exactly 4 channels, for file '%s'.

What it means

save_rgba() writes raw 32-bit RGBA bytes (no header); CImg warns when the image does not have exactly 4 channels because the raw dump layout will not match the expected interleaved RGBA byte stream. Emitted via cimg::warn(), non-fatal; the save proceeds with whatever channels exist.

Solutions

  1. Ensure exactly 4 channels before saving: append an opaque alpha channel (e.g. construct CImg with spectrum 4 and fill alpha=255, or use get_channels with appended channel)
  2. Drop to RGB and use save_rgb()/save_ppm() if no alpha is needed
  3. Use save_png() which handles both 3- and 4-channel images with a proper header

Example fix

// before
rgbImage.save_rgba("out.rgba");     // only 3 channels
// after
CImg<unsigned char> rgba(rgbImage.width(), rgbImage.height(), 1, 4, 0);
cimg_forXY(rgbImage,x,y) { rgba(x,y,0,0)=rgbImage(x,y,0,0); rgba(x,y,0,1)=rgbImage(x,y,0,1); rgba(x,y,0,2)=rgbImage(x,y,0,2); rgba(x,y,0,3)=255; }
rgba.save_rgba("out.rgba");
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum() != 4) { /* add opaque alpha or switch format */ }
img.save_rgba("out.rgba");

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling save_rgba() on an RGB image (_spectrum==3, no alpha), grayscale image (_spectrum==1), or any channel count != 4.

Common situations: Exporting images with alpha for compositors/game engines; forgetting that a loaded JPEG has 3 channels (no alpha); loading PNG without alpha and saving as RGBA.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

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

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

    const CImg<T>& _save_rgba(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_rgba(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_spectrum!=4)
        cimg::warn(_cimg_instance
                   "save_rgba(): image instance has not exactly 4 channels, for file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      const ulongT wh = (ulongT)_width*_height;
      unsigned char *const buffer = new unsigned char[4*wh], *nbuffer = buffer;
      const T
        *ptr1 = data(0,0,0,0),
        *ptr2 = _spectrum>1?data(0,0,0,1):0,
        *ptr3 = _spectrum>2?data(0,0,0,2):0,
        *ptr4 = _spectrum>3?data(0,0,0,3):0;
      switch (_spectrum) {
      case 1 : { // Scalar images
        for (ulongT k = 0; k<wh; ++k) {
          const unsigned char val = (unsigned char)*(ptr1++);
          *(nbuffer++) = val;
          *(nbuffer++) = val;

View on GitHub (pinned to f788b534b4)