Source for file PelEntryAscii.php

Documentation is available at PelEntryAscii.php

  1. <?php
  2.  
  3. /*  PEL: PHP Exif Library.  A library with support for reading and
  4.  *  writing all Exif headers in JPEG and TIFF images using PHP.
  5.  *
  6.  *  Copyright (C) 2004, 2005, 2006, 2007  Martin Geisler.
  7.  *
  8.  *  This program is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2 of the License, or
  11.  *  (at your option) any later version.
  12.  *
  13.  *  This program is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program in the file COPYING; if not, write to the
  20.  *  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  21.  *  Boston, MA 02110-1301 USA
  22.  */
  23.  
  24. /* $Id$ */
  25.  
  26.  
  27. /**
  28.  * Classes used to hold ASCII strings.
  29.  *
  30.  * The classes defined here are to be used for Exif entries holding
  31.  * ASCII strings, such as {@link PelTag::MAKE}{@link }
  32.  * PelTag::SOFTWARE}, and {@link PelTag::DATE_TIME}.  For
  33.  * entries holding normal textual ASCII strings the class {@link }
  34.  * PelEntryAscii} should be used, but for entries holding
  35.  * timestamps the class {@link PelEntryTime} would be more
  36.  * convenient instead.  Copyright information is handled by the {@link }
  37.  * PelEntryCopyright} class.
  38.  *
  39.  * @author Martin Geisler <mgeisler@users.sourceforge.net>
  40.  * @version $Revision$
  41.  * @date $Date$
  42.  * @license http://www.gnu.org/licenses/gpl.html GNU General Public
  43.  *  License (GPL)
  44.  * @package PEL
  45.  */
  46.  
  47. /**#@+ Required class definitions. */
  48. require_once('PelEntry.php');
  49. /**#@-*/
  50.  
  51.  
  52. /**
  53.  * Class for holding a plain ASCII string.
  54.  *
  55.  * This class can hold a single ASCII string, and it will be used as in
  56.  * <code>
  57.  * $entry = $ifd->getEntry(PelTag::IMAGE_DESCRIPTION);
  58.  * print($entry->getValue());
  59.  * $entry->setValue('This is my image.  I like it.');
  60.  * </code>
  61.  *
  62.  * @author Martin Geisler <mgeisler@users.sourceforge.net>
  63.  * @package PEL
  64.  */
  65. class PelEntryAscii extends PelEntry {
  66.  
  67.   /**
  68.    * The string hold by this entry.
  69.    *
  70.    * This is the string that was given to the {@link __construct}
  71.    * constructor} or later to {@link setValue}, without any final NULL
  72.    * character.
  73.    *
  74.    * @var string 
  75.    */
  76.   private $str;
  77.  
  78.  
  79.   /**
  80.    * Make a new PelEntry that can hold an ASCII string.
  81.    *
  82.    * @param int the tag which this entry represents.  This should be
  83.    *  one of the constants defined in {@link PelTag}, e.g., {@link }
  84.    *  PelTag::IMAGE_DESCRIPTION}, {@link PelTag::MODEL}, or any other
  85.    *  tag with format {@link PelFormat::ASCII}.
  86.    *
  87.    * @param string the string that this entry will represent.  The
  88.    *  string must obey the same rules as the string argument to {@link }
  89.    *  setValue}, namely that it should be given without any trailing
  90.    *  NULL character and that it must be plain 7-bit ASCII.
  91.    */
  92.   function __construct($tag$str ''{
  93.     $this->tag    = $tag;
  94.     $this->format = PelFormat::ASCII;
  95.     self::setValue($str);
  96.   }
  97.  
  98.  
  99.   /**
  100.    * Give the entry a new ASCII value.
  101.    *
  102.    * This will overwrite the previous value.  The value can be
  103.    * retrieved later with the {@link getValue} method.
  104.    *
  105.    * @param string the new value of the entry.  This should be given
  106.    *  without any trailing NULL character.  The string must be plain
  107.    *  7-bit ASCII, the string should contain no high bytes.
  108.    *
  109.    * @todo Implement check for high bytes?
  110.    */
  111.   function setValue($str{
  112.     $this->components = strlen($str)+1;
  113.     $this->str        $str;
  114.     $this->bytes      = $str chr(0x00);
  115.   }
  116.  
  117.  
  118.   /**
  119.    * Return the ASCII string of the entry.
  120.    *
  121.    * @return string the string held, without any final NULL character.
  122.    *  The string will be the same as the one given to {@link setValue}
  123.    *  or to the {@link __construct constructor}.
  124.    */
  125.   function getValue({
  126.     return $this->str;
  127.   }
  128.  
  129.  
  130.   /**
  131.    * Return the ASCII string of the entry.
  132.    *
  133.    * This methods returns the same as {@link getValue}.
  134.    *
  135.    * @param boolean not used with ASCII entries.
  136.    *
  137.    * @return string the string held, without any final NULL character.
  138.    *  The string will be the same as the one given to {@link setValue}
  139.    *  or to the {@link __construct constructor}.
  140.    */
  141.   function getText($brief false{
  142.     return $this->str;      
  143.   }
  144.  
  145. }
  146.  
  147.  
  148. /**
  149.  * Class for holding a date and time.
  150.  *
  151.  * This class can hold a timestamp, and it will be used as
  152.  * in this example where the time is advanced by one week:
  153.  * <code>
  154.  * $entry = $ifd->getEntry(PelTag::DATE_TIME_ORIGINAL);
  155.  * $time = $entry->getValue();
  156.  * print('The image was taken on the ' . date('jS', $time));
  157.  * $entry->setValue($time + 7 * 24 * 3600);
  158.  * </code>
  159.  *
  160.  * The example used a standard UNIX timestamp, which is the default
  161.  * for this class.
  162.  *
  163.  * But the Exif format defines dates outside the range of a UNIX
  164.  * timestamp (about 1970 to 2038) and so you can also get access to
  165.  * the timestamp in two other formats: a simple string or a Julian Day
  166.  * Count. Please see the Calendar extension in the PHP Manual for more
  167.  * information about the Julian Day Count.
  168.  *
  169.  * @author Martin Geisler <mgeisler@users.sourceforge.net>
  170.  * @package PEL
  171.  */
  172. class PelEntryTime extends PelEntryAscii {
  173.  
  174.   /**
  175.    * Constant denoting a UNIX timestamp.
  176.    */
  177.   const UNIX_TIMESTAMP   = 1;
  178.   /**
  179.    * Constant denoting a Exif string.
  180.    */
  181.   const EXIF_STRING      = 2;
  182.   /**
  183.    * Constant denoting a Julian Day Count.
  184.    */
  185.   const JULIAN_DAY_COUNT = 3;
  186.  
  187.   /**
  188.    * The Julian Day Count of the timestamp held by this entry.
  189.    *
  190.    * This is an integer counting the number of whole days since
  191.    * January 1st, 4713 B.C. The fractional part of the timestamp held
  192.    * by this entry is stored in {@link $seconds}.
  193.    *
  194.    * @var int 
  195.    */
  196.   private $day_count;
  197.  
  198.   /**
  199.    * The number of seconds into the day of the timestamp held by this
  200.    * entry.
  201.    *
  202.    * The number of whole days is stored in {@link $day_count} and the
  203.    * number of seconds left-over is stored here.
  204.    *
  205.    * @var int 
  206.    */
  207.   private $seconds;
  208.  
  209.  
  210.   /**
  211.    * Make a new entry for holding a timestamp.
  212.    *
  213.    * @param int the Exif tag which this entry represents.  There are
  214.    *  only three standard tags which hold timestamp, so this should be
  215.    *  one of the constants {@link PelTag::DATE_TIME}{@link }
  216.    *  PelTag::DATE_TIME_ORIGINAL}, or {@link }
  217.    *  PelTag::DATE_TIME_DIGITIZED}.
  218.    *
  219.    * @param int the timestamp held by this entry in the correct form
  220.    *  as indicated by the third argument. For {@link UNIX_TIMESTAMP}
  221.    *  this is an integer counting the number of seconds since January
  222.    *  1st 1970, for {@link EXIF_STRING} this is a string of the form
  223.    *  'YYYY:MM:DD hh:mm:ss', and for {@link JULIAN_DAY_COUNT} this is a
  224.    *  floating point number where the integer part denotes the day
  225.    *  count and the fractional part denotes the time of day (0.25 means
  226.    *  6:00, 0.75 means 18:00).
  227.    *
  228.    * @param int the type of the timestamp. This must be one of
  229.    *  {@link UNIX_TIMESTAMP}{@link EXIF_STRING}, or
  230.    *  {@link JULIAN_DAY_COUNT}.
  231.    */
  232.   function __construct($tag$timestamp$type self::UNIX_TIMESTAMP{
  233.     parent::__construct($tag);
  234.     $this->setValue($timestamp$type);
  235.   }
  236.  
  237.   
  238.   /**
  239.    * Return the timestamp of the entry.
  240.    *
  241.    * The timestamp held by this entry is returned in one of three
  242.    * formats: as a standard UNIX timestamp (default), as a fractional
  243.    * Julian Day Count, or as a string.
  244.    *
  245.    * @param int the type of the timestamp. This must be one of
  246.    *  {@link UNIX_TIMESTAMP}{@link EXIF_STRING}, or
  247.    *  {@link JULIAN_DAY_COUNT}.
  248.    *
  249.    * @return int the timestamp held by this entry in the correct form
  250.    *  as indicated by the type argument. For {@link UNIX_TIMESTAMP}
  251.    *  this is an integer counting the number of seconds since January
  252.    *  1st 1970, for {@link EXIF_STRING} this is a string of the form
  253.    *  'YYYY:MM:DD hh:mm:ss', and for {@link JULIAN_DAY_COUNT} this is a
  254.    *  floating point number where the integer part denotes the day
  255.    *  count and the fractional part denotes the time of day (0.25 means
  256.    *  6:00, 0.75 means 18:00).
  257.    */
  258.   function getValue($type self::UNIX_TIMESTAMP{
  259.     switch ($type{
  260.     case self::UNIX_TIMESTAMP:
  261.       $seconds $this->convertJdToUnix($this->day_count);
  262.       if ($seconds === false)
  263.         /* We get false if the Julian Day Count is outside the range
  264.          * of a UNIX timestamp. */ 
  265.         return false;
  266.       else
  267.         return $seconds $this->seconds;
  268.  
  269.     case self::EXIF_STRING:
  270.       list($year$month$day$this->convertJdToGregorian($this->day_count);
  271.       $hours   = (int)($this->seconds 3600);
  272.       $minutes = (int)($this->seconds 3600 60);
  273.       $seconds $this->seconds 60;
  274.       return sprintf('%04d:%02d:%02d %02d:%02d:%02d',
  275.                      $year$month$day$hours$minutes$seconds);
  276.     case self::JULIAN_DAY_COUNT:
  277.       return $this->day_count $this->seconds 86400;
  278.     default:
  279.       throw new PelInvalidArgumentException('Expected UNIX_TIMESTAMP (%d), ' .
  280.                                             'EXIF_STRING (%d), or ' .
  281.                                             'JULIAN_DAY_COUNT (%d) for $type, '.
  282.                                             'got %d.',
  283.                                             self::UNIX_TIMESTAMP,
  284.                                             self::EXIF_STRING,
  285.                                             self::JULIAN_DAY_COUNT,
  286.                                             $type);
  287.     }
  288.   }
  289.  
  290.  
  291.   /**
  292.    * Update the timestamp held by this entry.
  293.    *
  294.    * @param int the timestamp held by this entry in the correct form
  295.    *  as indicated by the third argument. For {@link UNIX_TIMESTAMP}
  296.    *  this is an integer counting the number of seconds since January
  297.    *  1st 1970, for {@link EXIF_STRING} this is a string of the form
  298.    *  'YYYY:MM:DD hh:mm:ss', and for {@link JULIAN_DAY_COUNT} this is a
  299.    *  floating point number where the integer part denotes the day
  300.    *  count and the fractional part denotes the time of day (0.25 means
  301.    *  6:00, 0.75 means 18:00).
  302.    *
  303.    * @param int the type of the timestamp. This must be one of
  304.    *  {@link UNIX_TIMESTAMP}{@link EXIF_STRING}, or
  305.    *  {@link JULIAN_DAY_COUNT}.
  306.    */
  307.   function setValue($timestamp$type self::UNIX_TIMESTAMP{
  308.     #if (empty($timestamp))
  309.     #  debug_print_backtrace();
  310.  
  311.     switch ($type{
  312.     case self::UNIX_TIMESTAMP:
  313.       $this->day_count $this->convertUnixToJd($timestamp);
  314.       $this->seconds   $timestamp 86400;
  315.       break;
  316.  
  317.     case self::EXIF_STRING:
  318.       /* Clean the timestamp: some timestamps are broken other
  319.        * separators than ':' and ' '. */
  320.       $d preg_split('/[^0-9]+/'$timestamp);
  321.       $this->day_count $this->convertGregorianToJd($d[0]$d[1]$d[2]);
  322.       $this->seconds   $d[3]*3600 $d[4]*60 $d[5];
  323.       break;
  324.  
  325.     case self::JULIAN_DAY_COUNT:
  326.       $this->day_count = (int)floor($timestamp);
  327.       $this->seconds = (int)(86400 ($timestamp floor($timestamp)));
  328.       break;
  329.  
  330.     default:
  331.       throw new PelInvalidArgumentException('Expected UNIX_TIMESTAMP (%d), ' .
  332.                                             'EXIF_STRING (%d), or ' .
  333.                                             'JULIAN_DAY_COUNT (%d) for $type, '.
  334.                                             'got %d.',
  335.                                             self::UNIX_TIMESTAMP,
  336.                                             self::EXIF_STRING,
  337.                                             self::JULIAN_DAY_COUNT,
  338.                                             $type);
  339.     }
  340.  
  341.     /* Now finally update the string which will be used when this is
  342.      * turned into bytes. */
  343.     parent::setValue($this->getValue(self::EXIF_STRING));
  344.   }
  345.  
  346.  
  347.   // The following four functions are used for converting back and
  348.   // forth between the date formats. They are used in preference to
  349.   // the ones from the PHP calendar extension to avoid having to
  350.   // fiddle with timezones and to avoid depending on the extension.
  351.   //
  352.   // See http://www.hermetic.ch/cal_stud/jdn.htm#comp for a reference.
  353.  
  354.   /**
  355.    * Converts a date in year/month/day format to a Julian Day count.
  356.    *
  357.    * @param int $year  the year.
  358.    * @param int $month the month, 1 to 12.
  359.    * @param int $day   the day in the month.
  360.    * @return int the Julian Day count.
  361.    */
  362.   function convertGregorianToJd($year$month$day{
  363.     // Special case mapping 0/0/0 -> 0
  364.     if ($year == || $month == || $day == 0)
  365.       return 0;
  366.  
  367.     $m1412 ($month <= 2? -0;
  368.     return floor(( 1461 $year 4800 $m1412 ) ) 4+
  369.       floor(( 367 $month 12 $m1412 ) ) 12-
  370.       floor(( floor( ( $year 4900 $m1412 100 ) ) 4+
  371.       $day 32075;
  372.   }
  373.  
  374.   /**
  375.    * Converts a Julian Day count to a year/month/day triple.
  376.    * 
  377.    * @param int the Julian Day count.
  378.    * @return array an array with three entries: year, month, day.
  379.    */
  380.   function convertJdToGregorian($jd{
  381.     // Special case mapping 0 -> 0/0/0
  382.     if ($jd == 0)
  383.       return array(0,0,0);
  384.  
  385.     $l $jd 68569;
  386.     $n floor(( $l 146097);
  387.     $l $l floor(( 146097 $n 4);
  388.     $i floor(( 4000 $l ) ) 1461001);
  389.     $l $l floor(( 1461 $i 431;
  390.     $j floor(( 80 $l 2447);
  391.     $d $l floor(( 2447 $j 80);
  392.     $l floor($j 11);
  393.     $m $j 12 $l );
  394.     $y 100 $n 49 $i $l;
  395.     return array($y$m$d);
  396.   }
  397.  
  398.   /**
  399.    * Converts a UNIX timestamp to a Julian Day count.
  400.    *
  401.    * @param int $timestamp the timestamp.
  402.    * @return int the Julian Day count.
  403.    */
  404.   function convertUnixToJd($timestamp{
  405.     return (int)(floor($timestamp 864002440588);
  406.   }
  407.  
  408.   /**
  409.    * Converts a Julian Day count to a UNIX timestamp.
  410.    *
  411.    * @param int $jd the Julian Day count.
  412.  
  413.    * @return mixed $timestamp the integer timestamp or false if the
  414.    *  day count cannot be represented as a UNIX timestamp.
  415.    */
  416.   function convertJdToUnix($jd{
  417.     $timestamp ($jd 244058886400;
  418.     if ($timestamp != (int)$timestamp)
  419.       return false;
  420.     else
  421.       return $timestamp;
  422.   }
  423.  
  424. }
  425.  
  426.  
  427. /**
  428.  * Class for holding copyright information.
  429.  *
  430.  * The Exif standard specifies a certain format for copyright
  431.  * information where the one {@link PelTag::COPYRIGHT copyright}
  432.  * tag} holds both the photographer and editor copyrights, separated
  433.  * by a NULL character.
  434.  *
  435.  * This class is used to manipulate that tag so that the format is
  436.  * kept to the standard.  A common use would be to add a new copyright
  437.  * tag to an image, since most cameras do not add this tag themselves.
  438.  * This would be done like this:
  439.  *
  440.  * <code>
  441.  * $entry = new PelEntryCopyright('Copyright, Martin Geisler, 2004');
  442.  * $ifd0->addEntry($entry);
  443.  * </code>
  444.  *
  445.  * Here we only set the photographer copyright, use the optional
  446.  * second argument to specify the editor copyright.  If there is only
  447.  * an editor copyright, then let the first argument be the empty
  448.  * string.
  449.  *
  450.  * @author Martin Geisler <mgeisler@users.sourceforge.net>
  451.  * @package PEL
  452.  */
  453. class PelEntryCopyright extends PelEntryAscii {
  454.  
  455.   /**
  456.    * The photographer copyright.
  457.    *
  458.    * @var string 
  459.    */
  460.   private $photographer;
  461.  
  462.   /**
  463.    * The editor copyright.
  464.    *
  465.    * @var string 
  466.    */
  467.   private $editor;
  468.  
  469.  
  470.   /**
  471.    * Make a new entry for holding copyright information.
  472.    *
  473.    * @param string the photographer copyright.  Use the empty string
  474.    *  if there is no photographer copyright.
  475.    *
  476.    * @param string the editor copyright.  Use the empty string if
  477.    *  there is no editor copyright.
  478.    */
  479.   function __construct($photographer ''$editor ''{
  480.     parent::__construct(PelTag::COPYRIGHT);
  481.     $this->setValue($photographer$editor);
  482.   }
  483.   
  484.  
  485.   /**
  486.    * Update the copyright information.
  487.    *
  488.    * @param string the photographer copyright.  Use the empty string
  489.    *  if there is no photographer copyright.
  490.    *
  491.    * @param string the editor copyright.  Use the empty string if
  492.    *  there is no editor copyright.
  493.    */
  494.   function setValue($photographer ''$editor ''{
  495.     $this->photographer $photographer;
  496.     $this->editor       $editor;
  497.  
  498.     if ($photographer == '' && $editor != '')
  499.       $photographer ' ';
  500.  
  501.     if ($editor == '')
  502.       parent::setValue($photographer);
  503.     else
  504.       parent::setValue($photographer chr(0x00$editor);
  505.   }
  506.  
  507.  
  508.   /**
  509.    * Retrive the copyright information.
  510.    *
  511.    * The strings returned will be the same as the one used previously
  512.    * with either {@link __construct the constructor} or with {@link }
  513.    * setValue}.
  514.    *
  515.    * @return array an array with two strings, the photographer and
  516.    *  editor copyrights.  The two fields will be returned in that
  517.    *  order, so that the first array index will be the photographer
  518.    *  copyright, and the second will be the editor copyright.
  519.    */
  520.   function getValue({
  521.     return array($this->photographer$this->editor);
  522.   }
  523.  
  524.  
  525.   /**
  526.    * Return a text string with the copyright information.
  527.    *
  528.    * The photographer and editor copyright fields will be returned
  529.    * with a '-' in between if both copyright fields are present,
  530.    * otherwise only one of them will be returned.
  531.    *
  532.    * @param boolean if false, then the strings '(Photographer)' and
  533.    *  '(Editor)' will be appended to the photographer and editor
  534.    *  copyright fields (if present), otherwise the fields will be
  535.    *  returned as is.
  536.    *
  537.    * @return string the copyright information in a string.
  538.    */
  539.   function getText($brief false{
  540.     if ($brief{
  541.       $p '';
  542.       $e '';
  543.     else {
  544.       $p ' ' Pel::tra('(Photographer)');
  545.       $e ' ' Pel::tra('(Editor)');
  546.     }
  547.  
  548.     if ($this->photographer != '' && $this->editor != '')
  549.       return $this->photographer $p ' - ' $this->editor $e;
  550.     
  551.     if ($this->photographer != '')
  552.       return $this->photographer $p;
  553.  
  554.     if ($this->editor != '')
  555.       return $this->editor $e;
  556.  
  557.     return '';
  558.   }
  559. }
  560.  
  561. ?>

Documentation generated on Thu, 05 May 2011 07:19:02 +0200 by phpDocumentor 1.4.3