├── .gitignore ├── composer.json ├── imageMetadataParser.php ├── license.txt ├── readme.markdown └── test └── test.php /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cnlpete/image-metadata-parser", 3 | "type": "library", 4 | "description": "An abstraction to Exif, ITPC and XMP", 5 | "keywords": ["php", "exif", "itpc"], 6 | "homepage": "https://github.com/cnlpete/imageMetadataParser", 7 | "license": "MIT", 8 | 9 | "require": { 10 | "php": ">=5.3.0" 11 | }, 12 | 13 | "authors": [{ 14 | "name": "Hauke Schade" 15 | }], 16 | 17 | "autoload": { 18 | "classmap": ["imageMetadataParser.php"] 19 | }, 20 | 21 | "target-dir": "" 22 | } 23 | -------------------------------------------------------------------------------- /imageMetadataParser.php: -------------------------------------------------------------------------------- 1 | sFilename = $sFilename; 20 | } 21 | 22 | public static function exifAvailable() { 23 | $load_ext = get_loaded_extensions(); 24 | return in_array('exif', $load_ext); 25 | } 26 | 27 | public function parseExif() { 28 | $aArr = @exif_read_data($this->sFilename, 'IFD0,THUMBNAIL', true); 29 | if ($aArr === false) 30 | return false; 31 | 32 | // the date and time the image was taken 33 | if (isset($aArr['IFD0']['DateTime'])) { 34 | $iTimestamp = self::timestampFromEXIF($aArr['IFD0']['DateTime']); 35 | if ($iTimestamp !== false) 36 | $this->aAttributes['datetime'] = $iTimestamp; 37 | } 38 | else if (isset($aArr['EXIF']['DateTimeOriginal'])) { 39 | $iTimestamp = self::timestampFromEXIF($aArr['EXIF']['DateTimeOriginal']); 40 | if ($iTimestamp !== false) 41 | $this->aAttributes['datetime'] = $iTimestamp; 42 | } 43 | else if (isset($aArr['EXIF']['DateTimeDigitized'])) { 44 | $iTimestamp = self::timestampFromEXIF($aArr['EXIF']['DateTimeDigitized']); 45 | if ($iTimestamp !== false) 46 | $this->aAttributes['datetime'] = $iTimestamp; 47 | } 48 | 49 | // the images title 50 | if (isset($aArr['COMPUTED']['UserComment'])) 51 | $this->aAttributes['title'] = trim($aArr['COMPUTED']['UserComment']); 52 | 53 | // the thumbnails mimetype 54 | if (isset($aArr['COMPUTED']['Thumbnail.MimeType'])) 55 | $this->aAttributes['thumbnailtype'] = $aArr['COMPUTED']['Thumbnail.MimeType']; 56 | 57 | // gps 58 | if (isset($aArr['GPS'])) 59 | $this->aAttributes['gps'] = $aArr['GPS']; 60 | 61 | // the exif orientation 62 | if (isset($aArr['IFD0']['Orientation'])) 63 | $this->aAttributes['orientation'] = $aArr['IFD0']['Orientation']; 64 | 65 | return true; 66 | } 67 | 68 | public function parseIPTC() { 69 | $aArr = @exif_read_data($this->sFilename, 'IDF0', true); 70 | $size = getimagesize($this->sFilename, $info); 71 | if(!isset($info['APP13'])) 72 | return false; 73 | 74 | $iptc = iptcparse($info['APP13']); 75 | 76 | if (isset($iptc["2#120"][0])) # caption 77 | $this->aAttributes['title'] = trim($iptc["2#120"][0]); 78 | else if (isset($iptc["2#105"][0])) # headline 79 | $this->aAttributes['title'] = trim($iptc["2#105"][0]); 80 | else if (isset($iptc["2#005"][0])) # graphic name 81 | $this->aAttributes['title'] = trim($iptc["2#005"][0]); 82 | 83 | if (isset($iptc["2#055"][0]) && isset($iptc["2#060"][0])) {# creation date 84 | $iTimestamp = self::timestampFromIPTC($iptc["2#055"][0], $iptc["2#060"][0]); 85 | if ($iTimestamp !== false) 86 | $this->aAttributes['datetime'] = $iTimestamp; 87 | } 88 | 89 | return true; 90 | } 91 | 92 | private function timestampFromIPTC( $date, $time ) { 93 | if ( ! ( preg_match('/\d\d\d\d\d\d[-+]\d\d\d\d/', $time) 94 | && preg_match('/\d\d\d\d\d\d\d\d/', $date) 95 | && substr($date, 0, 8) !== '00000000' ) ) { 96 | // wrong dates 97 | return false; 98 | } 99 | 100 | $iTimestamp = mktime( 101 | substr( $time, 0, 2 ), 102 | substr( $time, 2, 2 ), 103 | substr( $time, 4, 2 ), 104 | substr( $date, 4, 2 ), 105 | substr( $date, 6, 2 ), 106 | substr( $date, 0, 4 )); 107 | 108 | $iDiff = ( intval( substr( $time, 7, 2 ) ) *60*60 ) 109 | + ( intval( substr( $time, 9, 2 ) ) * 60 ); 110 | if ( substr( $time, 6, 1 ) === '-' ) 111 | $iDiff = - $iDiff; 112 | 113 | return $iTimestamp + $iDiff; 114 | } 115 | 116 | private function timestampFromEXIF( $string ) { 117 | if ( ! ( preg_match('/\d\d\d\d:\d\d:\d\d \d\d:\d\d:\d\d/', $string))) { 118 | // wrong date 119 | return false; 120 | } 121 | 122 | $iTimestamp = mktime( 123 | substr( $string, 11, 2 ), 124 | substr( $string, 14, 2 ), 125 | substr( $string, 17, 2 ), 126 | substr( $string, 5, 2 ), 127 | substr( $string, 8, 2 ), 128 | substr( $string, 0, 4 )); 129 | 130 | return $iTimestamp; 131 | } 132 | 133 | public function hasTitle() { 134 | return isset($this->aAttributes['title']); 135 | } 136 | public function getTitle() { 137 | return (string)$this->aAttributes['title']; 138 | } 139 | 140 | public function hasThumbnail() { 141 | return (isset($this->aAttributes['thumbnailtype'])); 142 | } 143 | public function getThumbnail() { 144 | return exif_thumbnail($this->sFilename); 145 | } 146 | public function getThumbnailContentType() { 147 | return $this->aAttributes['thumbnailtype']; 148 | } 149 | 150 | public function hasDateTime() { 151 | return isset($this->aAttributes['datetime']); 152 | } 153 | public function getDateTime() { 154 | return (int)$this->aAttributes['datetime']; 155 | } 156 | 157 | public function hasGPS() { 158 | return isset($this->aAttributes['gps']) && 159 | isset($this->aAttributes['gps']['GPSLongitude'][0]) && 160 | isset($this->aAttributes['gps']['GPSLatitude'][0]); 161 | } 162 | public function getGPS(&$dLat, &$dLong) { 163 | $latFirst = explode("/", $this->aAttributes['gps']['GPSLatitude'][0]); 164 | $latSecond = explode("/", $this->aAttributes['gps']['GPSLatitude'][1]); 165 | $latThird = explode("/", $this->aAttributes['gps']['GPSLatitude'][2]); 166 | $latRef = isset($this->aAttributes['gps']['GPSLatitudeRef']) ? $this->aAttributes['gps']['GPSLatitudeRef'] : 'N'; 167 | 168 | $latFirst = intval($latFirst[0]) / intval($latFirst[1]); 169 | $latSecond = intval($latSecond[0])/ intval($latSecond[1]); 170 | $latThird = intval($latThird[0]) / intval($latThird[1]); 171 | 172 | $dLat = $latFirst + ($latSecond*60 + $latThird) / 3600; 173 | if ($latRef == 'S') 174 | $dLat *= -1; 175 | 176 | $longFirst = explode("/", $this->aAttributes['gps']['GPSLongitude'][0]); 177 | $longSecond = explode("/", $this->aAttributes['gps']['GPSLongitude'][1]); 178 | $longThird = explode("/", $this->aAttributes['gps']['GPSLongitude'][2]); 179 | $longRef = isset($this->aAttributes['gps']['GPSLongitudeRef']) ? $this->aAttributes['gps']['GPSLongitudeRef'] : 'E'; 180 | 181 | $longFirst = intval($longFirst[0]) / intval($longFirst[1]); 182 | $longSecond = intval($longSecond[0])/ intval($longSecond[1]); 183 | $longThird = intval($longThird[0]) / intval($longThird[1]); 184 | 185 | $dLong = $longFirst + ($longSecond*60 + $longThird) / 3600; 186 | if ($longRef == 'W') 187 | $dLat *= -1; 188 | } 189 | public function getGPSArray() { 190 | $dLat = 0.0; $dLong = 0.0; 191 | $this->getGPS($dLat, $dLong); 192 | return array('lat' => $dLat, 'long' => $dLong); 193 | } 194 | 195 | public function hasOrientation() { 196 | return isset($this->aAttributes['orientation']); 197 | } 198 | public function getOrientation() { 199 | switch($this->aAttributes['orientation']) { 200 | case 3: 201 | return 180; 202 | break; 203 | case 6: 204 | return -90; 205 | break; 206 | case 8: 207 | return 90; 208 | break; 209 | default: 210 | return 0; 211 | } 212 | } 213 | public function getRawOrientation() { 214 | return $this->aAttributes['orientation']; 215 | } 216 | 217 | } 218 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Hauke Schade 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # Image-Metadata-Parser 2 | 3 | Hi! Image-Metadata-Parser is a set of php function which try to simplify the access to some imagefiles metadata (exif, itpc or xmp). 4 | 5 | ## Usage 6 | 7 | To use Image-Metadata-Parser, you simply need to place the class somewhere accessible within your application. 8 | 9 | Then you can create a new ParserObject with some imagefile and read its metadata. 10 | 11 | parseExif()) 16 | echo "Parsing of Exif Data failed"; 17 | if (!$imageparser->parseIPTC()) 18 | echo "Parsing of IPTC failed"; 19 | 20 | Get the title 21 | 22 | if ($imageparser->hasTitle()) 23 | echo "Image Title: " . $imageparser->getTitle(); 24 | 25 | get the date and time 26 | 27 | if ($imageparser->hasDateTime()) 28 | echo "Image Taken At: " . date('r', $imageparser->getDateTime()); 29 | 30 | get a thumbnail 31 | 32 | if ($imageparser->hasThumbnail()) { 33 | echo ""; 38 | } 39 | 40 | check the orientation 41 | 42 | if ($imageparser->hasOrientation()) 43 | if ($imageparser->getOrientation() === 0) 44 | echo "Image is oriented properly.
\n"; 45 | else 46 | echo "Image needs to be rotated with imagerotate(image, " . $imageparser->getOrientation() . ", 0);
\n"; 47 | 48 | get the gps coordinates 49 | 50 | if ($imageparser->hasGPS()) { 51 | $dLat = 0; $dLong = 0; 52 | $imageparser->getGPS($dLat, $dLong); 53 | echo "approximate GPS position: " . 54 | "Lat: " . $dLat . " Long: " . $dLong . ""; 55 | } 56 | 57 | Hope you find it useful! :) 58 | -------------------------------------------------------------------------------- /test/test.php: -------------------------------------------------------------------------------- 1 | Simple Test for ImageMetadataParser\n"; 15 | 16 | $imageparser = new ImageMetadataParser('test.jpg'); 17 | if (!$imageparser->parseExif()) 18 | echo "Parsing of EXIF failed
\n"; 19 | if (!$imageparser->parseIPTC()) 20 | echo "Parsing of IPTC failed
\n"; 21 | 22 | if ($imageparser->hasTitle()) 23 | echo "Image Title: " . $imageparser->getTitle() . "
\n"; 24 | 25 | if ($imageparser->hasDateTime()) 26 | echo "Image Taken At: " . date('r', $imageparser->getDateTime()) . "
\n"; 27 | 28 | if ($imageparser->hasOrientation()) 29 | if ($imageparser->getOrientation() === 0) 30 | echo "Image is oriented properly.
\n"; 31 | else { 32 | echo "Image needs to be rotated with imagerotate(image, " . $imageparser->getOrientation() . ", 0);
\n"; 33 | echo "Raw orientation info is " . $imageparser->getRawOrientation() . "
\n"; 34 | } 35 | 36 | if ($imageparser->hasThumbnail()) { 37 | echo "
\n"; 42 | } 43 | 44 | if ($imageparser->hasGPS()) { 45 | $dLat = 0; $dLong = 0; 46 | $imageparser->getGPS($dLat, $dLong); 47 | echo "approximate GPS position: " . 48 | "Lat: " . $dLat . " Long: " . $dLong . ""; 49 | } 50 | 51 | echo ""; 52 | --------------------------------------------------------------------------------