PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Writer\Exception
$bitmap isn't a 24bit true color bitmap.\n
Error message
$bitmap isn't a 24bit true color bitmap.\n
What it means
processBitmap() reads the BMP's planes/bitcount pair and requires bitcount == 24: only uncompressed 24-bit true-color bitmaps can be stored in the Xls IMDATA record. 1/4/8-bit palette bitmaps and 16/32-bit formats are rejected with this exception.
Source
Thrown at src/PhpSpreadsheet/Writer/Xls/Worksheet.php:2517
// Read and remove the bitmap width and height. Verify the sizes.
$width_and_height = unpack('V2', substr($data, 0, 8)) ?: [];
/** @var int */
$width = $width_and_height[1];
/** @var int */
$height = $width_and_height[2];
$data = substr($data, 8);
if ($width > 0xFFFF) {
throw new WriterException("$bitmap: largest image width supported is 65k.\n");
}
if ($height > 0xFFFF) {
throw new WriterException("$bitmap: largest image height supported is 65k.\n");
}
// Read and remove the bitmap planes and bpp data. Verify them.
$planes_and_bitcount = unpack('v2', substr($data, 0, 4));
$data = substr($data, 4);
if ($planes_and_bitcount === false || $planes_and_bitcount[2] != 24) { // Bitcount
throw new WriterException("$bitmap isn't a 24bit true color bitmap.\n");
}
if ($planes_and_bitcount[1] != 1) {
throw new WriterException("$bitmap: only 1 plane supported in bitmap image.\n");
}
// Read and remove the bitmap compression. Verify compression.
$compression = unpack('Vcomp', substr($data, 0, 4));
$data = substr($data, 4);
if ($compression === false || $compression['comp'] != 0) {
throw new WriterException("$bitmap: compression not supported in bitmap image.\n");
}
// Remove bitmap data: data size, hres, vres, colours, imp. colours.
$data = substr($data, 20);
// Add the BITMAPCOREHEADER data
$header = pack('Vvvvv', 0x000C, $width, $height, 0x01, 0x18);View on GitHub (pinned to 65b080eef4)
Solutions
- Re-encode the image as 24-bit BMP (GD: imagecreatetruecolor + imagebmp)
- Convert to PNG/JPEG and use the Drawing API instead
- Verify bit depth with getimagesize() before insertion
Example fix
// before
$worksheetWriter->insertBitmap(1, 1, 'palette8.bmp');
// after
$src = imagecreatefrombmp('palette8.bmp');
$true24 = imagecreatetruecolor(imagesx($src), imagesy($src));
imagecopy($true24, $src, 0, 0, 0, 0, imagesx($src), imagesy($src));
imagebmp($true24, 'true24.bmp');
$worksheetWriter->insertBitmap(1, 1, 'true24.bmp'); Defensive patterns
Strategy: validation
Validate before calling
$info = unpack('vplanes/vbits', (string) file_get_contents($path, false, null, 26, 4));
if ($info === false || $info['bits'] !== 24) {
// re-encode through GD as 24-bit true color
$src = imagecreatefrombmp($path);
$dst = imagecreatetruecolor(imagesx($src), imagesy($src));
imagecopy($dst, $src, 0, 0, 0, 0, imagesx($src), imagesy($src));
imagebmp($dst, $path);
}
$worksheetWriter->insertBitmap($row, $col, $path); Prevention
- Normalize every incoming BMP to 24-bit via imagecreatetruecolor() before insertBitmap()
- Reject 1/4/8-bit palette sources early with a clear message instead of failing at save
When it happens
Trigger: insertBitmap() with a common 8-bit palette BMP (saved by MS Paint defaults or older tools), a 1-bit monochrome scan, or a 32-bit BMP exported by image editors.
Common situations: Scanner output and legacy clip-art distributed as 8-bit BMPs; default save options of older Windows tooling.
Related errors
- Couldn't import $bitmap
- $bitmap doesn't contain enough data.\n
- $bitmap: compression not supported in bitmap image.\n
- $bitmap doesn't appear to be a valid bitmap image.\n
- $bitmap: largest image width supported is 65k.\n
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/bfce4842042ca0d0.
Report an issue: GitHub.