'The uploaded file can not be read', self::NOT_PNG => 'The uploaded file is not PNG image', self::NO_TRANSPARENCY => 'The uploaded PNG has no transparency', ); /** * Indicates the need for additional pixels transparency check * @var bool */ protected $_pixelsCheck = false; /** * Pixel coordinates for additional transparency check [x, y, alpha] * @var array */ protected $_pixelsMap = array( array(0, 0, 0), array(0, -1, 0), array(-1, 0, 0), array(-1, -1, 0), ); function __construct($options = null) { if ($options instanceof Zend_Config) { $options = $options->toArray(); } if ($options && is_array($options)) { $this->setOptions($options); } return $this; } public function setOptions($options) { if (isset($options['options'])) { unset($options['options']); } foreach ($options as $key => $value) { $method = 'set' . ucfirst($key); if (method_exists($this, $method)) { $this->$method($value); } } return $this; } /** * @param bool $flag * @return Qs_Validate_File_PngHasTransparency */ public function setPixelsCheck($flag) { $this->_pixelsCheck = (bool) $flag; return $this; } public function getPixelsCheck() { return $this->_pixelsCheck; } /** * Pixel coordinates for additional transparency check [x, y, alpha] * @param array $pixelsMap * @return Qs_Validate_File_PngHasTransparency */ public function setPixelsMap(array $pixelsMap) { if ($pixelsMap && is_array($pixelsMap)) { $_pixelsMap = array(); foreach ($pixelsMap as $spec) { list($x, $y, $a) = $spec; $_pixelsMap[] = array((int) $x, (int) $y, (int) $a); } $this->_pixelsMap = $_pixelsMap; } return $this; } /** * @return array */ public function getPixelsMap() { return $this->_pixelsMap; } /** * @param mixed|string $value Image Filename * @param array|null $file File data from Zend_File_Transfer * @return bool */ public function isValid($value, $file = null) { if (empty($value) || !is_readable($value)) { $this->_error(self::NOT_READABLE, $value); return false; } $validSignature = chr(0x89) . chr(0x50) . chr(0x4E) . chr(0x47); if ($validSignature !== file_get_contents($value, false, null, 0, 4)) { $this->_error(self::NOT_PNG, $value); return false; } if ((ord(file_get_contents($value, false, null, 25, 1)) & 4) || (($contents = file_get_contents($value)) && false !== strpos($contents, 'PLTE') && false !== strpos($contents, 'tRNS')) ) { return ($this->_pixelsCheck) ? $this->_checkPixelTransparency($value) : true; } $this->_error(self::NO_TRANSPARENCY, $file); return false; } /** * Check pixel transparency on png image according to $_pixelsMap * @param $filename * @return bool|string */ protected function _checkPixelTransparency($filename) { if (!$this->_pixelsCheck && empty($this->_pixelsMap)) { return true; } if (false !== ($image = imagecreatefrompng($filename)) && false !== ($size = getimagesize($filename)) ) { list($width, $height) = $size; foreach ($this->_pixelsMap as $spec) { list($x, $y, $a) = $spec; $x = ($x < 0) ? $width - $x : $x; $x = ($x < 0) ? 0 : (($x > $width) ? $width - 1 : $x); $y = ($y < 0) ? $height - $y : $y; $y = ($y < 0) ? 0 : (($y > $height) ? $height - 1 : $y); $pixelColor = imagecolorat($image, (int) $x, (int) $y); $colorInfo = imagecolorsforindex($image, $pixelColor); if ($colorInfo['alpha'] > $a) { return true; } } } return false; } }