599 lines
18 KiB
PHP
599 lines
18 KiB
PHP
<?php
|
|
|
|
/* PEL: PHP Exif Library. A library with support for reading and
|
|
* writing all Exif headers in JPEG and TIFF images using PHP.
|
|
*
|
|
* Copyright (C) 2004, 2005, 2006 Martin Geisler.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program in the file COPYING; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/* $Id: PelEntryShort.php 419 2006-02-20 16:22:36Z mgeisler $ */
|
|
|
|
|
|
/**
|
|
* Classes used to hold shorts, both signed and unsigned.
|
|
*
|
|
* @author Martin Geisler <mgeisler@users.sourceforge.net>
|
|
* @version $Revision: 419 $
|
|
* @date $Date: 2006-02-20 17:22:36 +0100 (Mon, 20 Feb 2006) $
|
|
* @license http://www.gnu.org/licenses/gpl.html GNU General Public
|
|
* License (GPL)
|
|
* @package PEL
|
|
*/
|
|
|
|
/**#@+ Required class definitions. */
|
|
require_once('PelEntryNumber.php');
|
|
require_once('PelConvert.php');
|
|
require_once('Pel.php');
|
|
/**#@-*/
|
|
|
|
|
|
/**
|
|
* Class for holding signed shorts.
|
|
*
|
|
* This class can hold shorts, either just a single short or an array
|
|
* of shorts. The class will be used to manipulate any of the Exif
|
|
* tags which has format {@link PelFormat::SHORT} like in this
|
|
* example:
|
|
*
|
|
* <code>
|
|
* $w = $ifd->getEntry(PelTag::EXIF_IMAGE_WIDTH);
|
|
* $w->setValue($w->getValue() / 2);
|
|
* $h = $ifd->getEntry(PelTag::EXIF_IMAGE_HEIGHT);
|
|
* $h->setValue($h->getValue() / 2);
|
|
* </code>
|
|
*
|
|
* Here the width and height is updated to 50% of their original
|
|
* values.
|
|
*
|
|
* @author Martin Geisler <mgeisler@users.sourceforge.net>
|
|
* @package PEL
|
|
*/
|
|
class PelEntryShort extends PelEntryNumber {
|
|
|
|
/**
|
|
* Make a new entry that can hold an unsigned short.
|
|
*
|
|
* The method accept several integer arguments. The {@link
|
|
* getValue} method will always return an array except for when a
|
|
* single integer argument is given here.
|
|
*
|
|
* This means that one can conveniently use objects like this:
|
|
* <code>
|
|
* $a = new PelEntryShort(PelTag::EXIF_IMAGE_HEIGHT, 42);
|
|
* $b = $a->getValue() + 314;
|
|
* </code>
|
|
* where the call to {@link getValue} will return an integer
|
|
* instead of an array with one integer element, which would then
|
|
* have to be extracted.
|
|
*
|
|
* @param PelTag the tag which this entry represents. This should be
|
|
* one of the constants defined in {@link PelTag}, e.g., {@link
|
|
* PelTag::IMAGE_WIDTH}, {@link PelTag::ISO_SPEED_RATINGS},
|
|
* or any other tag with format {@link PelFormat::SHORT}.
|
|
*
|
|
* @param int $value... the short(s) that this entry will
|
|
* represent. The argument passed must obey the same rules as the
|
|
* argument to {@link setValue}, namely that it should be within
|
|
* range of an unsigned short, that is between 0 and 65535
|
|
* (inclusive). If not, then a {@link PelOverFlowException} will be
|
|
* thrown.
|
|
*/
|
|
function __construct($tag /* $value... */) {
|
|
$this->tag = $tag;
|
|
$this->min = 0;
|
|
$this->max = 65535;
|
|
$this->format = PelFormat::SHORT;
|
|
|
|
$value = func_get_args();
|
|
array_shift($value);
|
|
$this->setValueArray($value);
|
|
}
|
|
|
|
|
|
/**
|
|
* Convert a number into bytes.
|
|
*
|
|
* @param int the number that should be converted.
|
|
*
|
|
* @param PelByteOrder one of {@link PelConvert::LITTLE_ENDIAN} and
|
|
* {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
|
|
*
|
|
* @return string bytes representing the number given.
|
|
*/
|
|
function numberToBytes($number, $order) {
|
|
return PelConvert::shortToBytes($number, $order);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the value of an entry as text.
|
|
*
|
|
* The value will be returned in a format suitable for presentation,
|
|
* e.g., instead of returning '2' for a {@link
|
|
* PelTag::METERING_MODE} tag, 'Center-Weighted Average' is
|
|
* returned.
|
|
*
|
|
* @param boolean some values can be returned in a long or more
|
|
* brief form, and this parameter controls that.
|
|
*
|
|
* @return string the value as text.
|
|
*/
|
|
function getText($brief = false) {
|
|
switch ($this->tag) {
|
|
case PelTag::METERING_MODE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Unknown');
|
|
case 1:
|
|
return Pel::tra('Average');
|
|
case 2:
|
|
return Pel::tra('Center-Weighted Average');
|
|
case 3:
|
|
return Pel::tra('Spot');
|
|
case 4:
|
|
return Pel::tra('Multi Spot');
|
|
case 5:
|
|
return Pel::tra('Pattern');
|
|
case 6:
|
|
return Pel::tra('Partial');
|
|
case 255:
|
|
return Pel::tra('Other');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::COMPRESSION:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 1:
|
|
return Pel::tra('Uncompressed');
|
|
case 6:
|
|
return Pel::tra('JPEG compression');
|
|
default:
|
|
return $this->value[0];
|
|
|
|
}
|
|
|
|
case PelTag::PLANAR_CONFIGURATION:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 1:
|
|
return Pel::tra('chunky format');
|
|
case 2:
|
|
return Pel::tra('planar format');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::SENSING_METHOD:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 1:
|
|
return Pel::tra('Not defined');
|
|
case 2:
|
|
return Pel::tra('One-chip color area sensor');
|
|
case 3:
|
|
return Pel::tra('Two-chip color area sensor');
|
|
case 4:
|
|
return Pel::tra('Three-chip color area sensor');
|
|
case 5:
|
|
return Pel::tra('Color sequential area sensor');
|
|
case 7:
|
|
return Pel::tra('Trilinear sensor');
|
|
case 8:
|
|
return Pel::tra('Color sequential linear sensor');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::LIGHT_SOURCE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Unknown');
|
|
case 1:
|
|
return Pel::tra('Daylight');
|
|
case 2:
|
|
return Pel::tra('Fluorescent');
|
|
case 3:
|
|
return Pel::tra('Tungsten (incandescent light)');
|
|
case 4:
|
|
return Pel::tra('Flash');
|
|
case 9:
|
|
return Pel::tra('Fine weather');
|
|
case 10:
|
|
return Pel::tra('Cloudy weather');
|
|
case 11:
|
|
return Pel::tra('Shade');
|
|
case 12:
|
|
return Pel::tra('Daylight fluorescent');
|
|
case 13:
|
|
return Pel::tra('Day white fluorescent');
|
|
case 14:
|
|
return Pel::tra('Cool white fluorescent');
|
|
case 15:
|
|
return Pel::tra('White fluorescent');
|
|
case 17:
|
|
return Pel::tra('Standard light A');
|
|
case 18:
|
|
return Pel::tra('Standard light B');
|
|
case 19:
|
|
return Pel::tra('Standard light C');
|
|
case 20:
|
|
return Pel::tra('D55');
|
|
case 21:
|
|
return Pel::tra('D65');
|
|
case 22:
|
|
return Pel::tra('D75');
|
|
case 24:
|
|
return Pel::tra('ISO studio tungsten');
|
|
case 255:
|
|
return Pel::tra('Other');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::FOCAL_PLANE_RESOLUTION_UNIT:
|
|
case PelTag::RESOLUTION_UNIT:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 2:
|
|
return Pel::tra('Inch');
|
|
case 3:
|
|
return Pel::tra('Centimeter');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::EXPOSURE_PROGRAM:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Not defined');
|
|
case 1:
|
|
return Pel::tra('Manual');
|
|
case 2:
|
|
return Pel::tra('Normal program');
|
|
case 3:
|
|
return Pel::tra('Aperture priority');
|
|
case 4:
|
|
return Pel::tra('Shutter priority');
|
|
case 5:
|
|
return Pel::tra('Creative program (biased toward depth of field)');
|
|
case 6:
|
|
return Pel::tra('Action program (biased toward fast shutter speed)');
|
|
case 7:
|
|
return Pel::tra('Portrait mode (for closeup photos with the background out of focus');
|
|
case 8:
|
|
return Pel::tra('Landscape mode (for landscape photos with the background in focus');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::ORIENTATION:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 1:
|
|
return Pel::tra('top - left');
|
|
case 2:
|
|
return Pel::tra('top - right');
|
|
case 3:
|
|
return Pel::tra('bottom - right');
|
|
case 4:
|
|
return Pel::tra('bottom - left');
|
|
case 5:
|
|
return Pel::tra('left - top');
|
|
case 6:
|
|
return Pel::tra('right - top');
|
|
case 7:
|
|
return Pel::tra('right - bottom');
|
|
case 8:
|
|
return Pel::tra('left - bottom');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::YCBCR_POSITIONING:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 1:
|
|
return Pel::tra('centered');
|
|
case 2:
|
|
return Pel::tra('co-sited');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::YCBCR_SUB_SAMPLING:
|
|
//CC (e->components, 2, v);
|
|
if ($this->value[0] == 2 && $this->value[1] == 1)
|
|
return 'YCbCr4:2:2';
|
|
if ($this->value[0] == 2 && $this->value[1] == 2)
|
|
return 'YCbCr4:2:0';
|
|
|
|
return $this->value[0] . ', ' . $this->value[1];
|
|
|
|
case PelTag::PHOTOMETRIC_INTERPRETATION:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 2:
|
|
return 'RGB';
|
|
case 6:
|
|
return 'YCbCr';
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::COLOR_SPACE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 1:
|
|
return 'sRGB';
|
|
case 2:
|
|
return 'Adobe RGB';
|
|
case 0xffff:
|
|
return Pel::tra('Uncalibrated');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::FLASH:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0x0000:
|
|
return Pel::tra('Flash did not fire.');
|
|
case 0x0001:
|
|
return Pel::tra('Flash fired.');
|
|
case 0x0005:
|
|
return Pel::tra('Strobe return light not detected.');
|
|
case 0x0007:
|
|
return Pel::tra('Strobe return light detected.');
|
|
case 0x0009:
|
|
return Pel::tra('Flash fired, compulsory flash mode.');
|
|
case 0x000d:
|
|
return Pel::tra('Flash fired, compulsory flash mode, return light not detected.');
|
|
case 0x000f:
|
|
return Pel::tra('Flash fired, compulsory flash mode, return light detected.');
|
|
case 0x0010:
|
|
return Pel::tra('Flash did not fire, compulsory flash mode.');
|
|
case 0x0018:
|
|
return Pel::tra('Flash did not fire, auto mode.');
|
|
case 0x0019:
|
|
return Pel::tra('Flash fired, auto mode.');
|
|
case 0x001d:
|
|
return Pel::tra('Flash fired, auto mode, return light not detected.');
|
|
case 0x001f:
|
|
return Pel::tra('Flash fired, auto mode, return light detected.');
|
|
case 0x0020:
|
|
return Pel::tra('No flash function.');
|
|
case 0x0041:
|
|
return Pel::tra('Flash fired, red-eye reduction mode.');
|
|
case 0x0045:
|
|
return Pel::tra('Flash fired, red-eye reduction mode, return light not detected.');
|
|
case 0x0047:
|
|
return Pel::tra('Flash fired, red-eye reduction mode, return light detected.');
|
|
case 0x0049:
|
|
return Pel::tra('Flash fired, compulsory flash mode, red-eye reduction mode.');
|
|
case 0x004d:
|
|
return Pel::tra('Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected.');
|
|
case 0x004f:
|
|
return Pel::tra('Flash fired, compulsory flash mode, red-eye reduction mode, return light detected.');
|
|
case 0x0058:
|
|
return Pel::tra('Flash did not fire, auto mode, red-eye reduction mode.');
|
|
case 0x0059:
|
|
return Pel::tra('Flash fired, auto mode, red-eye reduction mode.');
|
|
case 0x005d:
|
|
return Pel::tra('Flash fired, auto mode, return light not detected, red-eye reduction mode.');
|
|
case 0x005f:
|
|
return Pel::tra('Flash fired, auto mode, return light detected, red-eye reduction mode.');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::CUSTOM_RENDERED:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Normal process');
|
|
case 1:
|
|
return Pel::tra('Custom process');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::EXPOSURE_MODE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Auto exposure');
|
|
case 1:
|
|
return Pel::tra('Manual exposure');
|
|
case 2:
|
|
return Pel::tra('Auto bracket');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::WHITE_BALANCE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Auto white balance');
|
|
case 1:
|
|
return Pel::tra('Manual white balance');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::SCENE_CAPTURE_TYPE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Standard');
|
|
case 1:
|
|
return Pel::tra('Landscape');
|
|
case 2:
|
|
return Pel::tra('Portrait');
|
|
case 3:
|
|
return Pel::tra('Night scene');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::GAIN_CONTROL:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Normal');
|
|
case 1:
|
|
return Pel::tra('Low gain up');
|
|
case 2:
|
|
return Pel::tra('High gain up');
|
|
case 3:
|
|
return Pel::tra('Low gain down');
|
|
case 4:
|
|
return Pel::tra('High gain down');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::SATURATION:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Normal');
|
|
case 1:
|
|
return Pel::tra('Low saturation');
|
|
case 2:
|
|
return Pel::tra('High saturation');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::CONTRAST:
|
|
case PelTag::SHARPNESS:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Normal');
|
|
case 1:
|
|
return Pel::tra('Soft');
|
|
case 2:
|
|
return Pel::tra('Hard');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::SUBJECT_DISTANCE_RANGE:
|
|
//CC (e->components, 1, v);
|
|
switch ($this->value[0]) {
|
|
case 0:
|
|
return Pel::tra('Unknown');
|
|
case 1:
|
|
return Pel::tra('Macro');
|
|
case 2:
|
|
return Pel::tra('Close view');
|
|
case 3:
|
|
return Pel::tra('Distant view');
|
|
default:
|
|
return $this->value[0];
|
|
}
|
|
|
|
case PelTag::SUBJECT_AREA:
|
|
switch ($this->components) {
|
|
case 2:
|
|
return Pel::fmt('(x,y) = (%d,%d)', $this->value[0], $this->value[1]);
|
|
case 3:
|
|
return Pel::fmt('Within distance %d of (x,y) = (%d,%d)',
|
|
$this->value[0], $this->value[1], $this->value[2]);
|
|
case 4:
|
|
return Pel::fmt('Within rectangle (width %d, height %d) around (x,y) = (%d,%d)',
|
|
$this->value[0], $this->value[1],
|
|
$this->value[2], $this->value[3]);
|
|
|
|
default:
|
|
return Pel::fmt('Unexpected number of components (%d, expected 2, 3, or 4).', $this->components);
|
|
}
|
|
|
|
default:
|
|
return parent::getText($brief);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Class for holding signed shorts.
|
|
*
|
|
* This class can hold shorts, either just a single short or an array
|
|
* of shorts. The class will be used to manipulate any of the Exif
|
|
* tags which has format {@link PelFormat::SSHORT}.
|
|
*
|
|
* @author Martin Geisler <mgeisler@users.sourceforge.net>
|
|
* @package PEL
|
|
*/
|
|
class PelEntrySShort extends PelEntryNumber {
|
|
|
|
/**
|
|
* Make a new entry that can hold a signed short.
|
|
*
|
|
* The method accept several integer arguments. The {@link
|
|
* getValue} method will always return an array except for when a
|
|
* single integer argument is given here.
|
|
*
|
|
* @param PelTag the tag which this entry represents. This
|
|
* should be one of the constants defined in {@link PelTag}
|
|
* which has format {@link PelFormat::SSHORT}.
|
|
*
|
|
* @param int $value... the signed short(s) that this entry will
|
|
* represent. The argument passed must obey the same rules as the
|
|
* argument to {@link setValue}, namely that it should be within
|
|
* range of a signed short, that is between -32768 to 32767
|
|
* (inclusive). If not, then a {@link PelOverFlowException} will be
|
|
* thrown.
|
|
*/
|
|
function __construct($tag /* $value... */) {
|
|
$this->tag = $tag;
|
|
$this->min = -32768;
|
|
$this->max = 32767;
|
|
$this->format = PelFormat::SSHORT;
|
|
|
|
$value = func_get_args();
|
|
array_shift($value);
|
|
$this->setValueArray($value);
|
|
}
|
|
|
|
|
|
/**
|
|
* Convert a number into bytes.
|
|
*
|
|
* @param int the number that should be converted.
|
|
*
|
|
* @param PelByteOrder one of {@link PelConvert::LITTLE_ENDIAN} and
|
|
* {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
|
|
*
|
|
* @return string bytes representing the number given.
|
|
*/
|
|
function numberToBytes($number, $order) {
|
|
return PelConvert::sShortToBytes($number, $order);
|
|
}
|
|
}
|
|
|
|
|
|
?>
|