Yalantis/uCrop · error · CImgArgumentException
save_pnm(): Specified filename is (null).
Error message
save_pnm(): Specified filename is (null).
What it means
_save_pnm() requires at least one of an open FILE* or a filename string; when both are null it cannot know where to write, so it throws CImgArgumentException. This is a pure API-misuse guard at the top of the PNM/PPM/PGM save path.
Solutions
- Pass a valid non-null filename string to save_pnm()
- Open the file yourself and pass the FILE* to the FILE* overload
- Validate the path argument before calling save_pnm()
- Check that code deriving the filename (config, user input) never yields null
Example fix
// before
img.save_pnm((std::FILE*)NULL);
// after
img.save_pnm("output.pnm");
// or
std::FILE *f = std::fopen("output.pnm","wb");
if (f) img.save_pnm(f); Defensive patterns
Strategy: validation
Validate before calling
if (!file && (!filename || !*filename)) throw std::invalid_argument("save_pnm requires a filename or FILE*"); Type guard
bool hasDestination(std::FILE *f, const char *name) { return f != NULL || (name != NULL && name[0] != '\0'); } Try / catch
try { img.save_pnm(path.c_str()); } catch (CImgArgumentException &e) { /* handle missing destination */ } Prevention
- Never call FILE*-only overloads with a possibly-null stream
- Check fopen() results immediately
- Validate path strings before passing to CImg
When it happens
Trigger: Calling save_pnm((std::FILE*)0) or a wrapper that passes a null filename and no file handle, e.g. build_save_pnm-style code forwarding an unset path variable.
Common situations: Path variable left uninitialized or emptied by config parsing; calling the FILE*-only overload with a stream that failed to open and was null; passing 0 instead of a filename in templated code.
Related errors
- save_pfm(): Specified filename is (null).
- save_pnk(): Specified filename is (null).
- save_rgb(): Specified filename is (null).
- save_rgba(): Specified filename is (null).
- load_cimg(): Specified filename is (null).
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/d919ca2619faf91e.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:62275
//! Save image as a PNM file.
/**
\param filename Filename, as a C-string.
\param bytes_per_pixel Force the number of bytes per pixels for the saving.
**/
const CImg<T>& save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const {
return _save_pnm(0,filename,bytes_per_pixel);
}
//! Save image as a PNM file \overloading.
const CImg<T>& save_pnm(std::FILE *const file, const unsigned int bytes_per_pixel=0) const {
return _save_pnm(file,0,bytes_per_pixel);
}
const CImg<T>& _save_pnm(std::FILE *const file, const char *const filename,
const unsigned int bytes_per_pixel=0) const {
if (!file && !filename)
throw CImgArgumentException(_cimg_instance
"save_pnm(): Specified filename is (null).",
cimg_instance);
if (is_empty()) { cimg::fempty(file,filename); return *this; }
double stmin, stmax = (double)max_min(stmin);
if (_depth>1)
cimg::warn(_cimg_instance
"save_pnm(): 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_pnm(): Instance is multispectral, only the three first channels will be saved in file '%s'.",
cimg_instance,
filename?filename:"(FILE*)");
if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536)
cimg::warn(_cimg_instance
"save_pnm(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.",View on GitHub (pinned to f788b534b4)