⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.78
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-pear
/
pear
/
php
/
Horde
/
Image
/
Edit File: Exif.php
<?php /** * Copyright 2003-2017 Horde LLC (http://www.horde.org/) * * See the enclosed file LICENSE for license information (LGPL). If you * did not receive this file, see http://www.horde.org/licenses/lgpl21. * * @author Chuck Hagenbuch <chuck@horde.org> * @author Michael J. Rubinsky <mrubinsk@horde.org> * @category Horde * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1 * @package Image */ /** * General class for fetching and parsing EXIF information from images. * * Works equally well with either the built in php exif functions (if PHP * compiled with exif support), the Exiftool package (more complete but * slower), or the bundled exif library. * * @author Chuck Hagenbuch <chuck@horde.org> * @author Michael J. Rubinsky <mrubinsk@horde.org> * @category Horde * @copyright 2003-2017 Horde LLC * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1 * @package Image */ class Horde_Image_Exif { protected static $_titleFields = array( 'IPTC' => array('ObjectName'), 'XMP' => array('Title'), 'EXIF' => array(), 'COMPOSITE' => array() ); protected static $_descriptionFields = array( 'IPTC' => array('Caption-Abstract'), 'XMP' => array('Description'), 'EXIF' => array('ImageDescription'), 'COMPOSITE' => array() ); /** * Factory method for instantiating a Horde_Image_Exif object. * * @param string $driver * @param array $params * * @return Horde_Image_Exif */ public static function factory($driver = null, $params = array()) { if (empty($driver) && function_exists('exif_read_data')) { $driver = 'Php'; } elseif (empty($driver)) { $driver = 'Bundled'; } else { $driver = basename($driver); } $class = 'Horde_Image_Exif_' . $driver; return new $class($params); } /** * Converts from Intel to Motorola endien. * * Just reverses the bytes (assumes hex is passed in) * * @param string $intel * * @return string */ public static function intel2Moto($intel) { $len = strlen($intel); $moto = ''; for ($i = 0; $i <= $len; $i += 2) { $moto .= substr($intel, $len - $i, 2); } return $moto; } /** * Obtains an array of supported meta data fields. * * @TODO: This should probably be extended by the subclass? * * @return array */ public static function getCategories() { return array( 'IPTC' => array( 'Keywords' => array('description' => Horde_Image_Translation::t("Image keywords"), 'type' => 'array'), 'ObjectName' => array('description' => Horde_Image_Translation::t("Image Title"), 'type' => 'text'), 'By-line' => array('description' => Horde_Image_Translation::t("By"), 'type' => 'text'), 'CopyrightNotice' => array('description' => Horde_Image_Translation::t("Copyright"), 'type' => 'text'), 'Caption-Abstract' => array('description' => Horde_Image_Translation::t("Caption"), 'type' => 'text'), ), 'XMP' => array( 'Creator' => array('description' => Horde_Image_Translation::t("Image Creator"), 'type' => 'text'), 'Rights' => array('description' => Horde_Image_Translation::t("Rights"), 'type' => 'text'), 'UsageTerms' => array('description' => Horde_Image_Translation::t("Usage Terms"), 'type' => 'text'), 'Title' => array('description' => Horde_Image_Translation::t("Title"), 'type' => 'text'), 'Description' => array('description' => Horde_Image_Translation::t("Description"), 'type' => 'text'), ), 'EXIF' => array( 'DateTime' => array('description' => Horde_Image_Translation::t("Date Photo Modified"), 'type' => 'date'), 'DateTimeOriginal' => array('description' => Horde_Image_Translation::t("Date Photo Taken"), 'type' => 'date'), 'DateTimeDigitized' => array('description' => Horde_Image_Translation::t("Date Photo Digitized"), 'type' => 'date'), 'GPSLatitude' => array('description' => Horde_Image_Translation::t("Latitude"), 'type' => 'gps'), 'GPSLongitude' => array('description' => Horde_Image_Translation::t("Longitude"), 'type' => 'gps'), 'Make' => array('description' => Horde_Image_Translation::t("Camera Make"), 'type' => 'text'), 'Model' => array('description' => Horde_Image_Translation::t("Camera Model"), 'type' => 'text'), 'Software' => array('description' => Horde_Image_Translation::t("Software Version"), 'type' => 'text'), 'ImageType' => array('description' => Horde_Image_Translation::t("Photo Type"), 'type' => 'text'), 'ImageDescription' => array('description' => Horde_Image_Translation::t("Photo Description"), 'type' => 'text'), 'FileSize' => array('description' => Horde_Image_Translation::t("File Size"), 'type' => 'number'), 'ExifImageWidth' => array('description' => Horde_Image_Translation::t("Width"), 'type' => 'number'), 'ExifImageLength' => array('description' => Horde_Image_Translation::t("Height"), 'type' => 'number'), 'XResolution' => array('description' => Horde_Image_Translation::t("X Resolution"), 'type' => 'number'), 'YResolution' => array('description' => Horde_Image_Translation::t("Y Resolution"), 'type' => 'number'), 'ResolutionUnit' => array('description' => Horde_Image_Translation::t("Resolution Unit"), 'type' => 'text'), 'ShutterSpeedValue' => array('description' => Horde_Image_Translation::t("Shutter Speed"), 'type' => 'number'), 'ExposureTime' => array('description' => Horde_Image_Translation::t("Exposure"), 'type' => 'number'), 'FocalLength' => array('description' => Horde_Image_Translation::t("Focal Length"), 'type' => 'number'), 'FocalLengthIn35mmFilm' => array('description' => Horde_Image_Translation::t("Focal Length (35mm equiv)"), 'type' => 'number'), 'ApertureValue' => array('description' => Horde_Image_Translation::t("Aperture"), 'type' => 'number'), 'FNumber' => array('description' => Horde_Image_Translation::t("F-Number"), 'type' => 'number'), 'ISOSpeedRatings' => array('description' => Horde_Image_Translation::t("ISO Setting"), 'type' => 'number'), 'ExposureBiasValue' => array('description' => Horde_Image_Translation::t("Exposure Bias"), 'type' => 'number'), 'ExposureMode' => array('description' => Horde_Image_Translation::t("Exposure Mode"), 'type' => 'number'), 'ExposureProgram' => array('description' => Horde_Image_Translation::t("Exposure Program"), 'type' => 'number'), 'MeteringMode' => array('description' => Horde_Image_Translation::t("Metering Mode"), 'type' => 'number'), 'Flash' => array('description' => Horde_Image_Translation::t("Flash Setting"), 'type' => 'number'), 'UserComment' => array('description' => Horde_Image_Translation::t("User Comment"), 'type' => 'text'), 'ColorSpace' => array('description' => Horde_Image_Translation::t("Color Space"), 'type' => 'number'), 'SensingMethod' => array('description' => Horde_Image_Translation::t("Sensing Method"), 'type' => 'number'), 'WhiteBalance' => array('description' => Horde_Image_Translation::t("White Balance"), 'type' => 'number'), 'Orientation' => array('description' => Horde_Image_Translation::t("Camera Orientation"), 'type' => 'number'), 'Copyright' => array('description' => Horde_Image_Translation::t("Copyright"), 'type' => 'text'), 'Artist' => array('description' => Horde_Image_Translation::t("Artist"), 'type' => 'text'), 'LightSource' => array('description' => Horde_Image_Translation::t("Light source"), 'type' => 'number'), 'ImageStabalization' => array('description' => Horde_Image_Translation::t("Image Stabilization"), 'type' => 'text'), 'SceneCaptureType' => array('description' => Horde_Image_Translation::t("Scene Type"), 'type' => 'number'), ), 'COMPOSITE' => array( 'LensID' => array('description' => Horde_Image_Translation::t("Lens Id"), 'type' => 'text'), 'Lens' => array('description' => 'Lens', 'type' => 'text'), 'Aperture' => array('description' => Horde_Image_Translation::t("Aperture"), 'type' => 'text'), 'DOF' => array('description' => Horde_Image_Translation::t("Depth of Field"), 'type' => 'text'), 'FOV' => array('description' => Horde_Image_Translation::t("Field of View"), 'type' => 'text') ) ); } /** * Returns a list of metadata fields that can by used for image titles. * * @param mixed $driver A Horde_Image_Exif_Base instance or a string * specifying the driver in use. * * @return array An array of metadata field name hashes. * @since 2.1.0 */ public static function getTitleFields($driver = null) { if (!is_null($driver) && is_array($driver)) { $driver = self::factory($driver[0], $driver[1]); } if ($driver instanceof Horde_Image_Exif_Base) { $supported = $driver->supportedCategories(); } else { $supported = array('XMP', 'IPTC', 'EXIF'); } $fields = array(); foreach ($supported as $category) { $fields = array_merge($fields, self::$_titleFields[$category]); } $return = array(); $all = self::getFields($driver, true); foreach ($fields as $field) { $return[$field] = $all[$field]; } return $return; } /** * Returns a list of metadata fields that can by used for image * descriptions. * * @param mixed $driver A Horde_Image_Exif_Base instance or a string * specifying the driver in use. * * @return array An array of metadata field hashes. * @since 2.1.0 */ public static function getDescriptionFields($driver = null) { $map = self::getCategories(); if (!is_null($driver) && is_array($driver)) { $driver = self::factory($driver[0], $driver[1]); } if ($driver instanceof Horde_Image_Exif_Base) { $supported = $driver->supportedCategories(); } else { $supported = array('XMP', 'IPTC', 'EXIF'); } $fields = array(); foreach ($supported as $category) { $fields = array_merge($fields, self::$_descriptionFields[$category]); } $return = array(); $all = self::getFields($driver, true); foreach ($fields as $field) { $return[$field] = $all[$field]; } return $return; } /** * Returns a flattened array of supported metadata fields. * * @param mixed $driver A Horde_Image_Exif_Base instance or a * string specifying the driver in use. * @param boolean $description_only Only return the field descriptions. * * @return array */ public static function getFields($driver = null, $description_only = false) { if (!is_null($driver) && is_array($driver)) { $driver = self::factory($driver[0], $driver[1]); } if ($driver instanceof Horde_Image_Exif_Base) { $supported = $driver->supportedCategories(); } else { $supported = array('XMP', 'IPTC', 'EXIF' ); } $categories = self::getCategories(); $flattened = array(); foreach ($supported as $category) { $flattened = array_merge($flattened, $categories[$category]); } if ($description_only) { foreach ($flattened as $key => $data) { $return[$key] = $data['description']; } return $return; } return $flattened; } /** * More human friendly exposure formatting. */ protected static function _formatExposure($data) { if ($data > 0) { if ($data > 1) { return sprintf( Horde_Image_Translation::t("%d sec"), round($data, 2) ); } else { $n = $d = 0; self::_convertToFraction($data, $n, $d); if ($n <> 1) { return sprintf( Horde_Image_Translation::t("%4f sec"), $n / $d ); } return sprintf( Horde_Image_Translation::t("%s / %s sec"), $n, $d ); } } else { return Horde_Image_Translation::t("Bulb"); } } /** * Converts a floating point number into a fraction. * * Many thanks to Matthieu Froment for this code. * * (Ported from the Exifer library). */ protected static function _convertToFraction($v, &$n, &$d) { $MaxTerms = 15; // Limit to prevent infinite loop $MinDivisor = 0.000001; // Limit to prevent divide by zero $MaxError = 0.00000001; // How close is enough // Initialize fraction being converted $f = $v; // Initialize fractions with 1/0, 0/1 $n_un = 1; $d_un = 0; $n_deux = 0; $d_deux = 1; for ($i = 0; $i < $MaxTerms; $i++) { $a = floor($f); // Get next term $f = $f - $a; // Get new divisor $n = $n_un * $a + $n_deux; // Calculate new fraction $d = $d_un * $a + $d_deux; $n_deux = $n_un; // Save last two fractions $d_deux = $d_un; $n_un = $n; $d_un = $d; // Quit if dividing by zero if ($f < $MinDivisor) { break; } if (abs($v - $n / $d) < $MaxError) { break; } // reciprocal $f = 1 / $f; } } /** * Converts an exif field into human-readable form. * * Some of these cases are ported from the Exifer library, others were * changed from their implementation where the EXIF standard dictated * different behaviour. * * @param string $field The name of the field to translate. * @param string $data The data value to translate. * * @return string The converted data. */ public static function getHumanReadable($field, $data) { switch ($field) { case 'ExposureMode': switch ($data) { case 0: return Horde_Image_Translation::t("Auto exposure"); case 1: return Horde_Image_Translation::t("Manual exposure"); case 2: return Horde_Image_Translation::t("Auto bracket"); default: return Horde_Image_Translation::t("Unknown"); } case 'ExposureProgram': switch ($data) { case 1: return Horde_Image_Translation::t("Manual"); case 2: return Horde_Image_Translation::t("Normal Program"); case 3: return Horde_Image_Translation::t("Aperture Priority"); case 4: return Horde_Image_Translation::t("Shutter Priority"); case 5: return Horde_Image_Translation::t("Creative"); case 6: return Horde_Image_Translation::t("Action"); case 7: return Horde_Image_Translation::t("Portrait"); case 8: return Horde_Image_Translation::t("Landscape"); default: return Horde_Image_Translation::t("Unknown"); } case 'XResolution': case 'YResolution': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); return sprintf(Horde_Image_Translation::t("%d dots per unit"), $n); } return sprintf(Horde_Image_Translation::t("%d per unit"), $data); case 'ResolutionUnit': switch ($data) { case 1: return Horde_Image_Translation::t("Pixels"); case 2: return Horde_Image_Translation::t("Inch"); case 3: return Horde_Image_Translation::t("Centimeter"); default: return Horde_Image_Translation::t("Unknown"); } case 'ExifImageWidth': case 'ExifImageLength': return sprintf(Horde_Image_Translation::t("%d pixels"), $data); case 'Orientation': switch ($data) { case 1: return sprintf(Horde_Image_Translation::t("Normal (O deg)")); case 2: return sprintf(Horde_Image_Translation::t("Mirrored")); case 3: return sprintf(Horde_Image_Translation::t("Upsidedown")); case 4: return sprintf(Horde_Image_Translation::t("Upsidedown Mirrored")); case 5: return sprintf(Horde_Image_Translation::t("90 deg CW Mirrored")); case 6: return sprintf(Horde_Image_Translation::t("90 deg CCW")); case 7: return sprintf(Horde_Image_Translation::t("90 deg CCW Mirrored")); case 8: return sprintf(Horde_Image_Translation::t("90 deg CW")); } break; case 'ExposureTime': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); if ($d == 0) { return; } $data = $n / $d; } return self::_formatExposure($data); case 'ShutterSpeedValue': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); if ($d == 0) { return; } $data = $n / $d; } $data = exp($data * log(2)); if ($data > 0) { $data = 1 / $data; } return self::_formatExposure($data); case 'ApertureValue': case 'MaxApertureValue': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); if ($d == 0) { return; } $data = $n / $d; $data = exp(($data * log(2)) / 2); // Precision is 1 digit. $data = round($data, 1); } return 'f/' . $data; case 'FocalLength': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); if ($d == 0) { return; } return sprintf(Horde_Image_Translation::t("%d mm"), round($n / $d)); } return sprintf(Horde_Image_Translation::t("%d mm"), $data); case 'FNumber': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); if ($d != 0) { return 'f/' . round($n / $d, 1); } } return 'f/' . $data; case 'ExposureBiasValue': if (strpos($data, '/') !== false) { list($n, $d) = explode('/', $data, 2); if ($n == 0) { return '0 EV'; } } return $data . ' EV'; case 'MeteringMode': switch ($data) { case 0: return Horde_Image_Translation::t("Unknown"); case 1: return Horde_Image_Translation::t("Average"); case 2: return Horde_Image_Translation::t("Center Weighted Average"); case 3: return Horde_Image_Translation::t("Spot"); case 4: return Horde_Image_Translation::t("Multi-Spot"); case 5: return Horde_Image_Translation::t("Multi-Segment"); case 6: return Horde_Image_Translation::t("Partial"); case 255: return Horde_Image_Translation::t("Other"); default: return sprintf(Horde_Image_Translation::t("Unknown: %s"), $data); } break; case 'LightSource': switch ($data) { case 1: return Horde_Image_Translation::t("Daylight"); case 2: return Horde_Image_Translation::t("Fluorescent"); case 3: return Horde_Image_Translation::t("Tungsten"); case 4: return Horde_Image_Translation::t("Flash"); case 9: return Horde_Image_Translation::t("Fine weather"); case 10: return Horde_Image_Translation::t("Cloudy weather"); case 11: return Horde_Image_Translation::t("Shade"); case 12: return Horde_Image_Translation::t("Daylight fluorescent"); case 13: return Horde_Image_Translation::t("Day white fluorescent"); case 14: return Horde_Image_Translation::t("Cool white fluorescent"); case 15: return Horde_Image_Translation::t("White fluorescent"); case 17: return Horde_Image_Translation::t("Standard light A"); case 18: return Horde_Image_Translation::t("Standard light B"); case 19: return Horde_Image_Translation::t("Standard light C"); case 20: return 'D55'; case 21: return 'D65'; case 22: return 'D75'; case 23: return 'D50'; case 24: return Horde_Image_Translation::t("ISO studio tungsten"); case 255: return Horde_Image_Translation::t("other light source"); default: return Horde_Image_Translation::t("Unknown"); } case 'WhiteBalance': switch ($data) { case 0: return Horde_Image_Translation::t("Auto"); case 1: return Horde_Image_Translation::t("Manual"); default: Horde_Image_Translation::t("Unknown"); } break; case 'FocalLengthIn35mmFilm': return $data . ' mm'; case 'Flash': switch ($data) { case 0: return Horde_Image_Translation::t("No Flash"); case 1: return Horde_Image_Translation::t("Flash"); case 5: return Horde_Image_Translation::t("Flash, strobe return light not detected"); case 7: return Horde_Image_Translation::t("Flash, strobe return light detected"); case 9: return Horde_Image_Translation::t("Compulsory Flash"); case 13: return Horde_Image_Translation::t("Compulsory Flash, Return light not detected"); case 15: return Horde_Image_Translation::t("Compulsory Flash, Return light detected"); case 16: return Horde_Image_Translation::t("No Flash"); case 24: return Horde_Image_Translation::t("No Flash"); case 25: return Horde_Image_Translation::t("Flash, Auto-Mode"); case 29: return Horde_Image_Translation::t("Flash, Auto-Mode, Return light not detected"); case 31: return Horde_Image_Translation::t("Flash, Auto-Mode, Return light detected"); case 32: return Horde_Image_Translation::t("No Flash"); case 65: return Horde_Image_Translation::t("Red Eye"); case 69: return Horde_Image_Translation::t("Red Eye, Return light not detected"); case 71: return Horde_Image_Translation::t("Red Eye, Return light detected"); case 73: return Horde_Image_Translation::t("Red Eye, Compulsory Flash"); case 77: return Horde_Image_Translation::t("Red Eye, Compulsory Flash, Return light not detected"); case 79: return Horde_Image_Translation::t("Red Eye, Compulsory Flash, Return light detected"); case 89: return Horde_Image_Translation::t("Red Eye, Auto-Mode"); case 93: return Horde_Image_Translation::t("Red Eye, Auto-Mode, Return light not detected"); case 95: return Horde_Image_Translation::t("Red Eye, Auto-Mode, Return light detected"); } break; case 'FileSize': if ($data <= 0) { return '0 Bytes'; } $s = array('B', 'kB', 'MB', 'GB'); $e = floor(log($data, 1024)); return round($data/pow(1024, $e), 2) . ' ' . $s[$e]; case 'SensingMethod': switch ($data) { case 1: return Horde_Image_Translation::t("Not defined"); case 2: return Horde_Image_Translation::t("One Chip Color Area Sensor"); case 3: return Horde_Image_Translation::t("Two Chip Color Area Sensor"); case 4: return Horde_Image_Translation::t("Three Chip Color Area Sensor"); case 5: return Horde_Image_Translation::t("Color Sequential Area Sensor"); case 7: return Horde_Image_Translation::t("Trilinear Sensor"); case 8: return Horde_Image_Translation::t("Color Sequential Linear Sensor"); default: return Horde_Image_Translation::t("Unknown"); } case 'ColorSpace': switch ($data) { case 1: return Horde_Image_Translation::t("sRGB"); default: return Horde_Image_Translation::t("Uncalibrated"); } case 'SceneCaptureType': switch ($data) { case 0: return Horde_Image_Translation::t("Standard"); case 1: return Horde_Image_Translation::t("Landscape"); case 2: return Horde_Image_Translation::t("Portrait"); case 3: return Horde_Image_Translation::t("Night Scene"); default: return Horde_Image_Translation::t("Unknown"); } case 'DateTime': case 'DateTimeOriginal': case 'DateTimeDigitized': return date('m/d/Y H:i:s O', $data); case 'UserComment': //@TODO: the first 8 bytes of this field contain the charset used // to encode the comment. Either ASCII, JIS, UNICODE, or // UNDEFINED. Should probably either convert to a known charset // here and let the calling code deal with it, or allow this // method to take an optional charset to convert to (would // introduce a dependency on Horde_String to do the conversion). $data = trim(substr($data, 7)) ; default: return !empty($data) ? $data : '---'; } } }
Simpan