Yalantis/uCrop · error · CImgIOException
load_pdf_external(): Failed to load file '%s' with external
Error message
load_pdf_external(): Failed to load file '%s' with external command 'gs'.
What it means
On Unix, load_pdf_external() opens a pipe to 'gs -sDEVICE=ppmraw ...' with popen() and parses the PNM stream from the pipe. If parsing that stream (load_pnm) throws, this CImgIOException is thrown: ghostscript produced a stream that CImg could not decode as an image.
Source
Thrown at ucrop/src/main/jni/CImg.h:59923
CImg<T>& load_pdf_external(const char *const filename, const unsigned int resolution=400) {
if (!filename)
throw CImgArgumentException(_cimg_instance
"load_pdf_external(): Specified filename is (null).",
cimg_instance);
CImg<charT> command(1024), filename_tmp(256);
const CImg<charT> s_filename = CImg<charT>::string(filename)._system_strescape();
#if cimg_OS==1
std::FILE *file = 0;
cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o - -r%u \"%s\"",
resolution,s_filename.data());
file = popen(command,"r");
if (file) {
const unsigned int omode = cimg::exception_mode();
cimg::exception_mode(0);
try { load_pnm(file); } catch (...) {
pclose(file);
cimg::exception_mode(omode);
throw CImgIOException(_cimg_instance
"load_pdf_external(): Failed to load file '%s' with external command 'gs'.",
cimg_instance,
filename);
}
pclose(file);
return *this;
}
#endif
do {
cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm",
cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
} while (cimg::path_exists(filename_tmp));
cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o \"%s\" -r%u \"%s\"",
CImg<charT>::string(filename_tmp)._system_strescape().data(),resolution,s_filename.data());
cimg::system(command,"gs");
if (!cimg::path_exists(filename_tmp)) {
cimg::fclose(cimg::fopen(filename,"r"));
throw CImgIOException(_cimg_instanceView on GitHub (pinned to f788b534b4)
Solutions
- Run 'gs -q -dNOPAUSE -sDEVICE=ppmraw -o out.ppm -r400 file.pdf' by hand to see ghostscript's real error.
- Check the PDF opens in a viewer / with 'gs -sDEVICE=nullpage file.pdf'; repair or decrypt it first.
- Verify a real ghostscript is installed and on PATH ('gs --version').
- Lower the -r resolution argument if rendering fails at very high DPI due to memory.
- Render to a temp file yourself with gs, then load the PPM/PNG with CImg::load() — this also surfaces gs errors directly.
Example fix
// before
img.load_pdf_external("doc.pdf", 400);
// after
try { img.load_pdf_external("doc.pdf", 400); }
catch (CImgIOException&) {
if (cimg::system("gs -q -dNOPAUSE -sDEVICE=ppmraw -o doc.ppm -r150 doc.pdf"))
throw std::runtime_error("ghostscript failed on doc.pdf");
img.load("doc.ppm");
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!cimg::is_file(path)) throw std::invalid_argument("PDF missing");
if (cimg::system("gs --version","gs")!=0) throw std::runtime_error("ghostscript not installed"); Type guard
bool gsAvailable(){ return cimg::system("gs --version","gs")==0; } Try / catch
try { img.load_pdf_external(path, res); }
catch (CImgIOException& e) {
// gs stream undecodable: render to file yourself for a real exit status
if (cimg::system("gs -q -dNOPAUSE -sDEVICE=ppmraw -o page.ppm -r150 <file>")==0)
img.load("page.ppm");
else throw;
} Prevention
- Install ghostscript wherever PDF loading is used
- Reject encrypted/corrupt PDFs up front
- Lower resolution if renders fail on memory
- Prefer rendering to a temp file over pipes to capture gs errors
When it happens
Trigger: Calling load_pdf_external(filename, resolution) on Unix where gs ran but its stdout was not a valid PNM stream — gs printed an error to stdout, the PDF was encrypted/corrupt, gs failed mid-render (missing fonts), or the stream was empty.
Common situations: Ghostscript crashing on a malformed or password-protected PDF; 'gs' being a stub script that emits nothing; memory limits killing gs mid-render; gs version producing headers load_pnm cannot parse.
Related errors
- load_pdf_external(): Specified filename is (null).
- load_dcraw_external(): Failed to load file '%s' with externa
- load_pnm(): PNM header not found in file '%s'.
- load_pnm(): WIDTH and HEIGHT fields undefined in file '%s'.
- load_pnm(): Specified image dimensions in file '%s' exceed f
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/44bc8b272a0b1487.
Report an issue: GitHub.