Yalantis/uCrop · warning
save_rgb(): image instance has not exactly 3 channels, for…
Error message
save_rgb(): image instance has not exactly 3 channels, for file '%s'.
What it means
save_rgb() writes raw 24-bit RGB bytes (no header); CImg warns when the image does not have exactly 3 channels because the raw dump will not match the expected interleaved RGB layout — data will be misinterpreted or channels dropped depending on count. Emitted via cimg::warn(), the save still proceeds.
Solutions
- Append/drop channels to reach exactly 3: grayscale -> img.get_resize(...,1,1,1,3) or repeat channel; RGBA -> img.get_channels(0,2)
- Use save_ppm() or save_png() which handle arbitrary channel counts with proper headers
- If writing single-channel data, use save_pgm()/save_pnk() instead
Example fix
// before
grayImage.save_rgb("out.rgb"); // not 3 channels
// after
CImg<unsigned char> rgb = grayImage.get_resize(-100,-100,-100,3);
rgb.save_rgb("out.rgb"); Defensive patterns
Strategy: validation
Validate before calling
if (img.spectrum() != 3) img = img.get_resize(-100, -100, -100, 3); // replicate or truncate to 3 channels
img.save_rgb("out.rgb"); Type guard
bool is_rgb(const cimg_library::CImg<T>& img) { return img.spectrum() == 3; } Try / catch
try { img.save_rgb("out.rgb"); } catch (CImgException& e) { /* handle */ } Prevention
- Assert spectrum()==3 before raw RGB dumps
- Promote grayscale to 3 channels explicitly
- Prefer headered formats (PNG/PPM) to avoid layout mismatches
When it happens
Trigger: Calling save_rgb() on a grayscale image (_spectrum==1), an RGBA image (_spectrum==4), or any other channel count != 3.
Common situations: Exporting frames for external tools that expect raw RGB; converting from a color format that kept alpha; loading grayscale images and writing them as if they were RGB.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- save_rgba(): image instance has not exactly 4 channels, for…
- HSItoRGB(): Instance is not a HSI image.
- HSLtoRGB(): Instance is not a HSL image.
- HSVtoRGB(): Instance is not a HSV image.
- load_rgb(): Specified filename is (null).
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/fe30ff38c2785c29.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:62574
\param filename Filename, as a C-string.
**/
const CImg<T>& save_rgb(const char *const filename) const {
return _save_rgb(0,filename);
}
//! Save image as a RGB file \overloading.
const CImg<T>& save_rgb(std::FILE *const file) const {
return _save_rgb(file,0);
}
const CImg<T>& _save_rgb(std::FILE *const file, const char *const filename) const {
if (!file && !filename)
throw CImgArgumentException(_cimg_instance
"save_rgb(): Specified filename is (null).",
cimg_instance);
if (is_empty()) { cimg::fempty(file,filename); return *this; }
if (_spectrum!=3)
cimg::warn(_cimg_instance
"save_rgb(): image instance has not exactly 3 channels, for file '%s'.",
cimg_instance,
filename?filename:"(FILE*)");
std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
const ulongT wh = (ulongT)_width*_height;
unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer;
const T
*ptr1 = data(0,0,0,0),
*ptr2 = _spectrum>1?data(0,0,0,1):0,
*ptr3 = _spectrum>2?data(0,0,0,2):0;
switch (_spectrum) {
case 1 : { // Scalar image
for (ulongT k = 0; k<wh; ++k) {
const unsigned char val = (unsigned char)*(ptr1++);
*(nbuffer++) = val;
*(nbuffer++) = val;
*(nbuffer++) = val;View on GitHub (pinned to f788b534b4)