Yalantis/uCrop · error · CImgIOException
load_png(): Invalid color coding type %u in file '%s'.
Error message
load_png(): Invalid color coding type %u in file '%s'.
What it means
CImg's load_png only handles PNG_COLOR_TYPE_RGB and PNG_COLOR_TYPE_RGB_ALPHA. Grayscale, palette/indexed, and grayscale+alpha images throw CImgIOException even though libpng read them fine — the loader's post-read check rejects those color types.
Source
Thrown at ucrop/src/main/jni/CImg.h:57487
png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0);
throw CImgIOException(_cimg_instance
"load_png(): Invalid bit depth %u in file '%s'.",
cimg_instance,
bit_depth,nfilename?nfilename:"(FILE*)");
}
const int byte_depth = bit_depth>>3;
// Allocate memory for image reading.
png_bytep *const imgData = new png_bytep[H];
for (unsigned int row = 0; row<H; ++row) imgData[row] = new png_byte[(size_t)byte_depth*4*W];
png_read_image(png_ptr,imgData);
png_read_end(png_ptr,end_info);
// Read pixel data.
if (color_type!=PNG_COLOR_TYPE_RGB && color_type!=PNG_COLOR_TYPE_RGB_ALPHA) {
if (!file) cimg::fclose(nfile);
png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0);
throw CImgIOException(_cimg_instance
"load_png(): Invalid color coding type %u in file '%s'.",
cimg_instance,
color_type,nfilename?nfilename:"(FILE*)");
}
const bool is_alpha = (color_type==PNG_COLOR_TYPE_RGBA);
try { assign(W,H,1,(is_gray?1:3) + (is_alpha?1:0)); }
catch (...) { if (!file) cimg::fclose(nfile); throw; }
T
*ptr_r = data(0,0,0,0),
*ptr_g = is_gray?0:data(0,0,0,1),
*ptr_b = is_gray?0:data(0,0,0,2),
*ptr_a = !is_alpha?0:data(0,0,0,is_gray?1:3);
switch (bit_depth) {
case 8 : {
cimg_forY(*this,y) {
const unsigned char *ptrs = (unsigned char*)imgData[y];
cimg_forX(*this,x) {
*(ptr_r++) = (T)*(ptrs++);View on GitHub (pinned to f788b534b4)
Solutions
- Re-export as RGB or RGBA PNG: magick input.png PNG24:output.png (or PNG32 for alpha).
- Patch the loader to add png_set_palette_to_rgb/png_set_gray_to_rgb conversions (this custom CImg.h copy rejects them after conversion).
- Use img.load(path) (format auto-detect) if it routes to a more permissive loader in this build.
- Confirm the color type with pngcheck -v before distributing assets to the pipeline.
Example fix
// shell: convert grayscale/indexed PNG to RGBA
// magick icon.png PNG32:icon_rgba.png
img.load_png("icon_rgba.png"); // color type 6 (RGBA), accepted Defensive patterns
Strategy: fallback
Validate before calling
// read IHDR color type (byte 25): 2=RGB, 6=RGBA are supported
bool supportedColorType(const char *p) {
unsigned char h[27] = {}; std::FILE *f = std::fopen(p,"rb");
if (!f) return false;
size_t n = std::fread(h,1,27,f); std::fclose(f);
return n==27 && (h[25]==2 || h[25]==6);
} Try / catch
try { img.load_png(path); }
catch (CImgIOException &e) {
img.load(path); // fallback loader may handle gray/palette
} Prevention
- Convert all pipeline inputs to RGB/RGBA PNGs at ingest
- Avoid pngquant/indexed-color exports for images destined for this loader
- Validate color type with pngcheck during asset build
When it happens
Trigger: Loading a grayscale (PNG_COLOR_TYPE_GRAY) PNG, a palette/indexed PNG-8 (icons, optimized assets), or a gray+alpha PNG via load_png().
Common situations: Black-and-white scans or screenshots saved as grayscale PNG; icons optimized to indexed color by pngquant; UI assets exported as 'PNG-8' from design tools.
Related errors
- load_png(): Invalid bit depth %u in file '%s'.
- load_png(): Invalid PNG file '%s'.
- load_pnm(): PNM type 'P%d' found, but type is not supported.
- load_webp(): Does not support animated WebP '%s'.
- cimg::SDL3_attr(): %s
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/512e03f8660f492d.
Report an issue: GitHub.