<?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());
}
}
?>