PHPRO.ORG

The PHP GD library contains many wonderful tools for creating images and converting them. Sadly the ability to convert BMP images to JPG is not one of them. Here is a function that I find a little slow, but works well and has suffered several incarnations. If you have a better script, or a modification to for this one, just let us know.


<?php

/**
 *
 * @convert BMP to GD
 *
 * @param string $src
 *
 * @param string|bool $dest
 *
 * @return bool
 *
 */
function bmp2gd($src$dest false)
{
    
/*** try to open the file for reading ***/
    
if(!($src_f fopen($src"rb")))
    {
        return 
false;
    }

/*** try to open the destination file for writing ***/
if(!($dest_f fopen($dest"wb")))
    {
        return 
false;
    }

/*** grab the header ***/
$header unpack("vtype/Vsize/v2reserved/Voffset"fread$src_f14));

/*** grab the rest of the image ***/
$info unpack("Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vimportant",
fread($src_f40));

/*** extract the header and info into varibles ***/
extract($info);
extract($header);

/*** check for BMP signature ***/
if($type != 0x4D42)
{
    return 
false;
}

/*** set the pallete ***/
$palette_size $offset 54;
$ncolor $palette_size 4;
$gd_header "";

/*** true-color vs. palette ***/
$gd_header .= ($palette_size == 0) ? "\xFF\xFE" "\xFF\xFF";
$gd_header .= pack("n2"$width$height);
$gd_header .= ($palette_size == 0) ? "\x01" "\x00";
if(
$palette_size) {
$gd_header .= pack("n"$ncolor);
}
/*** we do not allow transparency ***/
$gd_header .= "\xFF\xFF\xFF\xFF";

/*** write the destination headers ***/
fwrite($dest_f$gd_header);

/*** if we have a valid palette ***/
if($palette_size)
{
    
/*** read the palette ***/
    
$palette fread($src_f$palette_size);
    
/*** begin the gd palette ***/
    
$gd_palette "";
    
$j 0;
    
/*** loop of the palette ***/
    
while($j $palette_size)
    {
        
$b $palette{$j++};
        
$g $palette{$j++};
        
$r $palette{$j++};
        
$a $palette{$j++};
        
/*** assemble the gd palette ***/
        
$gd_palette .= "$r$g$b$a";
    }
    
/*** finish the palette ***/
    
$gd_palette .= str_repeat("\x00\x00\x00\x00"256 $ncolor);
    
/*** write the gd palette ***/
    
fwrite($dest_f$gd_palette);
}

/*** scan line size and alignment ***/
$scan_line_size = (($bits $width) + 7) >> 3;
$scan_line_align = ($scan_line_size 0x03) ? - ($scan_line_size 0x03) : 0;

/*** this is where the work is done ***/
for($i 0$l $height 1$i $height$i++, $l--)
{
    
/*** create scan lines starting from bottom ***/
    
fseek($src_f$offset + (($scan_line_size $scan_line_align) * $l));
    
$scan_line fread($src_f$scan_line_size);
    if(
$bits == 24)
    {
        
$gd_scan_line "";
        
$j 0;
        while(
$j $scan_line_size)
        {
            
$b $scan_line{$j++};
            
$g $scan_line{$j++};
            
$r $scan_line{$j++};
            
$gd_scan_line .= "\x00$r$g$b";
        }
    }
    elseif(
$bits == 8)
    {
        
$gd_scan_line $scan_line;
    }
    elseif(
$bits == 4)
    {
        
$gd_scan_line "";
        
$j 0;
        while(
$j $scan_line_size)
        {
            
$byte ord($scan_line{$j++});
            
$p1 chr($byte >> 4);
            
$p2 chr($byte 0x0F);
            
$gd_scan_line .= "$p1$p2";
        }
        
$gd_scan_line substr($gd_scan_line0$width);
    }
    elseif(
$bits == 1)
    {
        
$gd_scan_line "";
        
$j 0;
        while(
$j $scan_line_size)
        {
            
$byte ord($scan_line{$j++});
            
$p1 chr((int) (($byte 0x80) != 0));
            
$p2 chr((int) (($byte 0x40) != 0));
            
$p3 chr((int) (($byte 0x20) != 0));
            
$p4 chr((int) (($byte 0x10) != 0));
            
$p5 chr((int) (($byte 0x08) != 0));
            
$p6 chr((int) (($byte 0x04) != 0));
            
$p7 chr((int) (($byte 0x02) != 0));
            
$p8 chr((int) (($byte 0x01) != 0));
            
$gd_scan_line .= "$p1$p2$p3$p4$p5$p6$p7$p8";
        }
    
/*** put the gd scan lines together ***/
    
$gd_scan_line substr($gd_scan_line0$width);
    }
    
/*** write the gd scan lines ***/
    
fwrite($dest_f$gd_scan_line);
}
/*** close the source file ***/
fclose($src_f);
/*** close the destination file ***/
fclose($dest_f);

return 
true;
}

/**
 *
 * @ceate a BMP image
 *
 * @param string $filename
 *
 * @return bin string on success
 *
 * @return bool false on failure
 *
 */
function ImageCreateFromBmp($filename)
{
    
/*** create a temp file ***/
    
$tmp_name tempnam("/tmp""GD");
    
/*** convert to gd ***/
    
if(bmp2gd($filename$tmp_name))
    {
        
/*** create new image ***/
        
$img imagecreatefromgd($tmp_name);
        
/*** remove temp file ***/
        
unlink($tmp_name);
        
/*** return the image ***/
        
return $img;
    }
    return 
false;
}

/*** example usage ***/

/*** read in the BMP image ***/
$img ImageCreateFromBmp("test.bmp");
/*** write the new jpeg image ***/
imagejpeg($img"test/test.jpg");

?>

<!-- display the image -->
<img src="test/test.jpg" alt="new jpg image" />