<?
/*
*------------------------------------------------------------
*                   BMP Image functions
*------------------------------------------------------------
*                      By JPEXS
*/




/*
*------------------------------------------------------------
*                    ImageBMP
*------------------------------------------------------------
*            - Creates new BMP file
*
*         Parameters:  $img - Target image
*                      $file - Target file to store
*                            - if not specified, bmp is returned
*
*           Returns: if $file specified - true if OK
                     if $file not specified - image data
*/
function imagebmp($img,$file="",$RLE=0)
{


$ColorCount=imagecolorstotal($img);

$Transparent=imagecolortransparent($img);
$IsTransparent=$Transparent!=-1;


if($IsTransparent) $ColorCount--;

if($ColorCount==0) {$ColorCount=0; $BitCount=24;};
if(($ColorCount>0)and($ColorCount<=2)) {$ColorCount=2; $BitCount=1;};
if(($ColorCount>2)and($ColorCount<=16)) { $ColorCount=16; $BitCount=4;};
if(($ColorCount>16)and($ColorCount<=256)) { $ColorCount=0; $BitCount=8;};


                $Width=imagesx($img);
                $Height=imagesy($img);

                $Zbytek=(4-($Width/(8/$BitCount))%4)%4;

                if($BitCount<24) $palsize=pow(2,$BitCount)*4;

                $size=(floor($Width/(8/$BitCount))+$Zbytek)*$Height+54;
                $size+=$palsize;
                $offset=54+$palsize;

                // Bitmap File Header
                $ret = 'BM';                        // header (2b)
                $ret .= int_to_dword($size);        // size of file (4b)
                $ret .= int_to_dword(0);        // reserved (4b)
                $ret .= int_to_dword($offset);        // byte location in the file which is first byte of IMAGE (4b)
                // Bitmap Info Header
                $ret .= int_to_dword(40);        // Size of BITMAPINFOHEADER (4b)
                $ret .= int_to_dword($Width);        // width of bitmap (4b)
                $ret .= int_to_dword($Height);        // height of bitmap (4b)
                $ret .= int_to_word(1);        // biPlanes = 1 (2b)
                $ret .= int_to_word($BitCount);        // biBitCount = {1 (mono) or 4 (16 clr ) or 8 (256 clr) or 24 (16 Mil)} (2b)
                $ret .= int_to_dword($RLE);        // RLE COMPRESSION (4b)
                $ret .= int_to_dword(0);        // width x height (4b)
                $ret .= int_to_dword(0);        // biXPelsPerMeter (4b)
                $ret .= int_to_dword(0);        // biYPelsPerMeter (4b)
                $ret .= int_to_dword(0);        // Number of palettes used (4b)
                $ret .= int_to_dword(0);        // Number of important colour (4b)
                // image data

                $CC=$ColorCount;
                $sl1=strlen($ret);
                if($CC==0) $CC=256;
                if($BitCount<24)
                   {
                    $ColorTotal=imagecolorstotal($img);
                     if($IsTransparent) $ColorTotal--;

                     for($p=0;$p<$ColorTotal;$p++)
                     {
                      $color=imagecolorsforindex($img,$p);
                       $ret.=inttobyte($color["blue"]);
                       $ret.=inttobyte($color["green"]);
                       $ret.=inttobyte($color["red"]);
                       $ret.=inttobyte(0); //RESERVED
                     };

                    $CT=$ColorTotal;
                  for($p=$ColorTotal;$p<$CC;$p++)
                       {
                      $ret.=inttobyte(0);
                      $ret.=inttobyte(0);
                      $ret.=inttobyte(0);
                      $ret.=inttobyte(0); //RESERVED
                     };
                   };


if($BitCount<=8)
{

 for($y=$Height-1;$y>=0;$y--)
 {
  $bWrite="";
  for($x=0;$x<$Width;$x++)
   {
   $color=imagecolorat($img,$x,$y);
   $bWrite.=decbinx($color,$BitCount);
   if(strlen($bWrite)==8)
    {
     $retd.=inttobyte(bindec($bWrite));
     $bWrite="";
    };
   };

  if((strlen($bWrite)<8)and(strlen($bWrite)!=0))
    {
     $sl=strlen($bWrite);
     for($t=0;$t<8-$sl;$t++)
      $sl.="0";
     $retd.=inttobyte(bindec($bWrite));
    };
 for($z=0;$z<$Zbytek;$z++)
   $retd.=inttobyte(0);
 };
};

if(($RLE==1)and($BitCount==8))
{
 for($t=0;$t<strlen($retd);$t+=4)
  {
   if($t!=0)
   if(($t)%$Width==0)
    $ret.=chr(0).chr(0);

   if(($t+5)%$Width==0)
   {
     $ret.=chr(0).chr(5).substr($retd,$t,5).chr(0);
     $t+=1;
   }
   if(($t+6)%$Width==0)
    {
     $ret.=chr(0).chr(6).substr($retd,$t,6);
     $t+=2;
    }
    else
    {
     $ret.=chr(0).chr(4).substr($retd,$t,4);
    };
  };
  $ret.=chr(0).chr(1);
}
else
{
$ret.=$retd;
};


                if($BitCount==24)
                {
                for($z=0;$z<$Zbytek;$z++)
                 $Dopl.=chr(0);

                for($y=$Height-1;$y>=0;$y--)
                 {
                 for($x=0;$x<$Width;$x++)
                        {
                           $color=imagecolorsforindex($img,ImageColorAt($img,$x,$y));
                           $ret.=chr($color["blue"]).chr($color["green"]).chr($color["red"]);
                        }
                 $ret.=$Dopl;
                 };

                 };

  if($file!="")
   {
    $r=($f=fopen($file,"w"));
    $r=$r and fwrite($f,$ret);
    $r=$r and fclose($f);
    return $r;
   }
  else
  {
   echo $ret;
  };
};


/*
*------------------------------------------------------------
*                    ImageCreateFromBmp
*------------------------------------------------------------
*            - Reads image from a BMP file
*
*         Parameters:  $file - Target file to load
*
*            Returns: Image ID
*/

function imagecreatefrombmp($file)
{
global  $CurrentBit, $echoMode;

$f=fopen($file,"r");
$Header=fread($f,2);

if($Header=="BM")
{
 $Size=freaddword($f);
 $Reserved1=freadword($f);
 $Reserved2=freadword($f);
 $FirstByteOfImage=freaddword($f);

 $SizeBITMAPINFOHEADER=freaddword($f);
 $Width=freaddword($f);
 $Height=freaddword($f);
 $biPlanes=freadword($f);
 $biBitCount=freadword($f);
 $RLECompression=freaddword($f);
 $WidthxHeight=freaddword($f);
 $biXPelsPerMeter=freaddword($f);
 $biYPelsPerMeter=freaddword($f);
 $NumberOfPalettesUsed=freaddword($f);
 $NumberOfImportantColors=freaddword($f);

if($biBitCount<24)
 {
  $img=imagecreate($Width,$Height);
  $Colors=pow(2,$biBitCount);
  for($p=0;$p<$Colors;$p++)
   {
    $B=freadbyte($f);
    $G=freadbyte($f);
    $R=freadbyte($f);
    $Reserved=freadbyte($f);
    $Palette[]=imagecolorallocate($img,$R,$G,$B);
   };




if($RLECompression==0)
{
   $Zbytek=(4-ceil(($Width/(8/$biBitCount)))%4)%4;

for($y=$Height-1;$y>=0;$y--)
    {
     $CurrentBit=0;
     for($x=0;$x<$Width;$x++)
      {
         $C=freadbits($f,$biBitCount);
       imagesetpixel($img,$x,$y,$Palette[$C]);
      };
    if($CurrentBit!=0) {freadbyte($f);};
    for($g=0;$g<$Zbytek;$g++)
     freadbyte($f);
     };

 };
};


if($RLECompression==1) //$BI_RLE8
{
$y=$Height;

$pocetb=0;

while(true)
{
$y--;
$prefix=freadbyte($f);
$suffix=freadbyte($f);
$pocetb+=2;

$echoit=false;

if($echoit)echo "Prefix: $prefix Suffix: $suffix<BR>";
if(($prefix==0)and($suffix==1)) break;
if(feof($f)) break;

while(!(($prefix==0)and($suffix==0)))
{
 if($prefix==0)
  {
   $pocet=$suffix;
   $Data.=fread($f,$pocet);
   $pocetb+=$pocet;
   if($pocetb%2==1) {freadbyte($f); $pocetb++;};
  };
 if($prefix>0)
  {
   $pocet=$prefix;
   for($r=0;$r<$pocet;$r++)
    $Data.=chr($suffix);
  };
 $prefix=freadbyte($f);
 $suffix=freadbyte($f);
 $pocetb+=2;
 if($echoit) echo "Prefix: $prefix Suffix: $suffix<BR>";
};

for($x=0;$x<strlen($Data);$x++)
 {
  imagesetpixel($img,$x,$y,$Palette[ord($Data[$x])]);
 };
$Data="";

};

};


if($RLECompression==2) //$BI_RLE4
{
$y=$Height;
$pocetb=0;

while(true)
{
$y--;
$prefix=freadbyte($f);
$suffix=freadbyte($f);
$pocetb+=2;

$echoit=false;

if($echoit)echo "Prefix: $prefix Suffix: $suffix<BR>";
if(($prefix==0)and($suffix==1)) break;
if(feof($f)) break;

while(!(($prefix==0)and($suffix==0)))
{
 if($prefix==0)
  {
   $pocet=$suffix;

   $CurrentBit=0;
   for($h=0;$h<$pocet;$h++)
    $Data.=chr(freadbits($f,4));
   if($CurrentBit!=0) freadbits($f,4);
   $pocetb+=ceil(($pocet/2));
   if($pocetb%2==1) {freadbyte($f); $pocetb++;};
  };
 if($prefix>0)
  {
   $pocet=$prefix;
   $i=0;
   for($r=0;$r<$pocet;$r++)
    {
    if($i%2==0)
     {
      $Data.=chr($suffix%16);
     }
     else
     {
      $Data.=chr(floor($suffix/16));
     };
    $i++;
    };
  };
 $prefix=freadbyte($f);
 $suffix=freadbyte($f);
 $pocetb+=2;
 if($echoit) echo "Prefix: $prefix Suffix: $suffix<BR>";
};

for($x=0;$x<strlen($Data);$x++)
 {
  imagesetpixel($img,$x,$y,$Palette[ord($Data[$x])]);
 };
$Data="";

};

};


 if($biBitCount==24)
{
 $img=imagecreatetruecolor($Width,$Height);
 $Zbytek=$Width%4;

   for($y=$Height-1;$y>=0;$y--)
    {
     for($x=0;$x<$Width;$x++)
      {
       $B=freadbyte($f);
       $G=freadbyte($f);
       $R=freadbyte($f);
       $color=imagecolorexact($img,$R,$G,$B);
       if($color==-1) $color=imagecolorallocate($img,$R,$G,$B);
       imagesetpixel($img,$x,$y,$color);
      }
    for($z=0;$z<$Zbytek;$z++)
     freadbyte($f);
   };
};
return $img;

};


fclose($f);


};





/*
* Helping functions:
*-------------------------
*
* freadbyte($file) - reads 1 byte from $file
* freadword($file) - reads 2 bytes (1 word) from $file
* freaddword($file) - reads 4 bytes (1 dword) from $file
* freadlngint($file) - same as freaddword($file)
* decbin8($d) - returns binary string of d zero filled to 8
* RetBits($byte,$start,$len) - returns bits $start->$start+$len from $byte
* freadbits($file,$count) - reads next $count bits from $file
* RGBToHex($R,$G,$B) - convert $R, $G, $B to hex
* int_to_dword($n) - returns 4 byte representation of $n
* int_to_word($n) - returns 2 byte representation of $n
*/

function freadbyte($f)
{
 return ord(fread($f,1));
};

function freadword($f)
{
 $b1=freadbyte($f);
 $b2=freadbyte($f);
 return $b2*256+$b1;
};


function freadlngint($f)
{
return freaddword($f);
};

function freaddword($f)
{
 $b1=freadword($f);
 $b2=freadword($f);
 return $b2*65536+$b1;
};



function RetBits($byte,$start,$len)
{
$bin=decbin8($byte);
$r=bindec(substr($bin,$start,$len));
return $r;

};



$CurrentBit=0;
function freadbits($f,$count)
{
 global $CurrentBit,$SMode;
 $Byte=freadbyte($f);
 $LastCBit=$CurrentBit;
 $CurrentBit+=$count;
 if($CurrentBit==8)
  {
   $CurrentBit=0;
  }
 else
  {
   fseek($f,ftell($f)-1);
  };
 return RetBits($Byte,$LastCBit,$count);
};



function RGBToHex($Red,$Green,$Blue)
  {
   $hRed=dechex($Red);if(strlen($hRed)==1) $hRed="0$hRed";
   $hGreen=dechex($Green);if(strlen($hGreen)==1) $hGreen="0$hGreen";
   $hBlue=dechex($Blue);if(strlen($hBlue)==1) $hBlue="0$hBlue";
   return($hRed.$hGreen.$hBlue);
  };

        function int_to_dword($n)
        {
                return chr($n & 255).chr(($n >> 8) & 255).chr(($n >> 16) & 255).chr(($n >> 24) & 255);
        }
        function int_to_word($n)
        {
                return chr($n & 255).chr(($n >> 8) & 255);
        }


function decbin8($d)
{
return decbinx($d,8);
};

function decbinx($d,$n)
{
$bin=decbin($d);
$sbin=strlen($bin);
for($j=0;$j<$n-$sbin;$j++)
 $bin="0$bin";
return $bin;
};

function inttobyte($n)
{
return chr($n);
};

?>