Yalantis/uCrop · error · CImgArgumentException

save_analyze(): Specified filename is (null).

Error message

save_analyze(): Specified filename is (null).

What it means

save_analyze() validates its filename argument up front and throws CImgArgumentException when it receives a null C-string, formatting the message with the literal '(null)'. It is a precondition check inside the Analyze 7.5 writer, fired before any header is built or file opened.

Source

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

     else if (pixel_type()==cimg::type<int>::string())
       wtr.setup_write_int();
     else if (pixel_type()==cimg::type<double>::string())
       wtr.setup_write_double();
     else
       wtr.setup_write_float();
     minc::save_standard_volume(wtr, this->_data);
     return *this;
#endif
    }

    //! Save image as an ANALYZE7.5 or NIFTI file.
    /**
      \param filename Filename, as a C-string.
      \param voxel_size Pointer to 3 consecutive values that tell about the voxel sizes along the X,Y and Z dimensions.
    **/
    const CImg<T>& save_analyze(const char *const filename, const float *const voxel_size=0) const {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_analyze(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(0,filename); return *this; }

      std::FILE *file;
      CImg<charT> hname(1024), iname(1024);
      const char *const ext = cimg::split_filename(filename);
      short datatype = -1;
      if (!*ext) {
        cimg_snprintf(hname,hname._width,"%s.hdr",filename);
        cimg_snprintf(iname,iname._width,"%s.img",filename);
      }
      if (!cimg::strncasecmp(ext,"hdr",3)) {
        std::strcpy(hname,filename);
        std::strncpy(iname,filename,iname._width - 1);
        cimg_snprintf(iname._data + std::strlen(iname) - 3,4,"img");
      }
      if (!cimg::strncasecmp(ext,"img",3)) {

View on GitHub (pinned to f788b534b4)

Solutions

  1. Validate the filename is non-null and non-empty before calling save_analyze and report which setting/argument was missing.
  2. Correct the producer of the path string so a valid filename reaches the call.
  3. Write to an already-open std::FILE* if that is what the caller actually has, instead of a null path.
  4. Wrap the call in a helper that converts a null path into a meaningful exception naming the source of the path.

Example fix

// before
char *name = cfg_get("analyze_output"); // may be NULL
img.save_analyze(name);

// after
char *name = cfg_get("analyze_output");
assert(name && *name);
img.save_analyze(name);
Defensive patterns

Strategy: validation

Validate before calling

if (!filename || !*filename)
  throw std::invalid_argument("save_analyze: filename is null or empty");

Type guard

bool valid_path(const char* p) { return p != nullptr && *p != '\0'; }

Try / catch

try {
  img.save_analyze(path.c_str());
} catch (const CImgArgumentException& e) {
  std::fprintf(stderr, "Analyze save failed, no filename: %s\n", e.what());
}

Prevention

When it happens

Trigger: Calling CImg::save_analyze(NULL) or passing a null filename through the generic save() dispatch; typically from an uninitialized pointer or an API that returned null instead of a path string.

Common situations: Config or environment lookup for the output path returned NULL; a concatenation helper failed silently and returned null; caller intended to use the FILE* overload but passed a null path instead.

Related errors


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