203 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * PHP Exif Exiftool Reader Adapter
 | |
|  *
 | |
|  * @link        http://github.com/miljar/PHPExif for the canonical source repository
 | |
|  * @copyright   Copyright (c) 2013 Tom Van Herreweghe <tom@theanalogguy.be>
 | |
|  * @license     http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License
 | |
|  * @category    PHPExif
 | |
|  * @package     Reader
 | |
|  */
 | |
| 
 | |
| namespace PHPExif\Adapter;
 | |
| 
 | |
| use PHPExif\Exif;
 | |
| use InvalidArgumentException;
 | |
| use RuntimeException;
 | |
| 
 | |
| /**
 | |
|  * PHP Exif Exiftool Reader Adapter
 | |
|  *
 | |
|  * Uses native PHP functionality to read data from a file
 | |
|  *
 | |
|  * @category    PHPExif
 | |
|  * @package     Reader
 | |
|  */
 | |
| class Exiftool extends AdapterAbstract
 | |
| {
 | |
|     const TOOL_NAME = 'exiftool';
 | |
| 
 | |
|     /**
 | |
|      * Path to the exiftool binary
 | |
|      *
 | |
|      * @var string
 | |
|      */
 | |
|     protected $toolPath;
 | |
| 
 | |
|     /**
 | |
|      * @var boolean
 | |
|      */
 | |
|     protected $numeric = true;
 | |
| 
 | |
|     /**
 | |
|      * @var array
 | |
|      */
 | |
|     protected $encoding = array();
 | |
| 
 | |
|     /**
 | |
|      * @var string
 | |
|      */
 | |
|     protected $mapperClass = '\\PHPExif\\Mapper\\Exiftool';
 | |
| 
 | |
|     /**
 | |
|      * Setter for the exiftool binary path
 | |
|      *
 | |
|      * @param string $path The path to the exiftool binary
 | |
|      * @return \PHPExif\Adapter\Exiftool Current instance
 | |
|      * @throws \InvalidArgumentException When path is invalid
 | |
|      */
 | |
|     public function setToolPath($path)
 | |
|     {
 | |
|         if (!file_exists($path)) {
 | |
|             throw new InvalidArgumentException(
 | |
|                 sprintf(
 | |
|                     'Given path (%1$s) to the exiftool binary is invalid',
 | |
|                     $path
 | |
|                 )
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         $this->toolPath = $path;
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param boolean $numeric
 | |
|      */
 | |
|     public function setNumeric($numeric)
 | |
|     {
 | |
|         $this->numeric = $numeric;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @see  http://www.sno.phy.queensu.ca/~phil/exiftool/faq.html#Q10
 | |
|      * @param array $encoding encoding parameters in an array eg. ["exif" => "UTF-8"]
 | |
|      */
 | |
|     public function setEncoding($encoding)
 | |
|     {
 | |
|         $possible_keys = array("exif", "iptc", "id3", "photoshop", "quicktime",);
 | |
|         $possible_values = array("UTF8", "cp65001", "UTF-8", "Thai", "cp874", "Latin", "cp1252",
 | |
|             "Latin1", "MacRoman", "cp10000", "Mac", "Roman", "Latin2", "cp1250", "MacLatin2",
 | |
|             "cp10029", "Cyrillic", "cp1251", "Russian", "MacCyrillic", "cp10007", "Greek",
 | |
|             "cp1253", "MacGreek", "cp10006", "Turkish", "cp1254", "MacTurkish", "cp10081",
 | |
|             "Hebrew", "cp1255", "MacRomanian", "cp10010", "Arabic", "cp1256", "MacIceland",
 | |
|             "cp10079", "Baltic", "cp1257", "MacCroatian", "cp10082", "Vietnam", "cp1258",);
 | |
|         foreach ($encoding as $type => $encoding) {
 | |
|             if (in_array($type, $possible_keys) && in_array($encoding, $possible_values)) {
 | |
|                 $this->encoding[$type] = $encoding;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Getter for the exiftool binary path
 | |
|      * Lazy loads the "default" path
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function getToolPath()
 | |
|     {
 | |
|         if (empty($this->toolPath)) {
 | |
|             $path = exec('which ' . self::TOOL_NAME);
 | |
|             $this->setToolPath($path);
 | |
|         }
 | |
| 
 | |
|         return $this->toolPath;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Reads & parses the EXIF data from given file
 | |
|      *
 | |
|      * @param string $file
 | |
|      * @return \PHPExif\Exif Instance of Exif object with data
 | |
|      * @throws \RuntimeException If the EXIF data could not be read
 | |
|      */
 | |
|     public function getExifFromFile($file)
 | |
|     {
 | |
|         $encoding = '';
 | |
|         if (!empty($this->encoding)) {
 | |
|             $encoding = '-charset ';
 | |
|             foreach ($this->encoding as $key => $value) {
 | |
|                 $encoding .= escapeshellarg($key).'='.escapeshellarg($value);
 | |
|             }
 | |
|         }
 | |
|         $result = $this->getCliOutput(
 | |
|             sprintf(
 | |
|                 '%1$s%3$s -j -a -G1 %5$s -c %4$s %2$s',
 | |
|                 $this->getToolPath(),
 | |
|                 escapeshellarg($file),
 | |
|                 $this->numeric ? ' -n' : '',
 | |
|                 escapeshellarg('%d deg %d\' %.4f"'),
 | |
|                 $encoding
 | |
|             )
 | |
|         );
 | |
| 
 | |
|         if (!mb_check_encoding($result, "utf-8")) {
 | |
|             $result = utf8_encode($result);
 | |
|         }
 | |
|         $data = json_decode($result, true);
 | |
|         if (!is_array($data)) {
 | |
|             throw new RuntimeException(
 | |
|                 'Could not decode exiftool output'
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         // map the data:
 | |
|         $mapper = $this->getMapper();
 | |
|         $mapper->setNumeric($this->numeric);
 | |
|         $mappedData = $mapper->mapRawData(reset($data));
 | |
| 
 | |
|         // hydrate a new Exif object
 | |
|         $exif = new Exif();
 | |
|         $hydrator = $this->getHydrator();
 | |
|         $hydrator->hydrate($exif, $mappedData);
 | |
|         $exif->setRawData(reset($data));
 | |
| 
 | |
|         return $exif;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the output from given cli command
 | |
|      *
 | |
|      * @param string $command
 | |
|      * @return mixed
 | |
|      * @throws RuntimeException If the command can't be executed
 | |
|      */
 | |
|     protected function getCliOutput($command)
 | |
|     {
 | |
|         $descriptorspec = array(
 | |
|             0 => array('pipe', 'r'),
 | |
|             1 => array('pipe', 'w'),
 | |
|             2 => array('pipe', 'a')
 | |
|         );
 | |
| 
 | |
|         $process = proc_open($command, $descriptorspec, $pipes);
 | |
| 
 | |
|         if (!is_resource($process)) {
 | |
|             throw new RuntimeException(
 | |
|                 'Could not open a resource to the exiftool binary'
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         $result = stream_get_contents($pipes[1]);
 | |
|         fclose($pipes[0]);
 | |
|         fclose($pipes[1]);
 | |
|         fclose($pipes[2]);
 | |
| 
 | |
|         proc_close($process);
 | |
| 
 | |
|         return $result;
 | |
|     }
 | |
| }
 |