Yalantis/uCrop · error · CImgIOException

save_analyze(): Unsupported pixel type '%s' for file '%s'.

Error message

save_analyze(): Unsupported pixel type '%s' for file '%s'.

What it means

The Analyze 7.5 header format only stores a limited set of datatypes; save_analyze() maps pixel_type() strings to header datatype codes (8 for 32-bit ints/64-bit-as-int32, 16 for float32, 64 for float64). If after all comparisons datatype is still negative, meaning the image's element type has no Analyze representation, it throws CImgIOException. Note the writer also aliases some types (e.g. uint64/int64 both written as int32) so errors only occur for widths like unsigned char/short.

Source

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

      ((char*)&(header[38]))[0] = 114;
      ((short*)&(header[40]))[0] = 4;
      ((short*)&(header[40]))[1] = (short)_width;
      ((short*)&(header[40]))[2] = (short)_height;
      ((short*)&(header[40]))[3] = (short)_depth;
      ((short*)&(header[40]))[4] = (short)_spectrum;
      if (!cimg::strcasecmp(pixel_type(),"bool") ||
          !cimg::strcasecmp(pixel_type(),"uint8") ||
          !cimg::strcasecmp(pixel_type(),"int8")) datatype = 2;
      if (!cimg::strcasecmp(pixel_type(),"uint16") ||
          !cimg::strcasecmp(pixel_type(),"int16")) datatype = 4;
      if (!cimg::strcasecmp(pixel_type(),"uint32") ||
          !cimg::strcasecmp(pixel_type(),"int32")) datatype = 8;
      if (!cimg::strcasecmp(pixel_type(),"uint64") ||
          !cimg::strcasecmp(pixel_type(),"int64")) datatype = 8;
      if (!cimg::strcasecmp(pixel_type(),"float32")) datatype = 16;
      if (!cimg::strcasecmp(pixel_type(),"float64")) datatype = 64;
      if (datatype<0)
        throw CImgIOException(_cimg_instance
                              "save_analyze(): Unsupported pixel type '%s' for file '%s'.",
                              cimg_instance,
                              pixel_type(),filename);

      ((short*)&(header[70]))[0] = datatype;
      ((short*)&(header[72]))[0] = sizeof(T);
      ((float*)&(header[108]))[0] = (float)(*iname?0:header.width());
      ((float*)&(header[112]))[0] = 1;
      ((float*)&(header[76]))[0] = 0;
      if (voxel_size) {
        ((float*)&(header[76]))[1] = voxel_size[0];
        ((float*)&(header[76]))[2] = voxel_size[1];
        ((float*)&(header[76]))[3] = voxel_size[2];
      } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1;
      file = cimg::fopen(hname,"wb");
      cimg::fwrite(header._data,header.width(),file);
      if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); }
      cimg::fwrite(_data,size(),file);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Cast the image to a supported type first: CImg<float>(img).save_analyze(filename) or img.get_float32().save_analyze(...).
  2. If exact 8-bit storage is required, use save_analyze on a type-mapped copy or switch to a format that supports unsigned char natively (PNG, NIfTI).
  3. Check pixel_type() at runtime and refuse unsupported saves early with a clear app-level message.
  4. Update CImg if a newer version extends the Analyze datatype table.

Example fix

// before
CImg<unsigned char> labels(256,256,1,1,0);
labels.save_analyze("seg.hdr"); // throws

// after
CImg<float> labelf(labels);
labelf.save_analyze("seg.hdr");
Defensive patterns

Strategy: validation

Validate before calling

static const char* kAnalyzeTypes[] = {"uint32","int32","uint64","int64","float32","float64"};
bool ok = false;
for (const char* t : kAnalyzeTypes)
  if (!cimg::strcasecmp(img.pixel_type(), t)) { ok = true; break; }
if (!ok) throw std::runtime_error(std::string("Analyze unsupported for ") + img.pixel_type());

Type guard

template <typename T>
constexpr bool analyze_supported() {
  return sizeof(T) >= 4; // Analyze writer only maps >=32-bit types
}

Try / catch

try {
  img.save_analyze("seg.hdr");
} catch (const CImgIOException& e) {
  std::fprintf(stderr, "converting to float32 for Analyze: %s\n", e.what());
  CImg<float>(img).save_analyze("seg.hdr");
}

Prevention

When it happens

Trigger: Calling save_analyze() on a CImg<unsigned char>, CImg<unsigned short>, or other type with no datatype mapping; calling it via generic save("file.hdr") with an 8/16-bit image instance.

Common situations: Saving segmentation masks or label maps stored as uint8; code refactored from float volumes to byte volumes; library version where fewer pixel types were registered for Analyze output.

Related errors


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