Файл: ather_lib/graph/bmp_images.php
Строк: 299
<?
/**
* @package com.jpexs.image.bmp
*
* JPEXS BMP Image functions
* @version 1.1
* @author JPEXS
* @copyright (c) JPEXS 2004-2009
*
* Webpage: http://www.jpexs.com
* Email: jpexs@jpexs.com
*
* If you like my script, you can donate... visit my webpages or email me for more info.
*
* Version changes:
* v1.1 - redesigned sourcecode, phpdoc included, all internal functions and global variables have prefix "jpexs_"
*
* TODO list:
* - better error handling
* - class encapsulation
* License:
* - you can freely use it
* - you can freely distribute sourcecode
* - you can freely modify it as long as you leave my copyright/author info in source code
* - if you developing closesource application, you should add my name at least to "about" page of your web application
* - if you create an amazing modification, please contact me... I can publish link to your webpage if you're interested...
* - if you want to use my script in commercial application for earning money, you should make a donation to me first
*/
/**
* Creates new BMP file from image resource
* @param resource $img Image resource to convert
* @param string $file File to save image to. If ommited or "", file is written to standard output
* @param boolean $useRLE When true, file will be saved with RLE compression (EXPERIMENTAL)
* @return boolean True when successfully writen to specified file
*/
function imagebmp($img,$file="",$useRLE=false)
{
$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 .= jpexs_int_to_dword($size); // size of file (4b)
$ret .= jpexs_int_to_dword(0); // reserved (4b)
$ret .= jpexs_int_to_dword($offset); // byte location in the file which is first byte of IMAGE (4b)
// Bitmap Info Header
$ret .= jpexs_int_to_dword(40); // Size of BITMAPINFOHEADER (4b)
$ret .= jpexs_int_to_dword($Width); // width of bitmap (4b)
$ret .= jpexs_int_to_dword($Height); // height of bitmap (4b)
$ret .= jpexs_int_to_word(1); // biPlanes = 1 (2b)
$ret .= jpexs_int_to_word($BitCount); // biBitCount = {1 (mono) or 4 (16 clr ) or 8 (256 clr) or 24 (16 Mil)} (2b)
$ret .= jpexs_int_to_dword($useRLE); // RLE COMPRESSION (4b)
$ret .= jpexs_int_to_dword(0); // width x height (4b)
$ret .= jpexs_int_to_dword(0); // biXPelsPerMeter (4b)
$ret .= jpexs_int_to_dword(0); // biYPelsPerMeter (4b)
$ret .= jpexs_int_to_dword(0); // Number of palettes used (4b)
$ret .= jpexs_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.=jpexs_inttobyte($color["blue"]);
$ret.=jpexs_inttobyte($color["green"]);
$ret.=jpexs_inttobyte($color["red"]);
$ret.=jpexs_inttobyte(0); //RESERVED
};
$CT=$ColorTotal;
for($p=$ColorTotal;$p<$CC;$p++)
{
$ret.=jpexs_inttobyte(0);
$ret.=jpexs_inttobyte(0);
$ret.=jpexs_inttobyte(0);
$ret.=jpexs_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.=jpexs_decbinx($color,$BitCount);
if(strlen($bWrite)==8)
{
$retd.=jpexs_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.=jpexs_inttobyte(bindec($bWrite));
};
for($z=0;$z<$Zbytek;$z++)
$retd.=jpexs_inttobyte(0);
};
};
if(($useRLE)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;
};
};
/**
* Reads image from a BMP file and converts it to image resource
* @global int $jpexs_CurrentBit Internal variable
* @param string $file File to read BMP image from
* @return resource Image resource or false on error
*
* Note:
* Reading RLE compressed bitmaps is EXPERIMENTAL
* Reading palette based bitmaps with less than 8bit palette is EXPERIMENTAL
*/
function imagecreatefrombmp($file)
{
global $jpexs_CurrentBit;
$f=fopen($file,"r");
$Header=fread($f,2);
if($Header=="BM")
{
$Size=jpexs_freaddword($f);
$Reserved1=jpexs_freadword($f);
$Reserved2=jpexs_freadword($f);
$FirstByteOfImage=jpexs_freaddword($f);
$SizeBITMAPINFOHEADER=jpexs_freaddword($f);
$Width=jpexs_freaddword($f);
$Height=jpexs_freaddword($f);
$biPlanes=jpexs_freadword($f);
$biBitCount=jpexs_freadword($f);
$RLECompression=jpexs_freaddword($f);
$WidthxHeight=jpexs_freaddword($f);
$biXPelsPerMeter=jpexs_freaddword($f);
$biYPelsPerMeter=jpexs_freaddword($f);
$NumberOfPalettesUsed=jpexs_freaddword($f);
$NumberOfImportantColors=jpexs_freaddword($f);
if($biBitCount<24)
{
$img=imagecreate($Width,$Height);
$Colors=pow(2,$biBitCount);
for($p=0;$p<$Colors;$p++)
{
$B=jpexs_freadbyte($f);
$G=jpexs_freadbyte($f);
$R=jpexs_freadbyte($f);
$Reserved=jpexs_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--)
{
$jpexs_CurrentBit=0;
for($x=0;$x<$Width;$x++)
{
$C=jpexs_freadbits($f,$biBitCount);
imagesetpixel($img,$x,$y,$Palette[$C]);
};
if($jpexs_CurrentBit!=0) {jpexs_freadbyte($f);};
for($g=0;$g<$Zbytek;$g++)
jpexs_freadbyte($f);
};
};
};
if($RLECompression==1) //$BI_RLE8
{
$y=$Height;
$pocetb=0;
while(true)
{
$y--;
$prefix=jpexs_freadbyte($f);
$suffix=jpexs_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) {jpexs_freadbyte($f); $pocetb++;};
};
if($prefix>0)
{
$pocet=$prefix;
for($r=0;$r<$pocet;$r++)
$Data.=chr($suffix);
};
$prefix=jpexs_freadbyte($f);
$suffix=jpexs_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(!feof($f))
echo freadbyte($f)."_".freadbyte($f)."<BR>";*/
while(true)
{
//break;
$y--;
$prefix=jpexs_freadbyte($f);
$suffix=jpexs_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;
$jpexs_CurrentBit=0;
for($h=0;$h<$pocet;$h++)
$Data.=chr(jpexs_freadbits($f,4));
if($jpexs_CurrentBit!=0) jpexs_freadbits($f,4);
$pocetb+=ceil(($pocet/2));
if($pocetb%2==1) {jpexs_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=jpexs_freadbyte($f);
$suffix=jpexs_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=jpexs_freadbyte($f);
$G=jpexs_freadbyte($f);
$R=jpexs_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++)
jpexs_freadbyte($f);
};
};
return $img;
}
else{
return false;
}
fclose($f);
};
/*
* Internal functions:
*-------------------------
*
* jpexs_freadbyte($file) - reads 1 byte from $file
* jpexs_freadword($file) - reads 2 bytes (1 word) from $file
* jpexs_freaddword($file) - reads 4 bytes (1 dword) from $file
* jpexs_freadlngint($file) - same as freaddword($file)
* jpexs_decbin8($d) - returns binary string of d zero filled to 8
* jpexs_retBits($byte,$start,$len) - returns bits $start->$start+$len from $byte
* jpexs_freadbits($file,$count) - reads next $count bits from $file
* jpexs_int_to_dword($n) - returns 4 byte representation of $n
* jpexs_int_to_word($n) - returns 2 byte representation of $n
*/
function jpexs_freadbyte($f)
{
return ord(fread($f,1));
};
function jpexs_freadword($f)
{
$b1=jpexs_freadbyte($f);
$b2=jpexs_freadbyte($f);
return $b2*256+$b1;
};
function jpexs_freadlngint($f)
{
return jpexs_freaddword($f);
};
function jpexs_freaddword($f)
{
$b1=jpexs_freadword($f);
$b2=jpexs_freadword($f);
return $b2*65536+$b1;
};
function jpexs_retBits($byte,$start,$len)
{
$bin=jpexs_decbin8($byte);
$r=bindec(substr($bin,$start,$len));
return $r;
};
$jpexs_CurrentBit=0;
function jpexs_freadbits($f,$count)
{
global $jpexs_CurrentBit,$SMode;
$Byte=jpexs_freadbyte($f);
$LastCBit=$jpexs_CurrentBit;
$jpexs_CurrentBit+=$count;
if($jpexs_CurrentBit==8)
{
$jpexs_CurrentBit=0;
}
else
{
fseek($f,ftell($f)-1);
};
return jpexs_retBits($Byte,$LastCBit,$count);
};
function jpexs_int_to_dword($n)
{
return chr($n & 255).chr(($n >> 8) & 255).chr(($n >> 16) & 255).chr(($n >> 24) & 255);
}
function jpexs_int_to_word($n)
{
return chr($n & 255).chr(($n >> 8) & 255);
}
function jpexs_decbin8($d)
{
return jpexs_decbinx($d,8);
};
function jpexs_decbinx($d,$n)
{
$bin=decbin($d);
$sbin=strlen($bin);
for($j=0;$j<$n-$sbin;$j++)
$bin="0$bin";
return $bin;
};
function jpexs_inttobyte($n)
{
return chr($n);
};
?>