Yalantis/uCrop · error · CImgIOException

save_cimg(): Unsupported data type

Error message

save_cimg(): Unsupported data type '%s' for file '%s'.

What it means

save_cimg writes a pixel-type tag in the CImg header and only knows how to serialize the C++ types it was instantiated/matched for (bool, char..double, int64, float32/64, etc., via the _cimg_save_cimg_case macros). If the list's pixel type T has no matching case (saved stays false), it throws CImgIOException naming the unrecognized type string.

Solutions

  1. Convert the list to a supported pixel type first, e.g. list.get_shared() copies: CImgList<float> out(list); then out.save_cimg(filename).
  2. Use one of the standard types (unsigned char, float, double, int, ...) as your image pixel type.
  3. If you must keep the custom type, write the data manually (serialize dimensions + raw buffer) instead of save_cimg.

Example fix

// before
CImgList<MyType> list; // unsupported pixel type
list.save_cimg("out.cimg");
// after
CImgList<float> out(list); // convert to supported type
out.save_cimg("out.cimg");
Defensive patterns

Strategy: type-guard

Validate before calling

// convert unsupported pixel types beforehand
CImgList<float> out(list);
out.save_cimg(path);

Type guard

template<typename T> struct cimg_saveable : std::integral_constant<bool, std::is_arithmetic<T>::value> {};

Try / catch

try { list.save_cimg(path); } catch (CImgIOException &e) { CImgList<float> out(list); out.save_cimg(path); }

Prevention

When it happens

Trigger: Using a CImgList of an exotic pixel type T that none of the save_cimg cases cover, then calling save_cimg.

Common situations: Custom typedefs or exotic integer widths as the pixel type; template code instantiating CImgList with a user type; porting code to a platform where the type string doesn't match any known case.

Related errors


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

Appendix: source

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

      if (!cimg::strncasecmp("little",str_endian,6)) endian = false;
      else if (!cimg::strncasecmp("big",str_endian,3)) endian = true;
      const unsigned int lmax = std::min(N,n0 + _width);
      _cimg_save_cimg_case("bool",0,0,cimg_uint8);
      _cimg_save_cimg_case("uint8","unsigned_char","uchar",cimg_uint8);
      _cimg_save_cimg_case("int8",0,0,cimg_int8);
      _cimg_save_cimg_case("char",0,0,char);
      _cimg_save_cimg_case("uint16","unsigned_short","ushort",cimg_uint16);
      _cimg_save_cimg_case("int16","short",0,cimg_int16);
      _cimg_save_cimg_case("uint32","unsigned_int","uint",cimg_uint32);
      _cimg_save_cimg_case("int32","int",0,cimg_int32);
      _cimg_save_cimg_case("uint64","unsigned_int64",0,cimg_uint64);
      _cimg_save_cimg_case("int64",0,0,cimg_int64);
      _cimg_save_cimg_case("float","float32",0,cimg_float32);
      _cimg_save_cimg_case("float64","double",0,cimg_float64);

      if (!saved) {
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimglist_instance
                              "save_cimg(): Unsupported data type '%s' for file '%s'.",
                              cimglist_instance,
                              filename?filename:"(FILE*)",str_pixeltype._data);
      }
      if (!file) cimg::fclose(nfile);
      return *this;
    }

    //! Insert the image instance into into an existing .cimg file, at specified coordinates.
    /**
      \param filename Filename to write data to.
      \param n0 Starting index of images to write.
      \param x0 Starting X-coordinates of image regions to write.
      \param y0 Starting Y-coordinates of image regions to write.
      \param z0 Starting Z-coordinates of image regions to write.
      \param c0 Starting C-coordinates of image regions to write.
    **/
    const CImgList<T>& save_cimg(const char *const filename,

View on GitHub (pinned to f788b534b4)