Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ composer.phar
.DS_Store
.idea
.phpunit.result.cache
.phpunit.cache
coverage.xml
infection.html
# Otherwise we won't be able to install it on different php version.
composer.lock
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"lychee-org/phpstan-lychee": "^2.0.1|^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpmd/phpmd": "^2.15",
"phpunit/phpunit": "^9.5.10",
"phpunit/phpunit": "^11.5 || ^12.0 || ^13.0",
"squizlabs/php_codesniffer": "^3.9",
"thecodingmachine/phpstan-safe-rule": "^1.2"
},
Expand All @@ -65,6 +65,7 @@
"vendor/bin/phpcs --standard=PSR2 ./lib/"
],
"run-tests": [
"@putenv XDEBUG_MODE=coverage",
"vendor/bin/phpunit -c phpunit.xml.dist",
"vendor/bin/phpunit --coverage-clover=coverage.xml"
],
Expand Down
314 changes: 314 additions & 0 deletions lib/PHPExif/Exif.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,21 @@ class Exif
public const COUNTRY = 'country';
public const CREATION_DATE = 'creationdate';
public const CREDIT = 'credit';
public const CROPPEDAREAIMAGEHEIGHTPIXELS = 'CroppedAreaImageHeightPixels';
public const CROPPEDAREAIMAGEWIDTHPIXELS = 'CroppedAreaImageWidthPixels';
public const CROPPEDAREALEFTPIXELS = 'CroppedAreaLeftPixels';
public const CROPPEDAREATOPPIXELS = 'CroppedAreaTopPixels';
public const DESCRIPTION = 'description';
public const DURATION = 'duration';
public const EXPOSURE = 'exposure';
public const EXPOSURE_BIAS = 'exposureBias';
public const FILESIZE = 'FileSize';
public const FILENAME = 'FileName';
public const FOCAL_LENGTH = 'focalLength';
public const FOCAL_DISTANCE = 'focalDistance';
public const FRAMERATE = 'framerate';
public const FULLPANOHEIGHTPIXELS = 'FullPanoHeightPixels';
public const FULLPANOWIDTHPIXELS = 'FullPanoWidthPixels';
public const GPS = 'gps';
public const HEADLINE = 'headline';
public const HEIGHT = 'height';
Expand All @@ -49,12 +56,16 @@ class Exif
public const MICROVIDEOOFFSET = 'MicroVideoOffset';
public const MIMETYPE = 'MimeType';
public const ORIENTATION = 'Orientation';
public const PROJECTIONTYPE = 'ProjectionType';
public const SOFTWARE = 'software';
public const SOURCE = 'source';
public const STATE = 'state';
public const SUBLOCATION = 'Sublocation';
public const TITLE = 'title';
public const USEPANORAMAVIEWER = 'UsePanoramaViewer';
public const VERTICAL_RESOLUTION = 'verticalResolution';
public const WHITE_BALANCE = 'whiteBalance';
public const WHITE_BALANCE_TEMPERATURE = 'whiteBalanceTemperature';
public const WIDTH = 'width';


Expand Down Expand Up @@ -341,6 +352,91 @@ public function setExposure(string $value): Exif
return $this;
}

/**
* Returns the exposure bias (exposure compensation) in EV, if it exists
* e.g. -0.67 for -2/3 EV
*
* @return float|false
*/
public function getExposureBias(): float|false
{
if (!isset($this->data[self::EXPOSURE_BIAS])) {
return false;
}

return $this->data[self::EXPOSURE_BIAS];
}

/**
* Sets the exposure bias (exposure compensation) in EV
*
* @param float $value
* @return Exif
*/
public function setExposureBias(float $value): Exif
{
$this->data[self::EXPOSURE_BIAS] = $value;

return $this;
}

/**
* Returns the EXIF white balance mode, if it exists
* 0 = auto, 1 = manual
*
* @return int|false
*/
public function getWhiteBalance(): int|false
{
if (!isset($this->data[self::WHITE_BALANCE])) {
return false;
}

return $this->data[self::WHITE_BALANCE];
}

/**
* Sets the EXIF white balance mode (0 = auto, 1 = manual)
*
* @param int $value
* @return Exif
*/
public function setWhiteBalance(int $value): Exif
{
$this->data[self::WHITE_BALANCE] = $value;

return $this;
}

/**
* Returns the white balance colour temperature in Kelvin, if it exists.
* Only the exiftool adapter provides it, as it comes from the maker notes
* (or Lightroom's XMP-crs data).
*
* @return int|false
*/
public function getWhiteBalanceTemperature(): int|false
{
if (!isset($this->data[self::WHITE_BALANCE_TEMPERATURE])) {
return false;
}

return $this->data[self::WHITE_BALANCE_TEMPERATURE];
}

/**
* Sets the white balance colour temperature in Kelvin
*
* @param int $value
* @return Exif
*/
public function setWhiteBalanceTemperature(int $value): Exif
{
$this->data[self::WHITE_BALANCE_TEMPERATURE] = $value;

return $this;
}

/**
* Returns the Exposure
*
Expand Down Expand Up @@ -1174,6 +1270,224 @@ public function getMicroVideoOffset(): string|false
return $this->data[self::MICROVIDEOOFFSET];
}

/**
* Sets the GPano projection type (lower-cased by the mappers)
*
* @param string $value
* @return Exif
*/
public function setProjectionType(string $value): Exif
{
$this->data[self::PROJECTIONTYPE] = $value;

return $this;
}

/**
* Returns the GPano projection type, if it exists
* e.g. "equirectangular" for a photo sphere
*
* @return string|false
*/
public function getProjectionType(): string|false
{
if (!isset($this->data[self::PROJECTIONTYPE])) {
return false;
}

return $this->data[self::PROJECTIONTYPE];
}

/**
* Sets the GPano UsePanoramaViewer flag
*
* @param bool $value
* @return Exif
*/
public function setUsePanoramaViewer(bool $value): Exif
{
$this->data[self::USEPANORAMAVIEWER] = $value;

return $this;
}

/**
* Returns the GPano UsePanoramaViewer flag, or null if it does not exist.
* Unlike the other getters, false is a meaningful value here.
*
* @return bool|null
*/
public function getUsePanoramaViewer(): ?bool
{
if (!isset($this->data[self::USEPANORAMAVIEWER])) {
return null;
}

return $this->data[self::USEPANORAMAVIEWER];
}

/**
* Sets the GPano full panorama width, in pixels
*
* @param int $value
* @return Exif
*/
public function setFullPanoWidthPixels(int $value): Exif
{
$this->data[self::FULLPANOWIDTHPIXELS] = $value;

return $this;
}

/**
* Returns the GPano full panorama width, in pixels, if it exists
*
* @return int|false
*/
public function getFullPanoWidthPixels(): int|false
{
if (!isset($this->data[self::FULLPANOWIDTHPIXELS])) {
return false;
}

return $this->data[self::FULLPANOWIDTHPIXELS];
}

/**
* Sets the GPano full panorama height, in pixels
*
* @param int $value
* @return Exif
*/
public function setFullPanoHeightPixels(int $value): Exif
{
$this->data[self::FULLPANOHEIGHTPIXELS] = $value;

return $this;
}

/**
* Returns the GPano full panorama height, in pixels, if it exists
*
* @return int|false
*/
public function getFullPanoHeightPixels(): int|false
{
if (!isset($this->data[self::FULLPANOHEIGHTPIXELS])) {
return false;
}

return $this->data[self::FULLPANOHEIGHTPIXELS];
}

/**
* Sets the GPano left offset of the cropped area, in pixels
*
* @param int $value
* @return Exif
*/
public function setCroppedAreaLeftPixels(int $value): Exif
{
$this->data[self::CROPPEDAREALEFTPIXELS] = $value;

return $this;
}

/**
* Returns the GPano left offset of the cropped area, in pixels, if it exists
*
* @return int|false
*/
public function getCroppedAreaLeftPixels(): int|false
{
if (!isset($this->data[self::CROPPEDAREALEFTPIXELS])) {
return false;
}

return $this->data[self::CROPPEDAREALEFTPIXELS];
}

/**
* Sets the GPano top offset of the cropped area, in pixels
*
* @param int $value
* @return Exif
*/
public function setCroppedAreaTopPixels(int $value): Exif
{
$this->data[self::CROPPEDAREATOPPIXELS] = $value;

return $this;
}

/**
* Returns the GPano top offset of the cropped area, in pixels, if it exists
*
* @return int|false
*/
public function getCroppedAreaTopPixels(): int|false
{
if (!isset($this->data[self::CROPPEDAREATOPPIXELS])) {
return false;
}

return $this->data[self::CROPPEDAREATOPPIXELS];
}

/**
* Sets the GPano cropped area width, in pixels
*
* @param int $value
* @return Exif
*/
public function setCroppedAreaImageWidthPixels(int $value): Exif
{
$this->data[self::CROPPEDAREAIMAGEWIDTHPIXELS] = $value;

return $this;
}

/**
* Returns the GPano cropped area width, in pixels, if it exists
*
* @return int|false
*/
public function getCroppedAreaImageWidthPixels(): int|false
{
if (!isset($this->data[self::CROPPEDAREAIMAGEWIDTHPIXELS])) {
return false;
}

return $this->data[self::CROPPEDAREAIMAGEWIDTHPIXELS];
}

/**
* Sets the GPano cropped area height, in pixels
*
* @param int $value
* @return Exif
*/
public function setCroppedAreaImageHeightPixels(int $value): Exif
{
$this->data[self::CROPPEDAREAIMAGEHEIGHTPIXELS] = $value;

return $this;
}

/**
* Returns the GPano cropped area height, in pixels, if it exists
*
* @return int|false
*/
public function getCroppedAreaImageHeightPixels(): int|false
{
if (!isset($this->data[self::CROPPEDAREAIMAGEHEIGHTPIXELS])) {
return false;
}

return $this->data[self::CROPPEDAREAIMAGEHEIGHTPIXELS];
}

/**
* Sets the sublocation value
*
Expand Down
Loading
Loading