phpbitmapgd2monochrome

Php imagebmp for monochrome bitmap


How to implement imagebmp() function for monochrome BMP? I found many implementation for 24bit bitmap but nothing about 1bit bitmap.


Solution

  • This is a working implemenation. I used a bindec function, I can be optimized using shift operators, but I found very easy the string padding function.

    function imagebmp(&$img, $filename = false)
    {
        $wid = imagesx($img);
        $hei = imagesy($img);
        $wid_pad = str_pad('', (4-ceil($wid/8) % 4) %4, "\0");
    
        $size = 62 + ( ceil($wid/8) + strlen($wid_pad)) * $hei;
    
        //prepare & save header
        $header['identifier']       = 'BM';
        $header['file_size']        = dword($size);
        $header['reserved']         = dword(0);
        $header['bitmap_data']      = dword(62);
        $header['header_size']      = dword(40);
        $header['width']            = dword($wid);
        $header['height']           = dword($hei);
        $header['planes']           = word(1);
        $header['bits_per_pixel']   = word(1);
        $header['compression']      = dword(0);
        $header['data_size']        = dword(0);
        $header['h_resolution']     = dword(0);
        $header['v_resolution']     = dword(0);
        $header['colors']           = dword(0);
        $header['important_colors'] = dword(0);
        $header['white']    = chr(255).chr(255).chr(255).chr(0);
        $header['black']    = chr(0).chr(0).chr(0).chr(0);
    
        if ($filename)
        {
            $f = fopen($filename, "wb");
            foreach ($header AS $h)
            {
                fwrite($f, $h);
            }
    
            //save pixels
            $str="";
            for ($y=$hei-1; $y>=0; $y--)
            {
                $str="";
                for ($x=0; $x<$wid; $x++)
                {
                    $rgb = imagecolorat($img, $x, $y);
                    $r = ($rgb >> 16) & 0xFF;
                    $g = ($rgb >> 8) & 0xFF;
                    $b = $rgb & 0xFF;
                    $gs = (($r*0.299)+($g*0.587)+($b*0.114));
                    if($gs>150) $color=0;
                    else $color=1;
                    $str=$str.$color;
                    if($x==$wid-1){
                        $str=str_pad($str, 8, "0");
                    }               
                    if(strlen($str)==8){
                        fwrite($f, chr((int)bindec($str)));
                        $str="";
                    }
                }
                fwrite($f, $wid_pad);
            }
            fclose($f);
    
        }
        else
        {
            foreach ($header AS $h)
            {
                echo $h;
            }
    
            //save pixels
            for ($y=$hei-1; $y>=0; $y--)
            {
                for ($x=0; $x<$wid; $x++)
                {
                    $rgb = imagecolorat($img, $x, $y);
                    $r = ($rgb >> 16) & 0xFF;
                    $g = ($rgb >> 8) & 0xFF;
                    $b = $rgb & 0xFF;
                    $gs = (($r*0.299)+($g*0.587)+($b*0.114));
                    if($gs>150) $color=0;
                    else $color=1;
                    $str=$str.$color;
                    if($x==$wid-1){
                        $str=str_pad($str, 8, "0");
                    }
                    if(strlen($str)==8){
                        echo chr((int)bindec($str));
                        $str="";
                    }
                }
                echo $wid_pad;
            }
        }
    }
    
    
    function dword($n)
    {
        return pack("V", $n);
    }
    function word($n)
    {
        return pack("v", $n);
    }