Location: PHPKode > scripts > PHPico > PHPico.php
<?php
namespace PHPico;
/**
*	All of classes, etc... are in this file.
*	@package PHPico
*/
/**
*	This function can be used to read $count of bytes as number (integer type probably) from string encoding in little-endian.
*	@param string $str string from which read number
*	@param int $offset from which offset read data
*	@param int $count how many bytes read?
*	@return int|float returns decoded little-endian number, type is depending on size of number (number < 2^31-1 === int)
*/
function readLE($str, $offset, $count) {
	$tmp = '';
	for($i = 0; $i < $count; $i++)
		//read all bytes in reverse order (in hex form, because you can put numbers one by one)
		$tmp .= bin2hex($str[$offset+$count-$i-1]);
	//return decimal representation of readed number
	return hexdec($tmp);
}
/**
*	This function can be used to read $count of bites as number (integer type probably) from string.
*	@param string $str string from which read bites
*	@param int $offset from which offset read bites
*	@param int $count how many bites read?
*	@return int|float returns number, type is depending on size of number (number < 2^31-1 === int)
*/
function readBites($str, $offset, $count) {
	$out = '';
	for($i = 0; $i < $count; $i++) {
		//byte number from zero
		$bn = floor(($offset + $i) / 8);
		//readed byte
		$b = readLE($str, $bn, 1);
		//number which is used to test bit
		$n = pow(2, 7 - (($offset + $i) - ($bn * 8)));
		//test if bit is set
		if(($b & $n) == $n)
			$out .= '1';
		else
			$out .= '0';
	}
	return bindec($out);
}
/**
*	This function can be used to write $count of bites as number (integer type probably) to string.
*	@param string $str pointer to string to which write bites
*	@param int $offset from which offset read data, after this variable follow bites
*	@param array $bites array of bites to write (1 or 0 values)
*/
function writeBites(&$str, $offset, $bites) {
	$bites = decbin($bites);
	$bites = str_split($bites);
	$count = count($bites);
	//echo($offset.":".($offset / 8)." ");
	for($i = 0; $i < $count; $i++) {
		$_offset = ceil(($offset + $i) / 8);
		if(isset($str[$_offset]))
			$byte = ord($str[$_offset]);
		else
			$byte = 0;
		if($bites[$i] == 0) {
			$byte = $byte & (255 ^ pow(2, 7 - (($offset + $i) % 8)));
		}
		else {
			$byte = $byte | pow(2, 7 - (($offset + $i) % 8));
		}
		$str[$_offset] = chr($byte);
	}
}
/**
*	This function turns integer type to string type with binary number with specified number of digits
*	@param int $count target count of digits
*	@return string returns string with binary number
*/
function d2b($count, $number) {
	$number = decbin($number);
	while(strlen($number) < $count)
		$number = '0'.$number;
	return $number;
}
/**
*	This function turns integer type to string type with hex number with specified number of digits
*	@param int $count target count of digits
*	@return string returns string with binary number
*/
function d2h($count, $number) {
	$number = dechex($number);
	while(strlen($number) < $count)
		$number = '0'.$number;
	return $number;
}
/**
*	This function convert binary number in string to string and put it to $file from $offset.
*	@param string &$file to which string write data?
*	@param int $offset from which offset write data?
*	@param string $binary_number data in format of binary number
*/
function writeBinary(&$file, $offset, $binary_number) {
	$length = strlen($binary_number) / 8;
	for($i = 0; $i <= $length; $i++) {
		$file[$offset + $i] = chr(bindec(substr($binary_number, $i * 8, 8)));
	}
}
/**
*	This function is second version of standart pack function. You can set offset from which is bytes packed.
*	@param string $file to which string pack data?
*	@param int $offset from which byte pack data (first byte is 0)?
*	@param string $format first parameter of standart php function pack, details here: http://php.net/manual/en/function.pack.php, after this variable follows variable count of values, same as in standart pack function
*/
function p2(&$file, $offset, $format) {
	$num = func_num_args();
	$tmp = '';
	for($i = 3; $i < $num; $i++)
		$tmp .= ', '.func_get_arg($i);
	eval("\$tmp = pack(\"$format\"$tmp);");
	for($i = 0; $i < strlen($tmp); $i++)
		$file[$offset + $i] = $tmp[$i];
}
/**
*	Value of FILE_NOT_FOUND error.
*/
define('FILE_NOT_FOUND', 1);
/**
*	Value of RESERVED_BYTE_INCORRECT error.
*/
define('RESERVED_BYTE_INCORRECT', 2);
/**
*	Value of INVALID_HEIGHT error.
*/
define('INVALID_HEIGHT', 4);
/**
*	Value of INVALID_WIDTH error.
*/
define('INVALID_WIDTH', 8);
/**
*	Value of INVALID_COLORCOUNT error.
*/
define('INVALID_COLORCOUNT', 16);
/**
*	Value of INVALID_COLOR_INTENSITY error.
*/
define('INVALID_COLOR_INTENSITY', 32);
/**
*	Value of MUST_BE_ZERO error.
*/
define('MUST_BE_ZERO', 64);
/**
*	Value of INVALID_INPUTOUTPUT_SIZE error.
*/
define('INVALID_INPUTOUTPUT_SIZE', 128);
/**
*	Value of INVALID_VARIABLE_TYPE error.
*/
define('INVALID_VARIABLE_TYPE', 256);
/**
*	Value of INDEX_DO_NOT_EXISTS error.
*/
define('INDEX_DO_NOT_EXISTS', 512);
/**
*	Value of TYPE_INCORRECT error.
*/
define('TYPE_INCORRECT', 1024); 
/**
*	Value of CANNOT_OPEN_FILE error.
*/
define('CANNOT_OPEN_FILE', 2048); 
/**
*	This class is a only public part for all works with ICO file format (hereinafter as ico). Create instance of this class for creating, reading and changing ico files.
*	@author Tomas W Volf <hide@address.com>
*	@version 1.0
*	@package PHPico
*	@copyright Copyright (c) Tomas Volf
*	@license http://www.fsf.org/licensing/licenses/lgpl.html LGPL
*	@see IconDir
*	@see Errors
*/
class Image {
	/**
	*	Used to store IconDir structure for this image.
	*	@var IconDir
	*/
	public $iconDir = null;
	/**
	*	Used to store IconImage structures for all images.
	*	@var array
	*/
	public $iconImages = array();
	/**
	*	Used to store errors.
	*	@var int
	*/
	public $e = 0;
	/**
	*	Content of file, can be null if no file loaded / saved.
	*	$var string
	*/
	public $file = null;
	/**
	*	Stop on errors?
	*	@var bool
	*/
	public $stopOnErrors = true;
	/**
	*	Create new instance of Image class and load file if $file not null.
	*	@param string $file if $str is false, then $file is url or path to icon file, else $file is content of icon file
	*	@param bool $str if this is true, then $file is content of file, else $file is url or path to file
	*	@param bool &$stopOnErrors stop on errors?
	*	@return Image returns new instance of Image class
	*/
	function Image($file = null, $str = false, $stopOnErrors = false) {
		$this->e = 0;
		$this->stopOnErrors = $stopOnErrors;
		try {
			if(!is_null($file)) {
				if(!$str) {
					if(($file = @file_get_contents($file)) === false) {
						if($this->stopOnErrors)
							throw new \Exception('File not found.', FILE_NOT_FOUND);
						else
							$this->e = $this->e | FILE_NOT_FOUND;
					}
				}
				$this->file = $file;
				$this->loadIconDir();
				foreach($this->iconDir->idEntries as $key=>$value) {
					$this->iconImages[$key] = new IconImage($file, $value, $this->stopOnErrors);
				}
			}
		}
		catch (Exception $e) {
			return false;
		}
		return true;
	}
	/**
	*	Use this function to create new blank icon with specified size and parameters.
	*	@param int $width width of new image
	*	@param int $height height of new image
	*	@param int $bitCount bit count of new image
	*/
	function createBlankImage($width = 32, $height = 32, $bitCount = 24) {
		if(!isset($this->iconDir))
			$this->iconDir = new iconDir(null, $this->stopOnErrors);
		$this->iconDir->idCount = 1;
		unset($this->iconImages);
		unset($this->iconDir->idEntries);
		$this->iconImages = array();
		$this->iconDir->idEntries = array();
		if($bitCount < 8)
			$colorCount = pow(2, $bitCount);
		else
			$colorCount = 0;
		$this->iconDir->idEntries[0] = new iconDirEntry(null, $this->stopOnErrors);
		$this->iconDir->idEntries[0]->setWidth($width);
		$this->iconDir->idEntries[0]->setHeight($height);
		$this->iconDir->idEntries[0]->setColorCount($colorCount);
		$this->iconDir->idEntries[0]->setReserved(0);
		$this->iconDir->idEntries[0]->setPlanes(1);
		$this->iconDir->idEntries[0]->setBitCount($bitCount);
		$this->iconDir->idEntries[0]->recalc();
		$this->iconDir->idEntries[0]->setImageOffset(22);
		$this->iconImages[0] = new IconImage(null, null, $this->stopOnErrors);
		$this->iconImages[0]->icHeader = new BitMapInfoHeader(null, $this->stopOnErrors);
		$this->iconImages[0]->icHeader->setSize(40);
		$this->iconImages[0]->icHeader->setWidth($width);
		$this->iconImages[0]->icHeader->setHeight($height * 2);
		$this->iconImages[0]->icHeader->setPlanes(1);
		$this->iconImages[0]->icHeader->setBitCount($bitCount);
		$this->iconImages[0]->icHeader->setCompression(0);
		$this->iconImages[0]->icHeader->setSizeImage(0);
		$this->iconImages[0]->icHeader->setXPelsPerMeter(0);
		$this->iconImages[0]->icHeader->setYPelsPerMeter(0);
		$this->iconImages[0]->icHeader->setClrUsed(0);
		$this->iconImages[0]->icHeader->setClrImportant(0);
		$this->check();
	}
	/**
	*	Use this function to create new icon.
	*	@param int $width width of new image
	*	@param int $height height of new image
	*	@param int $bitCount bit count of new image
	*/
	function addImage($width = 32, $height = 32, $bitCount = 24) {
		$index = count($this->iconImages);
		$this->iconDir->idCount = 1;
		if($bitCount < 8)
			$colorCount = pow(2, $bitCount);
		else
			$colorCount = 0;
		$this->iconDir->idEntries[$index] = new iconDirEntry(null, $this->stopOnErrors);
		$this->iconDir->idEntries[$index]->setWidth($width);
		$this->iconDir->idEntries[$index]->setHeight($height);
		$this->iconDir->idEntries[$index]->setColorCount($colorCount);
		$this->iconDir->idEntries[$index]->setReserved(0);
		$this->iconDir->idEntries[$index]->setPlanes(1);
		$this->iconDir->idEntries[$index]->setBitCount($bitCount);
		$this->iconDir->idEntries[$index]->recalc();
		$this->iconDir->idEntries[$index]->setImageOffset($this->iconDir->idEntries[$index]->getImageOffset() + $this->iconDir->idEntries[$index]->getBytesInRes() - 1);
		$this->iconImages[$index] = new IconImage(null, null, $this->stopOnErrors);
		$this->iconImages[$index]->icHeader = new BitMapInfoHeader(null, $this->stopOnErrors);
		$this->iconImages[$index]->icHeader->setSize(40);
		$this->iconImages[$index]->icHeader->setWidth($width);
		$this->iconImages[$index]->icHeader->setHeight($height * 2);
		$this->iconImages[$index]->icHeader->setPlanes(1);
		$this->iconImages[$index]->icHeader->setBitCount($bitCount);
		$this->iconImages[$index]->icHeader->setCompression(0);
		$this->iconImages[$index]->icHeader->setSizeImage(0);
		$this->iconImages[$index]->icHeader->setXPelsPerMeter(0);
		$this->iconImages[$index]->icHeader->setYPelsPerMeter(0);
		$this->iconImages[$index]->icHeader->setClrUsed(0);
		$this->iconImages[$index]->icHeader->setClrImportant(0);
		$this->check();
	}
	/**
	*	Use this function to remove icon with specified number.
	*	@param int $index number of icon (first has number 0)
	*/
	function removeImage($index) {
		$count = count($this->iconImages);
		if(isset($this->iconImages[$index])) {
			unset($this->iconImages[$index]);
			unset($this->iconDir->idEntries[$index]);
		}
		for($i = $index +1; $i < $count -1; $i++) {
			$this->iconImages[$i -1] = $this->iconImages[$i];
			$this->iconDir->idEntries[$i -1] = $this->iconDir->idEntries[$i];
		}
		unset($this->iconImages[$count]);
		unset($this->iconDir->idEntries[$count]);
	}
	/**
	*	Put pixel with specified colors and alpha chanel at specified coordinates.
	*	@param int $image number of image (first if 0)
	* @param int $x x-coordinate
	* @param int $y y-coordinate
	*	@param int $color index into icColors array
	*	@param int $alpha value of pixel in AND bitmap (0 or 1)
	*/
	function setPixel($image, $x, $y, $color, $alpha) {
		$height = $this->iconDir->idEntries[$image]->getHeight();
		$width = $this->iconDir->idEntries[$image]->getWidth();
		if(($x < $height) and ($y < $width) and ($x >= 0) and ($y >= 0)) {
			$this->iconImages[$image]->icXOR[$x+1][$y] = $color;
			$this->iconImages[$image]->icAND[$x+1][$y] = $alpha;
		}
	}
	/**
	*	Use this function to create new entry in icColors array.
	*	@param int $image number of image (first if 0)
	*	@param int $index index in icColors array
	*	@param int $red intensity of red color (0 - 255)
	*	@param int $green intensity of green color (0 - 255)
	*	@param int $blue intensity of blue color (0 - 255)
	*	@param int $reserved intensity of reserved color (0 - 255)
	*/
	function addColor($image, $index, $red, $green, $blue, $reserved) {
		$this->iconImages[$image]->icColors[$index] = new RGBQuad($red, $green, $blue, $reserved);
	}
	/**
	*	Use this function to get iconDir
	*	@return IconDir returns iconDir variable
	*/
	function getIconDir() {
		return $this->iconDir;
	}
	/**
	*	Use this function to get file
	*	@return IconDir returns file variable
	*/
	function getFile() {
		return $this->file;
	}
	/**
	*	You can use this function to check if all parameters of image is correct (size of icColor etc).
	*	@return bool returns true if there are not errors, else returns false
	*/
	function check() {
		$error = false;
		if(!isset($this->iconDir))
			$this->iconDir = new IconDir(null, $this->stopOnErrors);
		if(!isset($this->iconDir->idType))
			$this->iconDir->idType = 1;
		if($this->iconDir->idType != 1) {
			$error = true;
			$this->iconDir->idType = 1;
		}
		if(!isset($this->iconDir->idReserved))
			$this->iconDir->idReserved = 0;
		if($this->iconDir->idReserved != 0) {
			$error = true;
			$this->iconDir->idReserved = 0;
		}
		if(!isset($this->iconDir->idCount))
			$this->iconDir->idCount = 0;
		if($this->iconDir->idCount != count($this->iconImages)) {
			$error = true;
			$this->iconDir->idCount = count($this->iconImages);
		}
		while(count($this->iconImages) != count($this->iconDir->idEntries)) {
			$error = true;
			if(count($this->iconImages) < count($this->iconDir->idEntries))
					unset($this->iconDir->idEntries[count($this->iconDir->idEntries -1)]);
				else
					$this->iconDir->idEntries[] = new iconDirEntry(null, $this->stopOnErrors);
		}
		foreach($this->iconImages as $key=>$_unused) {
			if($this->iconImages[$key]->icHeader->getBitCount() != $this->iconDir->idEntries[$key]->getBitCount()) {
				$error = true;
					$this->iconDir->idEntries[$key]->setBitCount($this->iconImages[$key]->icHeader->getBitCount());
			}
			if($this->iconImages[$key]->icHeader->getWidth() != $this->iconDir->idEntries[$key]->getWidth()) {
				$error = true;
					$this->iconDir->idEntries[$key]->setWidth($this->iconImages[$key]->icHeader->getWidth());
			}
			if($this->iconImages[$key]->icHeader->getHeight() / 2 != $this->iconDir->idEntries[$key]->getHeight()) {
				$error = true;
					$this->iconDir->idEntries[$key]->setHeight($this->iconImages[$key]->icHeader->getHeight() / 2);
			}
			if($this->iconImages[$key]->icHeader->getPlanes() != $this->iconDir->idEntries[$key]->getPlanes()) {
				$error = true;
					$this->iconDir->idEntries[$key]->setPlanes($this->iconImages[$key]->icHeader->getPlanes());
			}
			if($this->iconDir->idEntries[$key]->getReserved() != 0)
				$this->iconDir->idEntries[$key]->setReserved(0);
			if($this->iconDir->idEntries[$key]->getPlanes() != 1)
				$this->iconDir->idEntries[$key]->setPlanes(1);
			$this->iconDir->idEntries[$key]->recalc();
			if($key == 0)
				if($this->iconDir->idEntries[$key]->getImageOffset() < 6 + $this->iconDir->idCount * 16)
					$this->iconDir->idEntries[$key]->setImageOffset(6 + $this->iconDir->idCount * 16);
				else ;
			else
				if($this->iconDir->idEntries[$key]->getImageOffset() < $this->iconDir->idEntries[$key-1]->getImageOffset() + $this->iconDir->idEntries[$key]->getBytesInRes())
					$this->iconDir->idEntries[$key]->setImageOffset($this->iconDir->idEntries[$key-1]->getImageOffset() + $this->iconDir->idEntries[$key]->getBytesInRes());
		}
		//biSizeImage may be 0, but it is recommended... so set it to 0
		foreach($this->iconImages as $key=>$_unused)
			if($this->iconImages[$key]->icHeader->getSizeImage() != 0) {
					$this->iconImages[$key]->icHeader->setSizeImage(0);
			}
		foreach($this->iconDir->idEntries as $key=>$iconDirEntry) {
			$bitCount = $iconDirEntry->getBitCount();
			if($bitCount < 8)
				$correctColorCount = pow(2, $bitCount);
			else
				$correctColorCount = 0;
			if($correctColorCount != $iconDirEntry->getColorCount()) {
				$error = true;
					$this->iconDir->idEntries[$key]->setColorCount($correctColorCount);
			}
			$_icHeader = 40;
			if($bitCount > 8)
				$_icColors = 0;
			else
				$_icColors = 4 * pow(2, $bitCount);
			$width = $iconDirEntry->getWidth();
			$height = $iconDirEntry->getHeight();
			$size = $width * $height;
			$add_whatX = 32 - ceil($width * $height) % 32;
			if($add_whatX == 32)
				$add_whatX = 0;
			$additionX = ceil($add_whatX * $height);
			$_icXOR = ceil(($additionX + $size * $bitCount) / 8);
			$add_whatA = 32 - $width % 32;
			if($add_whatA == 32)
				$add_whatA = 0;
			$additionA = ceil($add_whatA * $height);
			$_icAND = ceil(($additionA + $size) / 8);
			$bytesInRes = $_icHeader + $_icColors + $_icXOR + $_icAND;
			if($bytesInRes != $iconDirEntry->getBytesInRes()) {
				$error = true;
					$iconDirEntry->setBytesInRes($bytesInRes);
			}
		}
		foreach($this->iconImages as $key=>$iconImage) {
			//check count of color
			$bitCount = $iconImage->icHeader->getBitCount();
			if($bitCount <= 8)
				$correctColorCount = pow(2, $bitCount);
			else
				$correctColorCount = 0;
			if($bitCount <= 8) {
				while(count($this->iconImages[$key]->icColors) != $correctColorCount) {
					$error = true;
						if(count($this->iconImages[$key]->icColors) > $correctColorCount)
							unset($this->iconImages[$key]->icColors[count($this->iconImages[$key]->icColors) -1]);
						else
							$this->iconImages[$key]->icColors[] = new RGBQuad(0, 0, 0, 0, $this->stopOnErrors);
				}
			}
			//check XOR bitmap
			$_XORh = $iconImage->icHeader->getHeight() / 2 + 1;
			$_XORw = $iconImage->icHeader->getWidth();
			while(count($this->iconImages[$key]->icXOR) != $_XORh) {
				$error = true;
					if(count($this->iconImages[$key]->icXOR) > $_XORh)
						unset($this->iconImages[$key]->icXOR[count($this->iconImages[$key]->icXOR) -1]);
					else
						$this->iconImages[$key]->icXOR[] = array();
			}
			foreach($iconImage->icXOR as $key2=>$_unused) {
				if($key2 != 0) {
					if(!is_array($this->iconImages[$key]->icXOR[$key2]))
						$this->iconImages[$key]->icXOR[$key2] = array();
					while(count($this->iconImages[$key]->icXOR[$key2]) != $_XORw) {
						$error = true;
							if(count($this->iconImages[$key]->icXOR[$key2]) > $_XORw)
								unset($this->iconImages[$key]->icXOR[$key2][count($this->iconImages[$key]->icXOR[$key2]) -1]);
							else
								$this->iconImages[$key]->icXOR[$key2][] = 0;
					}
				}
			}
			//check AND bitmap
			$_ANDh = $iconImage->icHeader->getHeight() / 2 + 1;
			$_ANDw = $iconImage->icHeader->getWidth();
			while(count($this->iconImages[$key]->icAND) != $_ANDh) {
				$error = true;
					if(count($this->iconImages[$key]->icAND) > $_ANDh)
						unset($this->iconImages[$key]->icAND[count($iconImage->icAND) -1]);
					else
						$this->iconImages[$key]->icAND[] = array();
			}
			foreach($iconImage->icAND as $key2=>$row) {
				if($key2 != 0) {
					if(!is_array($this->iconImages[$key]->icAND[$key2]))
						$this->iconImages[$key]->icAND[$key2] = array();
					while(count($this->iconImages[$key]->icAND[$key2]) != $_ANDw) {
						$error = true;
							if(count($this->iconImages[$key]->icAND[$key2]) > $_ANDw)
								unset($this->iconImages[$key]->icAND[$key2][count($row) -1]);
							else
								$this->iconImages[$key]->icAND[$key2][] = 0;
					}
				}
			}
		}
		return $error;
	}
	/**
	* Use this funtion to load iconDir from file.
	*	@return bool returns true if iconDir was loaded, else returns false
	*/
	function loadIconDir() {
		try {
			$this->iconDir = new IconDir($this->file, $this->stopOnErrors);
			return true;
		}
		catch (Exception $e) {
			//rethrow exception
			throw $e;
		}
		return false;
	}
	/**
	* Use this funtion to reload from previously specified file.
	*	@return bool returns true if was loaded, else returns false
	*/
	function reload() {
		try {
			$this->iconDir = null;
			$this->iconImages = null;
			$this->loadIconDir();
			foreach($this->iconDir->idEntries as $key=>$value) {
				$this->iconImages[$key] = new IconImage($this->file, $value, $this->stopOnErrors);
			}
		}
		catch (Exception $e) {
			return false;
		}
		return true;
	}
	/**
	* Use this funtion to save changes to in-memory copy of file.
	*	@param string $mod mod of this function. S = only change $file variable, E = echo $file variable, F = save to file
	*	@param string $filename name of file to which same images if $mod is F
	*	@param bool $clear delete file before changing it?
	*/
	function save($mod = 'S', $filename = 'unnamed.ico', $clear = true) {
		$this->check();
		if($clear)
			$this->file = '';
		$this->iconDir->save($this->file);
		foreach($this->getIconDir()->getIconDirEntries() as $key=>$value)
			$this->iconImages[$key]->save($this->file, $this->getIconDir()->getIconDirEntry($key));
		
		{{{
			$tmp = '';
			for($i = 0; $i < 38; $i++)
			if(isset($this->file[$i]))
				$tmp .= $this->file[$i];
			else
				$tmp .= chr(0);
		file_put_contents('tmp', $tmp);
		}}}
		
		$tmp = '';
		$keys = array();
		foreach($this->file as $key=>$value)
			$keys[] = $key;
		$max = max($keys);
		for($i = 0; $i < $max; $i++)
			if(isset($this->file[$i]))
				$tmp .= $this->file[$i];
			else
				$tmp .= chr(0);
		$this->file = $tmp;
		switch($mod) {
			case 'S': {
				break;
			}
			case 'E': {
				echo($this->file);
				break;
			}
			case 'F': {
				try {
					$handle = fopen($filename, 'w+');
				}
				catch (Exception $e) {
					if($this->stopOnErrors)
						throw new \Exception('Cannot open file.', CANNOT_OPEN_FILE);
					else
						$this->e = $this->e | CANNOT_OPEN_FILE;
				}
  	    fwrite($handle, $this->file);
    		fclose($handle);
				break;
			}
		}
	}
	/**
	*	Use this function to turning "stop on errors" on and off.
	*	@param bool $on Do you want "stop on errors" on?
	*	@return bool returns true if setting was changed, else returns false
	*/
	function stopOnError($on = '') {
		try {
			$this->stopOnError = (bool) $on;
			return true;
		}
		catch (Exception $e) {
			//rethrow exception
			throw $e;
		}
		return false;
	}
	/*
	*	Use this function to export image to standart resource of gd type
	* $param int $id Index of exported image.
	*	@return resource returns resource of type "gd"
	*/
	/*function export($id = 0) {
		if(array_key_exists($id, $this->iconImages)) {
			//pointer to iconImage structure of exported image
			$iI = &$this->iconImages[$id];
			$export = imagecreatetruecolor($iI->icHeader->biWidth, $iI->icHeader->biHeight / 2);
			imagesavealpha($export, true);
			imagealphablending($export, false);
			$colors = array();
			$transparent = imagecolorallocatealpha($export, 255, 255, 255, 127);
			$transparent = imagecolorallocatealpha($export, 0, 0, 0, 0);
			foreach($iI->icColors as $key=>$color) {
				//$colors[$key] = imagecolorallocatealpha($export, $color->getR(), $color->getG(), $color->getB(), ceil($color->getRd() / 2));
				$colors[$key] = imagecolorallocatealpha($export, $color->getR(), $color->getG(), $color->getB(), 127);
			}
			$h = $iI->icHeader->biHeight / 2;
			$w = $iI->icHeader->biWidth -1;
			for($i = 1; $i <= $h; $i++)
				for($j = 0; $j <= $w; $j++) {
					if($iI->icAND[$i][$j] == 1)
						imagesetpixel($export, $j, $i-1, $transparent);
					else
						imagesetpixel($export, $j, $i-1, $colors[$iI->icXOR[$i][$j]]);
				}
			return $export;
		}
		else {
			if($this->stopOnErrors)
				throw new \Exception('Index do not exists in array iconImages.', INDEX_DO_NOT_EXISTS);
			else
				$this->e = $this->e | INDEX_DO_NOT_EXISTS;
		}
	}*/
}
/**
*	Microsoft ICONDIR structure. It is used to store type of file, count of images and images itself.
*	@author Tomas W Volf <hide@address.com>
*	@version 1.0
*	@copyright Copyright (c) Tomas Volf
*	@package PHPico
*	@license http://www.fsf.org/licensing/licenses/lgpl.html LGPL
*	@link http://msdn.microsoft.com/en-us/library/ms997538.aspx msdn.microsoft.com
*/
class IconDir {
	/**
	*	Used to store reserved word of ICONDIR structure.
	*	@var int
	*/
	public $idReserved = null;
	/**
	*	Used to store type of file (icon).
	*	@var int
	*/
	public $idType = null;
	/**
	*	Used to store count of images.
	*	@var int
	*/
	public $idCount = null;
	/**
	*	@var array Used to store idCount of IconDirEntry
	*/
	public $idEntries = array();
	/**
	*	Used to store errors.
	*	@var int
	*/
	public $e = 0;
	/**
	*	Contains valid types of image.
	* @var array
	*/
	public $validTypes = array(1, 2);
	/**
	*	Stop on errors?
	*	@var bool
	*/
	public $stopOnErrors = true;
	/**
	*	Load data from image file.
	*	@param string $file content of icon file
	*	@param bool &$stopOnErrors stop on errors?
	*	@return IconDir returns new instance of IconDir
	*/
	function IconDir($file, &$stopOnErrors) {
		$this->e = 0;
		$this->stopOnErrors = $stopOnErrors;
		if($file != null) {
			$this->idReserved = readLE($file, 0, 2);
			$this->idType = readLE($file, 2, 2);
			$this->idCount = readLE($file, 4, 2);
			//test reserved word (must be 0)
			if($this->idReserved != 0) {
				if($this->stopOnErrors)
					throw new \Exception('Value of reserved byte incorrect.', RESERVED_BYTE_INCORRECT);
				else
					$this->e = $this->e | RESERVED_BYTE_INCORRECT;
			}
			//test type (must be 1 or 2)
			if(!in_array($this->idType, $this->validTypes)) {
				if($this->stopOnErrors)
					throw new \Exception('Type value must be 1 or 2.', TYPE_INCORRECT);
				else
					$this->e = $this->e | TYPE_INCORRECT;
			}
			for($i = 0; $i < $this->idCount; $i++) {
				$this->idEntries[] = new IconDirEntry(substr($file, 6+($i*16), 16), $stopOnErrors);
			}
		}
	}
	/**
	*	Use this function to get idEntry at specified index.
	*	@return IconDirEntry returns structure at index
	*/
	function getIconDirEntry($index = 0) {
		return $this->idEntries[$index];
	}
	/**
	*	Use this function to get idEntres.
	*	@return array returns all iconDirEntries
	*/
	function getIconDirEntries() {
		return $this->idEntries;
	}
	/**
	*	Use this function to save actual status to specified string.
	*	@param str &$file pointer to string
	*/
	function save(&$file) {
		p2($file, 0, "vvv", $this->idReserved, $this->idType, $this->idCount);
		foreach($this->idEntries as $key=>$value) {
			$this->idEntries[$key]->save($file, $key);
		}
	}
}
/**
*	Microsoft ICONDIRENTRY structure. It is used to store information about image.
*	@author Tomas W Volf <hide@address.com>
*	@version 1.0
*	@copyright Copyright (c) Tomas Volf
*	@package PHPico
*	@license http://www.fsf.org/licensing/licenses/lgpl.html LGPL
*	@link http://msdn.microsoft.com/en-us/library/ms997538.aspx msdn.microsoft.com
*/
class IconDirEntry {
	/**
	*	Width, in pixels, of the image.
	*	@var int
	*/
	public $bWidth;
  /**
  *	Height, in pixels, of the image.
	*	@var int
	*/
	public $bHeight;
  /**
  *	Number of colors in image (0 if >=8bpp).
	*	@var int
	*/
	public $bColorCount;
  /**
  *	Reserved (must be 0).
	*	@var int
	*/
	public $bReserved;
  /**
  *	Color Planes.
	*	@var int
	*/
	public $wPlanes;
  /**
  *	Bits per pixel.
	*	@var int
	*/
	public $wBitCount;
  /**
  *	How many bytes in this resource?
	*	@var int
	*/
	public $dwBytesInRes;
  /**
  *	Where in the file is this image?
	*	@var int
	*/
	public $dwImageOffset;
	/**
	*	Used to store errors.
	*	@var int
	*/
	public $e = 0;
	/**
	*	Stop on errors?
	*	@var bool
	*/
	public $stopOnErrors = true;
	/**
	*	Load this IconDirEntry from part of file.
	*	@param string $file part of file with IconDirEntry
	*	@param bool &$stopOnErrors stop on errors?
	*	@return IconDirEntry returns new instance of IconDirEntry
	*/
	function IconDirEntry($file = null, &$stopOnErrors) {
		$this->e = 0;
		$this->stopOnErrors = $stopOnErrors;
		if($file != null) {
			$this->setWidth(readLE($file, 0, 1));
			$this->setHeight(readLE($file, 1, 1));
			$this->setColorCount(readLE($file, 2, 1));
			$this->setReserved(readLE($file, 3, 1));
			$this->setPlanes(readLE($file, 4, 2));
			$this->setBitCount(readLE($file, 6, 2));
			$this->setBytesInRes(readLE($file, 8, 4));
			$this->setImageOffset(readLE($file, 12, 4));
		}
	}
	/**
	*	Gets value of width.
	*	@return in return value of width
	*/
	function getWidth() {
		return $this->bWidth;
	}
	/**
	*	Gets value of height.
	*	@return in return value of height
	*/
	function getHeight() {
		return $this->bHeight;
	}
	/**
	*	Gets value of color count.
	*	@return in return value of color count
	*/
	function getColorCount() {
		return $this->bColorCount;
	}
	/**
	*	Gets value of reserved.
	*	@return in return value of reserved
	*/
	function getReserved() {
		return $this->bReserved;
	}
	/**
	*	Gets value of planes.
	*	@return in return value of planes
	*/
	function getPlanes() {
		return $this->wPlanes;
	}
	/**
	*	Gets value of bit count.
	*	@return in return value of bit count
	*/
	function getBitCount() {
		return $this->wBitCount;
	}
	/**
	*	Gets value of bytes in resource.
	*	@return in return value of bytes in resource
	*/
	function getBytesInRes() {
		return $this->dwBytesInRes;
	}
	/**
	*	Gets value of image offset.
	*	@return in return value of image offset
	*/
	function getImageOffset() {
		return $this->dwImageOffset;
	}
	/**
  *	Sets value of width.
	*	@param int $to new value of width
	*	@param bool $recalc recalculate values of related variables?
	*	@return int returns value of width
  */
  function setWidth($to, $recalc = true) {
		if((0 <= $to) and ($to <= 255))
			$this->bWidth = $to;
		else
			if($this->stopOnErrors)
				throw new \Exception('Width must be between 0 and 255.', INVALID_WIDTH);
			else
				$this->e = $this->e | INVALID_WIDTH;
		if($recalc)
			$this->recalc();
		return $this->bWidth;
	}
	/**
  *	Sets value of height.
	*	@param int $to new value of height
	*	@param bool $recalc recalculate values of related variables?
	*	@return int returns value of height
  */
  function setHeight($to, $recalc = true) {
		if((0 <= $to) and ($to <= 255))
			$this->bHeight = $to;
		else
			if($this->stopOnErrors)
				throw new \Exception('Height must be between 0 and 255.', INVALID_HEIGHT);
			else
				$this->e = $this->e | INVALID_HEIGHT;
		if($recalc)
			$this->recalc();
		return $this->bHeight;
	}
	/**
  *	Sets value of color count.
	*	@param int $to new value of color count
	*	@param bool $recalc recalculate values of related variables?
	*	@return int returns value of color count
  */
  function setColorCount($to, $recalc = true) {
		if((0 <= $to) and ($to <= 255))
			$this->bColorCount = $to;
		else
			if($this->stopOnErrors)
				throw new \Exception('Color count must be between 0 and 255.', INVALID_COLORCOUNT);
			else
				$this->e = $this->e | INVALID_COLORCOUNT;
		if($recalc)
			$this->recalc();
		return $this->bColorCount;
	}
	/**
  *	Sets value of reserved byte.
	*	@param int $to new value of reserved byte
	*	@return int returns value of reserved byte
  */
  function setReserved($to) {
		if($to == 0)
			$this->bReserved = $to;
		else
			if($this->stopOnErrors)
				throw new \Exception('Reserved byte incorrect.', RESERVED_BYTE_INCORRECT);
			else
				$this->e = $this->e | RESERVED_BYTE_INCORRECT;
		return $this->bReserved;
	}
	/**
  *	Sets value of planes.
	*	@param int $to new value of planes
	*	@return int returns value of planes
  */
  function setPlanes($to) {
		$this->wPlanes = $to;
		return $this->wPlanes;
	}
	/**
  *	Sets value of bit count.
	*	@param int $to new value of bit count
	*	@param bool $recalc recalculate values of related variables?
	*	@return int returns value of bit count
  */
  function setBitCount($to, $recalc = true) {
		$this->wBitCount = $to;
		if($recalc)
			$this->recalc();
		return $this->wBitCount;
	}
	/**
  *	Sets value of bytes in resource (DO NOT USE!).
	*	@param int $to new value of bytes in resource
	*	@return int returns value of bytes in resource
  */
  function setBytesInRes($to) {
		$this->dwBytesInRes = $to;
		return $this->dwBytesInRes;
	}
	/**
  *	Sets value of image offset.
	*	@param int $to new value of image offset
	*	@return int returns value of image offset
  */
  function setImageOffset($to) {
		$this->dwImageOffset = $to;
		return $this->dwImageOffset;
	}
	/**
	*	This function calculate new value of dwBytesInRes
	*	@return int return new value = dwBytesInRes
	*/
	function recalc() {
		$icHeader = 40;
		$icColors = 4 * $this->bColorCount;
		$size = $this->bWidth * $this->bHeight;
		$add_whatX = 32 - ceil($this->bWidth * $this->wBitCount) % 32;
		if($add_whatX == 32)
			$add_whatX = 0;
		$additionX = ceil($add_whatX * $this->bHeight);
		$icXOR = ceil(($additionX + $size * $this->wBitCount) / 8);
		$add_whatA = 32 - $this->bWidth % 32;
		if($add_whatA == 32)
			$add_whatA = 0;
		$additionA = ceil($add_whatA * $this->bHeight);
		$icAND = ceil(($additionA + $size) / 8);
		$this->dwBytesInRes = $icHeader + $icColors + $icXOR + $icAND;
		return $this->dwBytesInRes;
	}
	/**
	*	Use this function to save actual status to specified string.
	*	@param str &$file pointer to string
	*	@param int $index number of this IconDirEntry (to determine offset)
	*/
	function save(&$file, $index) {
		$offset = 6 + $index * 16;
		p2($file, $offset, "CCCCvvVV", $this->bWidth, $this->bHeight, $this->bColorCount, $this->bReserved, $this->wPlanes, $this->wBitCount, $this->dwBytesInRes, $this->dwImageOffset);
	}
	
}
/**
*	Microsoft ICONIMAGE structure. It is used to store image data.
*	@author Tomas W Volf <hide@address.com>
*	@version 1.0
*	@copyright Copyright (c) Tomas Volf
*	@package PHPico
*	@license http://www.fsf.org/licensing/licenses/lgpl.html LGPL
*/
class IconImage {
	/**
	*	Header of image data, stores informations about width, height, ...
	*	@var BITMAPINFOHEADER
	*/
	public $icHeader = null;
	/**
	*	Color table.
	*	@var array
	*/
  public $icColors = array();
  /**
  *	DIB bits for XOR mask.
  *	@var array
  */
  public $icXOR = array();
  /**
  *	DIB bits for AND mask.
  *	@var array
  */
  public $icAND = array();
  /**
  *	PHP true color Image
  *	@var resource
  */
  public $image = null;
  /**
	*	Stop on errors?
	*	@var bool
	*/
	public $stopOnErrors = true;
	/**
	*	Used to store errors.
	*	@var int
	*/
	public $e = 0;
	/**
	*	Create new instance of IconImage class and load file if $file not null.
	*	@param string $file content of image file
	*	@param bool &$stopOnErrors stop on errors?
	*	@param IconDirEntry $iconDirEntry IconDirEntry for this IconImage
	*	@return returns new instance of IconImage class
	*/
	function IconImage($file, $iconDirEntry, &$stopOnErrors) {
		$this->stopOnErrors = $stopOnErrors;
		$this->e = 0;
		if($file != null) {
			$file = substr($file, $iconDirEntry->getImageOffset(), $iconDirEntry->getBytesInRes());
			$this->icHeader = new BitMapInfoHeader(substr($file, 0, 40), $this->e, $this->stopOnErrors);
			if(0 <= $iconDirEntry->getColorCount() and $iconDirEntry->getColorCount() <= 255) {
				if($iconDirEntry->getBitCount() == 8)
					$colorLimit = 256;
				else
					$colorLimit = $iconDirEntry->getColorCount();
				for($i = 0; $i < $colorLimit; $i++) {
					$r = readLE($file, 42+($i*4), 1);
					$g = readLE($file, 41+($i*4), 1);
					$b = readLE($file, 40+($i*4), 1);
					$rd = readLE($file, 43+($i*4), 1);
					$this->icColors[] = new RGBQuad($r, $g, $b, $rd, $stopOnErrors);
				}
				//offset of XOR table (Xor Offset)
				$xo = 40 + $i * 4;
				$size = $this->icHeader->biWidth * ($this->icHeader->biHeight / 2);
				$h = $this->icHeader->biHeight / 2;
				$add_whatX = 32 - ceil($this->icHeader->biWidth * $this->icHeader->biBitCount) % 32;
				if($add_whatX == 32)
					$add_whatX = 0;
				$additionX = ceil($add_whatX * $h);
				$add_whatA = 32 - ceil($this->icHeader->biWidth) % 32;
				if($add_whatA == 32)
					$add_whatA = 0;
				$additionA = ceil($h * $add_whatA);
				$xoa = ceil(($size * $this->icHeader->biBitCount + $additionX) / 8);
				$xor_file = substr($file, $xo, $xoa);
				$and_file = substr($file, $xo + $xoa, ceil(($size  + $additionA)/ 8));
				if(strlen($xor_file) + strlen($and_file) == $xoa + ceil(($size + $additionA) / 8)) {
					for($i = 0; $i < $h; $i++)
						$this->icXOR[] = array();
					$add = 0;
					for($i = 0; $i < $h; $i++) {
						$im = $i * $this->icHeader->biWidth;
						if($this->icHeader->biBitCount < 24)
							for($j = 0; $j < $this->icHeader->biWidth; $j++) 
								$this->icXOR[$h-$i][$j] = readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add, $this->icHeader->biBitCount);
						elseif($this->icHeader->biBitCount == 24)
							for($j = 0; $j < $this->icHeader->biWidth; $j++) {
								$tmp = new RGBQuad(readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add + 16, 8), readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add + 8, 8), readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add, 8), 0, $this->stopOnErrors);
								$index = count($this->icColors);
								$this->icColors[$index] = $tmp;
								$this->icXOR[$h-$i][$j] = $index;
							}
						elseif($this->icHeader->biBitCount == 32)
							for($j = 0; $j < $this->icHeader->biWidth; $j++) {
								$tmp = new RGBQuad(readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add + 16, 8), readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add + 8, 8), readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add, 8), readBites($xor_file, ($im + $j) * $this->icHeader->biBitCount + $add + 24, 8), $this->stopOnErrors);
								$index = count($this->icColors);
								$this->icColors[$index] = $tmp;
								$this->icXOR[$h-$i][$j] = $index;
							}
						$add += $add_whatX;
					}
					for($i = 0; $i < $h; $i++)
						$this->icAND[] = array();
					$add = 0;
					for($i = 0; $i < $h; $i++) {						
						$im = $i * $this->icHeader->biWidth + (+1);
						for($j = 0; $j < $this->icHeader->biWidth; $j++)
							$this->icAND[$h-$i][$j] = readBites($and_file, $im + $j + $add-1, 1);
						$add += $add_whatA;
					}
				}
				else {
					if($this->stopOnErrors)
						throw new \Exception('There is not enought bytes in input file.', INVALID_INPUTOUTPUT_SIZE);
					else
						$this->e = $this->e | INVALID_INPUTOUTPUT_SIZE;
				}
			}
			else {
				if($this->stopOnErrors)
					throw new \Exception('ColorCount must be between 0 and 255.', INVALID_COLORCOUNT);
				else
					$this->e = $this->e | INVALID_COLORCOUNT;
			}
		}
	}
	/**
	*	Use this function to save actual status to specified string.
	*	@param str &$file pointer to string
	*	@param IconDirEntry $iconDirEntry IconDirEntry structure related to this IconImage
	*/
	function save(&$file, $iconDirEntry) {
		$offset = $iconDirEntry->getImageOffset();
		$this->icHeader->save($file, $offset);
		$offset += $this->icHeader->getSize();
		if(($iconDirEntry->getColorCount() != 0) or ($iconDirEntry->getBitCount() == 8))
			foreach($this->icColors as $key=>$value) {
				$this->icColors[$key]->save($file, $offset);
				$offset += 4;
			}
		$size = $this->icHeader->biWidth * ($this->icHeader->biHeight / 2);
		$h = $this->icHeader->biHeight / 2;
		$add_whatX = 32 - ceil($this->icHeader->biWidth * $this->icHeader->biBitCount) % 32;
		if($add_whatX == 32)
			$add_whatX = 0;
		$add_whatX /= $this->icHeader->biBitCount;
		$add_whatA = 32 - ceil($this->icHeader->biWidth) % 32;
		if($add_whatA == 32)
			$add_whatA = 0;
		$save = '';
		for($i = 0; $i < $h; $i++)
			for($j = 0; $j < $this->icHeader->biWidth + $add_whatX; $j++) {
				if($this->icHeader->biBitCount < 24)
					if(isset($this->icXOR[$h-$i][$j]))
						$save .= d2b($this->icHeader->biBitCount, $this->icXOR[$h-$i][$j]);
					else
						$save .= d2b($this->icHeader->biBitCount, 0);
				elseif($this->icHeader->biBitCount == 24)
					if(isset($this->icXOR[$h-$i][$j]) and isset($this->icColors[$this->icXOR[$h-$i][$j]]))
						$save .= d2b($this->icHeader->biBitCount, hexdec(d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getB()).d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getG()).d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getR())));
					else
						$save .= d2b($this->icHeader->biBitCount, 0);
				elseif($this->icHeader->biBitCount == 32) {
					if(isset($this->icXOR[$h-$i][$j]) and isset($this->icColors[$this->icXOR[$h-$i][$j]])) {
						$save .= d2b($this->icHeader->biBitCount, hexdec(d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getB()).d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getG()).d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getR()).d2h(2, $this->icColors[$this->icXOR[$h-$i][$j]]->getRd())));
					}
					else
						$save .= d2b($this->icHeader->biBitCount, 0);
				}
			}
		for($i = 0; $i < $h; $i++)
			for($j = 0; $j < $this->icHeader->biWidth + $add_whatA; $j++) {
				if(isset($this->icAND[$h-$i][$j]))
					$save .= d2b(1, $this->icAND[$h-$i][$j]);
				else
					$save .= d2b(1, 0);
			}
		writeBinary($file, $offset, $save);
	}
}
/**
*	Microsoft RGBQUAD structure. It is used to store color info data.
*	@author Tomas W Volf <hide@address.com>
*	@version 1.0
*	@copyright Copyright (c) Tomas Volf
*	@package PHPico
*	@license http://www.fsf.org/licensing/licenses/lgpl.html LGPL
*	@link http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx BITMAPINFOHEADER at msdn.microsoft.com
*/
class RGBQuad {
	/**
	*	Specifies the intensity of blue in the color.
	*	@var int
	*/
	public $rgbBlue = 0;
	/**
	*	Specifies the intensity of green in the color.
	*	@var int
	*/
	public $rgbGreen = 0;
	/**
	*	Specifies the intensity of red in the color.
	*	@var int
	*/
	public $rgbRed = 0;
	/**
	*	Reserved, set to zero.
	*	@var int
	*/
	public $reserved = 0;
	/**
	*	Stop on errors?
	*	@var bool
	*/
	public $stopOnErrors = true;
	/**
	*	Used to store errors.
	*	@var int
	*/
	public $e = 0;
	/**
  *	Create new instance of RGBQuad class and load colors.
  *	@param bool &$stopOnErrors stop on errors?
	*	@param int $r intensity of red
	*	@param int $g intensity of green
	*	@param int $b intensity of blue
	*	@param int $rd reserved byte (must be 0)
	*	@return RGBQuad returns new instance of RGBQuad
  */
  function RGBQuad($r = 0, $g = 0, $b = 0, $rd = 0, &$stopOnErrors = false) {
  	$this->e = 0;
  	$this->stopOnErrors = $stopOnErrors;
  	$this->setR($r);
  	$this->setG($g);
  	$this->setB($b);
  	$this->setRd($rd);
	}
	/**
  *	Gets value of red color.
	*	@return int returns value of red color
  */
  function getR() {
  	return $this->rgbRed;
  }
  /**
  *	Gets value of green color.
	*	@return int returns value of green color
  */
  function getG() {
  	return $this->rgbGreen;
  }
  /**
  *	Gets value of blue color.
	*	@return int returns value of blue color
  */
  function getB() {
  	return $this->rgbBlue;
  }
  /**
  *	Gets value of reserved byte.
	*	@return int returns value of reserved byte
  */
  function getRd() {
  	return $this->reserved;
  }
  /**
  *	Sets value of red color.
	*	@param int $to new value of red color
	*	@return int returns value of red color
  */
  function setR($to) {
  	if((0 <= $to) and ($to <= 255))
  		$this->rgbRed = $to;
  	else
			if($this->stopOnErrors)
				throw new \Exception('Color intensity must be between 0 and 255.', INVALID_COLOR_INTENSITY);
			else
				$this->e = $this->e | INVALID_COLOR_INTENSITY;
		return $this->rgbRed;
  }
  /**
  *	Sets value of green color.
	*	@param int $to new value of green color
	*	@return int returns value of green color
  */
  function setG($to) {
  	if((0 <= $to) and ($to <= 255))
  		$this->rgbGreen = $to;
  	else
			if($this->stopOnErrors)
				throw new \Exception('Color intensity must be between 0 and 255.', INVALID_COLOR_INTENSITY);
			else
				$this->e = $this->e | INVALID_COLOR_INTENSITY;
		return $this->rgbGreen;
  }
  /**
  *	Sets value of blue color.
	*	@param int $to new value of blue color
	*	@return int returns value of blue color
  */
  function setB($to) {
  	if((0 <= $to) and ($to <= 255))
  		$this->rgbBlue = $to;
  	else
			if($this->stopOnErrors)
				throw new \Exception('Color intensity must be between 0 and 255.', INVALID_COLOR_INTENSITY);
			else
				$this->e = $this->e | INVALID_COLOR_INTENSITY;
		return $this->rgbBlue;
  }
  /**
  *	Sets value of reserved byte.
	*	@param int $to new value of reserved byte
	*	@return int returns value of reserved
  */
  function setRd($to) {
  	if((0 <= $to) and ($to <= 255))
  		$this->reserved = $to;
  	else
			if($this->stopOnErrors)
				throw new \Exception('Reserved byte value must be between 0 and 255.', RESERVED_BYTE_INCORRECT);
			else
				$this->e = $this->e | RESERVED_BYTE_INCORRECT;
		return $this->reserved;
  }
  /**
	*	Use this function to save actual status to specified string.
	*	@param str &$file pointer to string
	*	@param int $offset offset in file
	*/
	function save(&$file, $offset) {
		p2($file, $offset, "CCCC", $this->getB(), $this->getG(), $this->getR(), $this->getRd());
	}
}
/**
*	Microsoft BITMAPINFOHEADER structure. It is used to store image data header.
*	@author Tomas W Volf <hide@address.com>
*	@version 1.0
*	@copyright Copyright (c) Tomas Volf
*	@package PHPico
*	@license http://www.fsf.org/licensing/licenses/lgpl.html LGPL
*	@link http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx BITMAPINFOHEADER at msdn.microsoft.com
*/
class BitMapInfoHeader {
	/**
	*	The number of bytes required by the structure.
	*	@var int
	*/
	public $biSize;
	/**
	*	The width of the bitmap, in pixels.
	*	@var int
	*/
  public $biWidth;
  /**
  *	The added height of XOR and AND bitmaps, in pixels. If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.
  *	@var int
  */
  public $biHeight;
  /**
  *	The number of planes for the target device. This value must be set to 1.
  *	@var int
  */
  public $biPlanes;
  /**
  *	The number of bits-per-pixel. The biBitCount member of the BITMAPINFOHEADER structure determines the number of bits that define each pixel and the maximum number of colors in the bitmap.
  *	@var int
  */
  public $biBitCount;
  /**
  *	The type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed). Must be 0.
  *	@var int
  */
  public $biCompression;
  /**
  *	The size, in bytes, of the image. This may be set to zero for BI_RGB ($biCompression == 0) bitmaps.
  *	@var int
  */
  public $biSizeImage;
  /**
  *	The horizontal resolution, in pixels-per-meter, of the target device for the bitmap. Must be 0.
  *	@var int
  */
  public $biXPelsPerMeter;
  /**
  *	The vertical resolution, in pixels-per-meter, of the target device for the bitmap. Must be 0.
  *	@var int
  */
  public $biYPelsPerMeter;
  /**
  *	The number of color indexes in the color table that are actualy used by the bitmap. Must be 0.
  *	@var int
  */
  public $biClrUsed;
  /**
  *	The number of color indexes that are required for displaying the bitmap. If this value is zero, all colors are required. Must be 0.
  *	@var int
  */
  public $biClrImportant;
  /**
	*	Stop on errors?
	*	@var bool
	*/
	public $stopOnErrors = true;
	/**
	*	Used to store errors.
	*	@var int
	*/
	public $e = 0;
	/**
  *	Create new instance of BitMapInfoHeader class and load header.
  *	@param string $header data of BitMapInfoHeader
  *	@param bool &$stopOnErrors stop on errors?
	*	@return returns new instance of BitMapInfoHeader
  */
  function BitMapInfoHeader($header, &$stopOnErrors) {
  	$this->e = 0;
  	$this->stopOnErrors = $stopOnErrors;
  	if($header != null) {
  		$this->setSize(readLE($header, 0, 4));
  		$this->setWidth(readLE($header, 4, 4));
  		$this->setHeight(readLE($header, 8, 4));
  		$this->setPlanes(readLE($header, 12, 2));
  		$this->setBitCount(readLE($header, 14, 2));
	  	$this->setCompression(readLE($header, 16, 4));
  		$this->setSizeImage(readLE($header, 20, 4));
  		$this->setXPelsPerMeter(readLE($header, 24, 4));
	  	$this->setYPelsPerMeter(readLE($header, 28, 4));
  		$this->setClrUsed(readLE($header, 32, 4));
  		$this->setClrImportant(readLE($header, 36, 4));
	  }
  }
  /**
  *	Gets value of Size.
	*	@return int returns value of Size
  */
  function getSize() {
  	return $this->biSize;
  }
  /**
  *	Gets value of Width.
	*	@return int returns value of Width
  */
  function getWidth() {
  	return $this->biWidth;
  }
  /**
  *	Gets value of Height.
	*	@return int returns value of Height
  */
  function getHeight() {
  	return $this->biHeight;
  }
  /**
  *	Gets value of Planes.
	*	@return int returns value of Planes
  */
  function getPlanes() {
  	return $this->biPlanes;
  }
  /**
  *	Gets value of BitCount.
	*	@return int returns value of BitCount
  */
  function getBitCount() {
  	return $this->biBitCount;
  }
  /**
  *	Gets value of Compression.
	*	@return int returns value of Compression
  */
  function getCompression() {
  	return $this->biCompression;
  }
  /**
  *	Gets value of SizeImage.
	*	@return int returns value of SizeImage
  */
  function getSizeImage() {
  	return $this->biSizeImage;
  }
  /**
  *	Gets value of XPelsPerMeter.
	*	@return int returns value of XPelsPerMeter
  */
  function getXPelsPerMeter() {
  	return $this->biXPelsPerMeter;
  }
  /**
  *	Gets value of YPelsPerMeter.
	*	@return int returns value of YPelsPerMeter
  */
  function getYPelsPerMeter() {
  	return $this->biYPelsPerMeter;
  }
  /**
  *	Gets value of ClrUsed.
	*	@return int returns value of ClrUsed
  */
  function getClrUsed() {
  	return $this->biClrUsed;
  }
  /**
  *	Gets value of Important.
	*	@return int returns value of Important
  */
  function getClrImportant() {
  	return $this->biClrImportant;
  }
  /**
  *	Sets value of Size.
	*	@param int $to new value of Size
	*	@return int returns value of Size
  */
  function setSize($to) {
  	$this->biSize = $to;
  	return $this->biSize;
  }
  /**
  *	Sets value of Width.
	*	@param int $to new value of Width
	*	@return int returns value of Width
  */
  function setWidth($to) {
  	$this->biWidth = $to;
  	return $this->biWidth;
  }
  /**
  *	Sets value of Height.
	*	@param int $to new value of Height
	*	@return int returns value of Height
  */
  function setHeight($to) {
  	$this->biHeight = $to;
  	return $this->biHeight;
  }
  /**
  *	Sets value of Planes.
	*	@param int $to new value of Planes
	*	@return int returns value of Planes
  */
  function setPlanes($to) {
  	$this->biPlanes = $to;
  	return $this->biPlanes;
  }
  /**
  *	Sets value of BitCount.
	*	@param int $to new value of BitCount
	*	@return int returns value of BitCount
  */
  function setBitCount($to) {
  	$this->biBitCount = $to;
  	return $this->biBitCount;
  }
  /**
  *	Sets value of Compression.
	*	@param int $to new value of Compression
	*	@return int returns value of Compression
  */
  function setCompression($to) {
  	if($this->biCompression != 0) {
  		if($this->stopOnErrors)
				throw new \Exception('Compression must be 0.', MUST_BE_ZERO);
			else
				$this->e = $this->e | MUST_BE_ZERO;
  	}
  	else
  		$this->biCompression = $to;  	
  	return $this->biCompression;
  }
  /**
  *	Sets value of SizeImage.
	*	@param int $to new value of SizeImage
	*	@return int returns value of SizeImage
  */
  function setSizeImage($to) {
  	$this->biSizeImage = $to;
  	return $this->biSizeImage;
  }
  /**
  *	Sets value of XPelsPerMeter.
	*	@param int $to new value of XPelsPerMeter
	*	@return int returns value of XPelsPerMeter
  */
  function setXPelsPerMeter($to) {
  	if($this->biXPelsPerMeter != 0) {
  		if($this->stopOnErrors)
				throw new \Exception('XPelsPerMeter must be 0.', MUST_BE_ZERO);
			else
				$this->e = $this->e | MUST_BE_ZERO;
  	}
  	else
  		$this->biXPelsPerMeter = $to;
  	return $this->biXPelsPerMeter;
  }
  /**
  *	Sets value of YPelsPerMeter.
	*	@param int $to new value of YPelsPerMeter
	*	@return int returns value of YPelsPerMeter
  */
  function setYPelsPerMeter($to) {
  	if($this->biYPelsPerMeter != 0) {
  		if($this->stopOnErrors)
				throw new \Exception('YPelPerMeter must be 0.', MUST_BE_ZERO);
			else
				$this->e = $this->e | MUST_BE_ZERO;
  	}
  	else
  		$this->biYPelsPerMeter = $to;
  	return $this->biYPelsPerMeter;
  }
  /**
  *	Sets value of ClrUsed.
	*	@param int $to new value of ClrUsed
	*	@return int returns value of ClrUsed
  */
  function setClrUsed($to) {
  	if($this->biClrUsed != 0) {
  		if($this->stopOnErrors)
				throw new \Exception('ClrUsed must be 0.', MUST_BE_ZERO);
			else
				$this->e = $this->e | MUST_BE_ZERO;
  	}
  	else
  		$this->biClrUsed = $to;
  	return $this->biClrUsed;
  }
  /**
  *	Sets value of ClrImportant.
	*	@param int $to new value of ClrImportant
	*	@return int returns value of ClrImportant
  */
  function setClrImportant($to) {
  	if($this->biClrImportant != 0) {
  		if($this->stopOnErrors)
				throw new \Exception('ClrImportant must be 0.', MUST_BE_ZERO);
			else
				$this->e = $this->e | MUST_BE_ZERO;
  	}
  	else
  		$this->biClrImportant = $to;
  	return $this->biClrImportant;
  }
  /**
	*	Use this function to save actual status to specified string.
	*	@param str &$file pointer to string
	*	@param int $offset offset in file
	*/
	function save(&$file, $offset) {
		p2($file, $offset, "VVVvvVVVVVV", $this->getSize(), $this->getWidth(), $this->getHeight(), $this->getPlanes(), $this->getBitCount(), $this->getCompression(), $this->getSizeImage(), $this->getXPelsPerMeter(), $this->getYPelsPerMeter(), $this->getClrUsed(), $this->getClrImportant());
	}
}
?>
Return current item: PHPico