Rev 2131 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** Classe d'extraction de metadonnées afin de les mettre dans* un tableau au format du cel* Encodage en entrée : utf8* Encodage en sortie : utf8** @author Aurélien PERONNET <aurelien@tela-botanica.org>* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>* @version $Id$* @copyright © 2012, Tela Botanica*/class ExtracteurMetadonnees {private $meta = array();private $tableau_ids_tags_exif = array('InteropIndex' => '1','InteropVersion' => '2','ProcessingSoftware' => '11','SubfileType' => '254','OldSubfileType' => '255','ImageWidth' => '256','ImageHeight' => '257','BitsPerSample' => '258','Compression' => '259','PhotometricInterpretation' => '262','Thresholding' => '263','CellWidth' => '264','CellLength' => '265','FillOrder' => '266','DocumentName' => '269','ImageDescription' => '270','Make' => '271','Model' => '272','StripOffsets' => '273','Orientation' => '274','SamplesPerPixel' => '277','RowsPerStrip' => '278','StripByteCounts' => '279','MinSampleValue' => '280','MaxSampleValue' => '281','XResolution' => '282','YResolution' => '283','PlanarConfiguration' => '284','PageName' => '285','XPosition' => '286','YPosition' => '287','FreeOffsets' => '288','FreeByteCounts' => '289','GrayResponseUnit' => '290','GrayResponseCurve' => '291','T4Options' => '292','T6Options' => '293','ResolutionUnit' => '296','PageNumber' => '297','ColorResponseUnit' => '300','TransferFunction' => '301','Software' => '305','ModifyDate' => '306','Artist' => '315','HostComputer' => '316','Predictor' => '317','WhitePoint' => '318','PrimaryChromaticities' => '319','ColorMap' => '320','HalftoneHints' => '321','TileWidth' => '322','TileLength' => '323','TileOffsets' => '324','TileByteCounts' => '325','BadFaxLines' => '326','CleanFaxData' => '327','ConsecutiveBadFaxLines' => '328','SubIFD' => '330','InkSet' => '332','InkNames' => '333','NumberofInks' => '334','DotRange' => '336','TargetPrinter' => '337','ExtraSamples' => '338','SampleFormat' => '339','SMinSampleValue' => '340','SMaxSampleValue' => '341','TransferRange' => '342','ClipPath' => '343','XClipPathUnits' => '344','YClipPathUnits' => '345','Indexed' => '346','JPEGTables' => '347','OPIProxy' => '351','GlobalParametersIFD' => '400','ProfileType' => '401','FaxProfile' => '402','CodingMethods' => '403','VersionYear' => '404','ModeNumber' => '405','Decode' => '433','DefaultImageColor' => '434','T82Options' => '435','JPEGTables' => '437','JPEGProc' => '512','ThumbnailOffset' => '513','ThumbnailLength' => '514','JPEGRestartInterval' => '515','JPEGLosslessPredictors' => '517','JPEGPointTransforms' => '518','JPEGQTables' => '519','JPEGDCTables' => '520','JPEGACTables' => '521','YCbCrCoefficients' => '529','YCbCrSubSampling' => '530','YCbCrPositioning' => '531','ReferenceBlackWhite' => '532','StripRowCounts' => '559','ApplicationNotes' => '700','USPTOMiscellaneous' => '999','RelatedImageFileFormat' => '4096','RelatedImageWidth' => '4097','RelatedImageHeight' => '4098','Rating' => '18246','XP_DIP_XML' => '18247','StitchInfo' => '18248','RatingPercent' => '18249','ImageID' => '32781','WangTag1' => '32931','WangAnnotation' => '32932','WangTag3' => '32933','WangTag4' => '32934','Matteing' => '32995','DataType' => '32996','ImageDepth' => '32997','TileDepth' => '32998','Model2' => '33405','CFARepeatPatternDim' => '33421','CFAPattern2' => '33422','BatteryLevel' => '33423','KodakIFD' => '33424','Copyright' => '33432','ExposureTime' => '33434','FNumber' => '33437','MDFileTag' => '33445','MDScalePixel' => '33446','MDColorTable' => '33447','MDLabName' => '33448','MDSampleInfo' => '33449','MDPrepDate' => '33450','MDPrepTime' => '33451','MDFileUnits' => '33452','PixelScale' => '33550','AdventScale' => '33589','AdventRevision' => '33590','UIC1Tag' => '33628','UIC2Tag' => '33629','UIC3Tag' => '33630','UIC4Tag' => '33631','IPTC-NAA' => '33723','IntergraphPacketData' => '33918','IntergraphFlagRegisters' => '33919','IntergraphMatrix' => '33920','INGRReserved' => '33921','ModelTiePoint' => '33922','Site' => '34016','ColorSequence' => '34017','IT8Header' => '34018','RasterPadding' => '34019','BitsPerRunLength' => '34020','BitsPerExtendedRunLength' => '34021','ColorTable' => '34022','ImageColorIndicator' => '34023','BackgroundColorIndicator' => '34024','ImageColorValue' => '34025','BackgroundColorValue' => '34026','PixelIntensityRange' => '34027','TransparencyIndicator' => '34028','ColorCharacterization' => '34029','HCUsage' => '34030','TrapIndicator' => '34031','CMYKEquivalent' => '34032','SEMInfo' => '34118','AFCP_IPTC' => '34152','PixelMagicJBIGOptions' => '34232','ModelTransform' => '34264','WB_GRGBLevels' => '34306','LeafData' => '34310','PhotoshopSettings' => '34377','ExifOffset' => '34665','ICC_Profile' => '34675','TIFF_FXExtensions' => '34687','MultiProfiles' => '34688','SharedData' => '34689','T88Options' => '34690','ImageLayer' => '34732','GeoTiffDirectory' => '34735','GeoTiffDoubleParams' => '34736','GeoTiffAsciiParams' => '34737','ExposureProgram' => '34850','SpectralSensitivity' => '34852','GPSInfo' => '34853','ISO' => '34855','Opto-ElectricConvFactor' => '34856','Interlace' => '34857','TimeZoneOffset' => '34858','SelfTimerMode' => '34859','SensitivityType' => '34864','StandardOutputSensitivity' => '34865','RecommendedExposureIndex' => '34866','ISOSpeed' => '34867','ISOSpeedLatitudeyyy' => '34868','ISOSpeedLatitudezzz' => '34869','FaxRecvParams' => '34908','FaxSubAddress' => '34909','FaxRecvTime' => '34910','LeafSubIFD' => '34954','ExifVersion' => '36864','DateTimeOriginal' => '36867','CreateDate' => '36868','ComponentsConfiguration' => '37121','CompressedBitsPerPixel' => '37122','ShutterSpeedValue' => '37377','ApertureValue' => '37378','BrightnessValue' => '37379','ExposureCompensation' => '37380','MaxApertureValue' => '37381','SubjectDistance' => '37382','MeteringMode' => '37383','LightSource' => '37384','Flash' => '37385','FocalLength' => '37386','FlashEnergy' => '37387','SpatialFrequencyResponse' => '37388','Noise' => '37389','FocalPlaneXResolution' => '37390','FocalPlaneYResolution' => '37391','FocalPlaneResolutionUnit' => '37392','ImageNumber' => '37393','SecurityClassification' => '37394','ImageHistory' => '37395','SubjectArea' => '37396','ExposureIndex' => '37397','TIFF-EPStandardID' => '37398','SensingMethod' => '37399','CIP3DataFile' => '37434','CIP3Sheet' => '37435','CIP3Side' => '37436','StoNits' => '37439','MakerNoteCanon' => '37500','UserComment' => '37510','SubSecTime' => '37520','SubSecTimeOriginal' => '37521','SubSecTimeDigitized' => '37522','MSDocumentText' => '37679','MSPropertySetStorage' => '37680','MSDocumentTextPosition' => '37681','ImageSourceData' => '37724','XPTitle' => '40091','XPComment' => '40092','XPAuthor' => '40093','XPKeywords' => '40094','XPSubject' => '40095','FlashpixVersion' => '40960','ColorSpace' => '40961','ExifImageWidth' => '40962','ExifImageHeight' => '40963','RelatedSoundFile' => '40964','InteropOffset' => '40965','FlashEnergy' => '41483','SpatialFrequencyResponse' => '41484','Noise' => '41485','FocalPlaneXResolution' => '41486','FocalPlaneYResolution' => '41487','FocalPlaneResolutionUnit' => '41488','ImageNumber' => '41489','SecurityClassification' => '41490','ImageHistory' => '41491','SubjectLocation' => '41492','ExposureIndex' => '41493','TIFF-EPStandardID' => '41494','SensingMethod' => '41495','FileSource' => '41728','SceneType' => '41729','CFAPattern' => '41730','CustomRendered' => '41985','ExposureMode' => '41986','WhiteBalance' => '41987','DigitalZoomRatio' => '41988','FocalLengthIn35mmFormat' => '41989','SceneCaptureType' => '41990','GainControl' => '41991','Contrast' => '41992','Saturation' => '41993','Sharpness' => '41994','DeviceSettingDescription' => '41995','SubjectDistanceRange' => '41996','ImageUniqueID' => '42016','OwnerName' => '42032','SerialNumber' => '42033','LensInfo' => '42034','LensMake' => '42035','LensModel' => '42036','LensSerialNumber' => '42037','GDALMetadata' => '42112','GDALNoData' => '42113','Gamma' => '42240','ExpandSoftware' => '44992','ExpandLens' => '44993','ExpandFilm' => '44994','ExpandFilterLens' => '44995','ExpandScanner' => '44996','ExpandFlashLamp' => '44997','PixelFormat' => '48129','Transformation' => '48130','Uncompressed' => '48131','ImageType' => '48132','ImageWidth' => '48256','ImageHeight' => '48257','WidthResolution' => '48258','HeightResolution' => '48259','ImageOffset' => '48320','ImageByteCount' => '48321','AlphaOffset' => '48322','AlphaByteCount' => '48323','ImageDataDiscard' => '48324','AlphaDataDiscard' => '48325','OceScanjobDesc' => '50215','OceApplicationSelector' => '50216','OceIDNumber' => '50217','OceImageLogic' => '50218','Annotations' => '50255','PrintIM' => '50341','USPTOOriginalContentType' => '50560','DNGVersion' => '50706','DNGBackwardVersion' => '50707','UniqueCameraModel' => '50708','LocalizedCameraModel' => '50709','CFAPlaneColor' => '50710','CFALayout' => '50711','LinearizationTable' => '50712','BlackLevelRepeatDim' => '50713','BlackLevel' => '50714','BlackLevelDeltaH' => '50715','BlackLevelDeltaV' => '50716','WhiteLevel' => '50717','DefaultScale' => '50718','DefaultCropOrigin' => '50719','DefaultCropSize' => '50720','ColorMatrix1' => '50721','ColorMatrix2' => '50722','CameraCalibration1' => '50723','CameraCalibration2' => '50724','ReductionMatrix1' => '50725','ReductionMatrix2' => '50726','AnalogBalance' => '50727','AsShotNeutral' => '50728','AsShotWhiteXY' => '50729','BaselineExposure' => '50730','BaselineNoise' => '50731','BaselineSharpness' => '50732','BayerGreenSplit' => '50733','LinearResponseLimit' => '50734','CameraSerialNumber' => '50735','DNGLensInfo' => '50736','ChromaBlurRadius' => '50737','AntiAliasStrength' => '50738','ShadowScale' => '50739','SR2Private' => '50740','MakerNoteSafety' => '50741','RawImageSegmentation' => '50752','CalibrationIlluminant1' => '50778','CalibrationIlluminant2' => '50779','BestQualityScale' => '50780','RawDataUniqueID' => '50781','AliasLayerMetadata' => '50784','OriginalRawFileName' => '50827','OriginalRawFileData' => '50828','ActiveArea' => '50829','MaskedAreas' => '50830','AsShotICCProfile' => '50831','AsShotPreProfileMatrix' => '50832','CurrentICCProfile' => '50833','CurrentPreProfileMatrix' => '50834','ColorimetricReference' => '50879','PanasonicTitle' => '50898','PanasonicTitle2' => '50899','CameraCalibrationSig' => '50931','ProfileCalibrationSig' => '50932','ProfileIFD' => '50933','AsShotProfileName' => '50934','NoiseReductionApplied' => '50935','ProfileName' => '50936','ProfileHueSatMapDims' => '50937','ProfileHueSatMapData1' => '50938','ProfileHueSatMapData2' => '50939','ProfileToneCurve' => '50940','ProfileEmbedPolicy' => '50941','ProfileCopyright' => '50942','ForwardMatrix1' => '50964','ForwardMatrix2' => '50965','PreviewApplicationName' => '50966','PreviewApplicationVersion' => '50967','PreviewSettingsName' => '50968','PreviewSettingsDigest' => '50969','PreviewColorSpace' => '50970','PreviewDateTime' => '50971','RawImageDigest' => '50972','OriginalRawFileDigest' => '50973','SubTileBlockSize' => '50974','RowInterleaveFactor' => '50975','ProfileLookTableDims' => '50981','ProfileLookTableData' => '50982','OpcodeList1' => '51008','OpcodeList2' => '51009','OpcodeList3' => '51022','NoiseProfile' => '51041','Padding' => '59932','OffsetSchema' => '59933','OwnerName' => '65000','SerialNumber' => '65001','Lens' => '65002','KDC_IFD' => '65024','RawFile' => '65100','Converter' => '65101','WhiteBalance' => '65102','Exposure' => '65105','Shadows' => '65106','Brightness' => '65107','Contrast' => '65108','Saturation' => '65109','Sharpness' => '65110','Smoothness' => '65111','MoireFilter' => '65112',);public function extraireMetadonnees($cheminImage) {if ($this->peutUtiliserExifTool()) {$this->meta = $this->decoderMetadonneesExifTool($cheminImage);} else {$this->meta = $this->decoderMetadonneesBasique($cheminImage);}$metadonnees = array();$metadonnees['hauteur'] = $this->obtenirHauteur();$metadonnees['largeur'] = $this->obtenirLargeur();$metadonnees['date_prise_de_vue'] = $this->obtenirDatePriseDeVue();$metadonnees['appareil_fabriquant'] = $this->obtenirAppareilFabricant();$metadonnees['appareil_modele'] = $this->obtenirAppareilModele();$metadonnees['meta_exif'] = $this->convertirMetaVersXML('EXIF');$metadonnees['meta_iptc'] = $this->convertirMetaVersXML('IPTC');$metadonnees['meta_xmp'] = $this->convertirMetaVersXML('XMP');$metadonnees['meta_makernote'] = $this->convertirMetaVersXML('MAKERNOTE');return $metadonnees;}private function peutUtiliserExifTool() {// TODO indiquer ceci dans un fichier de configreturn file_exists('/usr/bin/exiftool') && is_executable('/usr/bin/exiftool');}private function decoderMetadonneesExifTool($cheminImage) {$metadata = array();$res = exec('/usr/bin/exiftool -g -D "'.$cheminImage.'"', $metadata);$metadata_decodees = array();$categorie = '';foreach($metadata as &$data) {if ($this->estUnSeparateurCategorieExifTool($data)) {$categorie = trim(str_replace('----', '', $data));} else {$data_decodee = $this->parserValeurMetadonneeExifTool($data);$cle_metadonnee = str_replace(' ', '', $data_decodee['cle']);$metadata_decodees[$categorie][$cle_metadonnee] = $data_decodee;}}return $metadata_decodees;}private function estUnSeparateurCategorieExifTool($data) {return preg_match('^---- (.)* ----^',$data);}private function parserValeurMetadonneeExifTool($data) {$cle_valeur = explode(':',$data,2);$valeur = '';if(count($cle_valeur) == 2) {$valeur = trim($cle_valeur[1]);}$id_cle = explode(' ',trim($cle_valeur[0]),2);$id_cle[1] = str_replace(array('-','/'),'',$id_cle[1]);$cle_id_valeur = array('cle' => $id_cle[1], 'id' => str_replace('-','',$id_cle[0]), 'valeur' => $valeur);return $cle_id_valeur;}public function decoderMetadonneesBasique($chemin_fichier) {$exif = @exif_read_data($chemin_fichier, "EXIF,COMPUTED,IFD0,FILE,COMMENT", true, false);// tant pis pour les makernote et xmp, les décoder demande trop de librairies externes, autant installer exiftool alors$metadonnees = array();$metadonnees['XMP'] = array();unset($metadonnees['EXIF']['MakerNote']);$metadonnees['MAKERNOTE'] = array();$metadonnees_non_formatees = array();if(isset($exif['EXIF'])) {$metadonnees_non_formatees = array_merge($metadonnees_non_formatees, $exif['EXIF']);}if(isset($exif['IFD0'])) {$metadonnees_non_formatees = array_merge($metadonnees_non_formatees, $exif['IFD0']);}$metadonnees['EXIF'] = $this->formaterTableauExif($metadonnees_non_formatees);$metadonnees['IPTC'] = $this->extraireIptc($chemin_fichier);$metadonnees['File'] = array('ImageWidth' => array('id' => '', 'valeur' => $exif['COMPUTED']['Width']),'ImageHeight' => array('id' => '', 'valeur' => $exif['COMPUTED']['Height']));return $metadonnees ;}private function formaterTableauExif(&$tableau) {$tableau_exif_formate = array();foreach ($tableau as $nom_tag => $valeur) {$id = '';if (isset($this->tableau_ids_tags_exif[$nom_tag])) {$id = $this->tableau_ids_tags_exif[$nom_tag];}$tableau_exif_formate[$nom_tag] = array('id' => $id, 'valeur' => $valeur);}return $tableau_exif_formate;}/*** Extraction des metadonnées iptc**/public function extraireIptc($chemin_fichier) {$meta = array();// getimagesize renvoie les infos iptc dans le tableau info$info = array();$size = getimagesize($chemin_fichier, $info);// s'il existeif (isset($info["APP13"])) {// on parse les donnees$iptc = iptcparse($info["APP13"]);if ($iptc) {// et on les analyseforeach ($iptc as $marker => $section) {foreach ($section as $nom => $val) {// pour remplir le tableau de donnees$this->decoderValeurIptc($marker, $val, $meta);}}}}return $meta;}/*** Stocke une valeur de metadonnées iptc dans le champ du tableau correspondant* @param String $nom nom de la valeur* @param String $val valeur* @param String $data référence vers le tableau où la donnée sera stockée**/private function decoderValeurIptc($nom, $val, &$data_tab) {switch ($nom) {case "2#005" :// mots cles iptc$data_tab['Category'] = array('id' => '5', 'valeur' => $val);break;case "2#080" :// champ by line$data_tab['By-Line'] = array('id' => '80', 'valeur' => $val);break ;case "2#085" :// champ by line titre$data_tab['By-LineTitle'] = array('id' => '85', 'valeur' => $val);break ;case "2#090" :// ville$data_tab['City'] = array('id' => '90', 'valeur' => $val);break ;case "2#092" :// sous location$data_tab['SubLocation'] = array('id' => '92', 'valeur' => $val);break ;case "2#095" :// etat (pour les us)$data_tab['ProvinceState'] = array('id' => '95', 'valeur' => $val);break ;case "2#100" :// code pays$data_tab['CountryPrimaryLocationCode'] = array('id' => '100', 'valeur' => $val);break ;case "2#101" :// code pays$data_tab['CountryName'] = array('id' => '101', 'valeur' => $val);break ;case "2#105" :// titre principal$data_tab['Headline'] = array('id' => '105', 'valeur' => $val);break ;case "2#110" :// credit$data_tab['Credit'] = array('id' => '110', 'valeur' => $val);break ;case "2#116" :// copyright$data_tab['CopyrightNotice'] = array('id' => '116', 'valeur' => $val);break ;case "2#118" :// contact$data_tab['Contact'] = array('id' => '118', 'valeur' => $val);break ;default:unset($data_tab['nom']);}}private function obtenirHauteur() {$hauteur = isset($this->meta['File']['ImageHeight']) ? $this->meta['File']['ImageHeight']['valeur'] : '';return $hauteur;}private function obtenirLargeur() {$largeur = isset($this->meta['File']['ImageWidth']) ? $this->meta['File']['ImageWidth']['valeur'] : '';return $largeur;}private function obtenirDatePriseDeVue() {$date = isset($this->meta['EXIF']['DateTimeOriginal']) ? $this->meta['EXIF']['DateTimeOriginal']['valeur'] : '';return $date;}private function obtenirAppareilFabricant() {$fabriquant = isset($this->meta['EXIF']['Make']) ? $this->meta['EXIF']['Make']['valeur'] : '';return $fabriquant;}private function obtenirAppareilModele() {$modele = isset($this->meta['EXIF']['CameraModelName']) ? $this->meta['EXIF']['CameraModelName']['valeur'] : '';return $modele;}private function convertirMetaVersXML($type) {$xml = null;if (isset($this->meta[$type])) {$racine = strtolower($type);$xml = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";$xml .= "<$racine>"."\n";foreach ($this->meta[$type] as $prop => &$valeur) {$xml .= '<'.$prop.' id="'.$valeur['id'].'">'.$valeur['valeur'].'</'.$prop.'>'."\n";}$xml .= "</$racine>";}return $xml;}}?>