php / php/doc-en

Document imagebmp() bit depth

Open
#4,339 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Feature Status: Needs Triage
Dominant language
XML
Stars
596
Forks
890
Avg merge
1d 15h
Merged PRs (30d)
55

Description

Description

We have a business case where we need PHP to return a 1-bit depth BMP image to the client. This is because the client is outputting the image to a thermal receipt printer which can only handle 1-bit or 4-bit depth images. The imagebmp() function does not currently have a parameter to specify the color depth; it probably should. The documentation did not specify what the color depth of the generated image was by default.

Ideally, it would be nice to have a function with the following signature:

imagebmp(GdImage $image, resource|string|null $file = null, bool $compressed = true, int $colorDepth = 24): bool

We worked around this issue by writing a user-defined function:

// The PHP GD extension cannot output a 1-bit depth BMP with its built-in functions, so you have to DIY.
// See https://en.wikipedia.org/wiki/BMP_file_format
function output1BitBMP($gdImage) {
    $width = imagesx($gdImage);
    $height = imagesy($gdImage);

    // Create a 1-bit BMP header
    $fileHeaderSize = 14;
    $infoHeaderSize = 40;
    $paletteSize = 8; // 2 colors * 4 bytes per color
    $rowSize = ceil($width / 8);
    $rowSizePadded = ($rowSize + 3) & ~3; // Rows are padded to multiples of 4 bytes
    $imageSize = $rowSizePadded * $height;
    $fileSize = $fileHeaderSize + $infoHeaderSize + $paletteSize + $imageSize;

    // BMP file header
    $fileHeader = pack('vVvvV', 0x4D42, $fileSize, 0, 0, $fileHeaderSize + $infoHeaderSize + $paletteSize);

    // BMP info header
    $infoHeader = pack('V3v2V6', $infoHeaderSize, $width, $height, 1, 1, 0, $imageSize, 0, 0, 2, 0);

    // BMP color palette (black and white)
    $palette = pack('V2', 0x00000000, 0x00FFFFFF);

    // BMP pixel data
    $pixelData = '';
    for ($y = $height - 1; $y >= 0; $y--) {
        $row = '';
        for ($x = 0; $x < $width; $x += 8) {
            $byte = 0;
            for ($bit = 0; $bit < 8; $bit++) {
                if ($x + $bit < $width) {
                    $color = imagecolorat($gdImage, $x + $bit, $y);
                    $gray = (imagecolorsforindex($gdImage, $color)['red'] + imagecolorsforindex($gdImage, $color)['green'] + imagecolorsforindex($gdImage, $color)['blue']) / 3;
                    $byte |= ($gray < 128 ? 1 : 0) << (7 - $bit);
                }
            }
            $row .= chr($byte);
        }
        // Pad the row to a multiple of 4 bytes
        while (strlen($row) % 4 !== 0) {
            $row .= chr(0);
        }
        $pixelData .= $row;
    }

    // Output the BMP
    header('Content-Type: image/bmp');
    echo $fileHeader . $infoHeader . $palette . $pixelData;
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue concerns PHP's imagebmp() function and the GD extension; start by checking the imagebmp() documentation and its stated default color depth. Determine whether the task is documentation-only or requires the proposed colorDepth API, then document the actual behavior or clarify the implementation scope.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
documentation
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.