<?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$ */


/**
 * Classes for dealing with JPEG markers.
 *
 * @author Martin Geisler <mgeisler@users.sourceforge.net>
 * @version $Revision: 432 $
 * @date $Date: 2006-09-06 00:13:00 +0200 (Wed, 06 Sep 2006) $
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public
 * License (GPL)
 * @package PEL
 */

/**#@+ Required class definitions. */
require_once('Pel.php');
/**#@-*/


/**
 * Class with static methods for JPEG markers.
 *
 * This class defines the constants to be used whenever one refers to
 * a JPEG marker.  All the methods defined are static, and they all
 * operate on one argument which should be one of the class constants.
 * They will all be denoted by PelJpegMarker in the documentation.
 *
 * @author Martin Geisler <mgeisler@users.sourceforge.net>
 * @package PEL
 */
class PelJpegMarker {

  /** Encoding (baseline) */
  const SOF0  = 0xC0;
  /** Encoding (extended sequential) */
  const SOF1  = 0xC1;
  /** Encoding (progressive) */
  const SOF2  = 0xC2;
  /** Encoding (lossless) */
  const SOF3  = 0xC3;
  /** Define Huffman table */
  const DHT   = 0xC4;
  /** Encoding (differential sequential) */
  const SOF5  = 0xC5;
  /** Encoding (differential progressive) */
  const SOF6  = 0xC6;
  /** Encoding (differential lossless) */
  const SOF7  = 0xC7;
  /** Extension */
  const JPG   = 0xC8;
  /** Encoding (extended sequential, arithmetic) */
  const SOF9  = 0xC9;
  /** Encoding (progressive, arithmetic) */
  const SOF10 = 0xCA;
  /** Encoding (lossless, arithmetic) */
  const SOF11 = 0xCB;
  /** Define arithmetic coding conditioning */
  const DAC   = 0xCC;
  /** Encoding (differential sequential, arithmetic) */
  const SOF13 = 0xCD;
  /** Encoding (differential progressive, arithmetic) */
  const SOF14 = 0xCE;
  /** Encoding (differential lossless, arithmetic) */
  const SOF15 = 0xCF;
  /** Restart 0 */
  const RST0  = 0xD0;
  /** Restart 1 */
  const RST1  = 0xD1;
  /** Restart 2 */
  const RST2  = 0xD2;
  /** Restart 3 */
  const RST3  = 0xD3;
  /** Restart 4 */
  const RST4  = 0xD4;
  /** Restart 5 */
  const RST5  = 0xD5;
  /** Restart 6 */
  const RST6  = 0xD6;
  /** Restart 7 */
  const RST7  = 0xD7;
  /** Start of image */
  const SOI   = 0xD8;
  /** End of image */
  const EOI   = 0xD9;
  /** Start of scan */
  const SOS   = 0xDA;
  /** Define quantization table */
  const DQT   = 0xDB;
  /** Define number of lines */
  const DNL   = 0xDC;
  /** Define restart interval */
  const DRI   = 0xDD;
  /** Define hierarchical progression */
  const DHP   = 0xDE;
  /** Expand reference component */
  const EXP   = 0xDF;
  /** Application segment 0 */
  const APP0  = 0xE0;
  /**
   * Application segment 1
   *
   * When a JPEG image contains Exif data, the data will normally be
   * stored in this section and a call to {@link PelJpeg::getExif()}
   * will return a {@link PelExif} object representing it.
   */
  const APP1  = 0xE1;
  /** Application segment 2 */
  const APP2  = 0xE2;
  /** Application segment 3 */
  const APP3  = 0xE3;
  /** Application segment 4 */
  const APP4  = 0xE4;
  /** Application segment 5 */
  const APP5  = 0xE5;
  /** Application segment 6 */
  const APP6  = 0xE6;
  /** Application segment 7 */
  const APP7  = 0xE7;
  /** Application segment 8 */
  const APP8  = 0xE8;
  /** Application segment 9 */
  const APP9  = 0xE9;
  /** Application segment 10 */
  const APP10 = 0xEA;
  /** Application segment 11 */
  const APP11 = 0xEB;
  /** Application segment 12 */
  const APP12 = 0xEC;
  /** Application segment 13 */
  const APP13 = 0xED;
  /** Application segment 14 */
  const APP14 = 0xEE;
  /** Application segment 15 */
  const APP15 = 0xEF;
  /** Extension 0 */
  const JPG0  = 0xF0;
  /** Extension 1 */
  const JPG1  = 0xF1;
  /** Extension 2 */
  const JPG2  = 0xF2;
  /** Extension 3 */
  const JPG3  = 0xF3;
  /** Extension 4 */
  const JPG4  = 0xF4;
  /** Extension 5 */
  const JPG5  = 0xF5;
  /** Extension 6 */
  const JPG6  = 0xF6;
  /** Extension 7 */
  const JPG7  = 0xF7;
  /** Extension 8 */
  const JPG8  = 0xF8;
  /** Extension 9 */
  const JPG9  = 0xF9;
  /** Extension 10 */
  const JPG10 = 0xFA;
  /** Extension 11 */
  const JPG11 = 0xFB;
  /** Extension 12 */
  const JPG12 = 0xFC;
  /** Extension 13 */
  const JPG13 = 0xFD;
  /** Comment */
  const COM   = 0xFE;

  /**
   * Check if a byte is a valid JPEG marker.
   *
   * @param PelJpegMarker the byte that will be checked.
   *
   * @return boolean if the byte is recognized true is returned,
   * otherwise false will be returned.
   */
  static function isValid($m) {
    return ($m >= self::SOF0 && $m <= self::COM);
  }
  
  /**
   * Turn a JPEG marker into bytes.
   *
   * @param PelJpegMarker the marker.
   *
   * @return string the marker as a string.  This will be a string
   * with just a single byte since all JPEG markers are simply single
   * bytes.
   */
  static function getBytes($m) {
    return chr($m);
  }

  /**
   * Return the short name for a marker.
   *
   * @param PelJpegMarker the marker.
   *
   * @return string the name of the marker, e.g., 'SOI' for the Start
   * of Image marker.
   */
  static function getName($m) {
    switch ($m) {
    case self::SOF0:  return 'SOF0';
    case self::SOF1:  return 'SOF1';
    case self::SOF2:  return 'SOF2';
    case self::SOF3:  return 'SOF3';
    case self::SOF5:  return 'SOF5';
    case self::SOF6:  return 'SOF6';
    case self::SOF7:  return 'SOF7';
    case self::SOF9:  return 'SOF9';
    case self::SOF10: return 'SOF10';
    case self::SOF11: return 'SOF11';
    case self::SOF13: return 'SOF13';
    case self::SOF14: return 'SOF14';
    case self::SOF15: return 'SOF15';
    case self::SOI:   return 'SOI';
    case self::EOI:   return 'EOI';
    case self::SOS:   return 'SOS';
    case self::COM:   return 'COM';
    case self::DHT:   return 'DHT';
    case self::JPG:   return 'JPG';
    case self::DAC:   return 'DAC';
    case self::RST0:  return 'RST0';
    case self::RST1:  return 'RST1';
    case self::RST2:  return 'RST2';
    case self::RST3:  return 'RST3';
    case self::RST4:  return 'RST4';
    case self::RST5:  return 'RST5';
    case self::RST6:  return 'RST6';
    case self::RST7:  return 'RST7';
    case self::DQT:   return 'DQT';
    case self::DNL:   return 'DNL';
    case self::DRI:   return 'DRI';
    case self::DHP:   return 'DHP';
    case self::EXP:   return 'EXP';
    case self::APP0:  return 'APP0';
    case self::APP1:  return 'APP1';
    case self::APP2:  return 'APP2';
    case self::APP3:  return 'APP3';
    case self::APP4:  return 'APP4';
    case self::APP5:  return 'APP5';
    case self::APP6:  return 'APP6';
    case self::APP7:  return 'APP7';
    case self::APP8:  return 'APP8';
    case self::APP9:  return 'APP9';
    case self::APP10: return 'APP10';
    case self::APP11: return 'APP11';
    case self::APP12: return 'APP12';
    case self::APP13: return 'APP13';
    case self::APP14: return 'APP14';
    case self::APP15: return 'APP15';
    case self::JPG0:  return 'JPG0';
    case self::JPG1:  return 'JPG1';
    case self::JPG2:  return 'JPG2';
    case self::JPG3:  return 'JPG3';
    case self::JPG4:  return 'JPG4';
    case self::JPG5:  return 'JPG5';
    case self::JPG6:  return 'JPG6';
    case self::JPG7:  return 'JPG7';
    case self::JPG8:  return 'JPG8';
    case self::JPG9:  return 'JPG9';
    case self::JPG10: return 'JPG10';
    case self::JPG11: return 'JPG11';
    case self::JPG12: return 'JPG12';
    case self::JPG13: return 'JPG13';
    case self::COM:   return 'COM';
    default:          return Pel::fmt('Unknown marker: 0x%02X', $m);
    }
  }

  /**
   * Returns a description of a JPEG marker.
   *
   * @param PelJpegMarker the marker.
   *
   * @return string the description of the marker.
   */
  static function getDescription($m) {
    switch ($m) {
    case self::SOF0:
      return Pel::tra('Encoding (baseline)');
    case self::SOF1:
      return Pel::tra('Encoding (extended sequential)');
    case self::SOF2:
      return Pel::tra('Encoding (progressive)');
    case self::SOF3:
      return Pel::tra('Encoding (lossless)');
    case self::SOF5:
      return Pel::tra('Encoding (differential sequential)');
    case self::SOF6:
      return Pel::tra('Encoding (differential progressive)');
    case self::SOF7:
      return Pel::tra('Encoding (differential lossless)');
    case self::SOF9:
      return Pel::tra('Encoding (extended sequential, arithmetic)');
    case self::SOF10:
      return Pel::tra('Encoding (progressive, arithmetic)');
    case self::SOF11:
      return Pel::tra('Encoding (lossless, arithmetic)');
    case self::SOF13:
      return Pel::tra('Encoding (differential sequential, arithmetic)');
    case self::SOF14:
      return Pel::tra('Encoding (differential progressive, arithmetic)');
    case self::SOF15:
      return Pel::tra('Encoding (differential lossless, arithmetic)');
    case self::SOI:
      return Pel::tra('Start of image');
    case self::EOI:
      return Pel::tra('End of image');
    case self::SOS:
      return Pel::tra('Start of scan');
    case self::COM:
      return Pel::tra('Comment');
    case self::DHT:
      return Pel::tra('Define Huffman table');
    case self::JPG:
      return Pel::tra('Extension');
    case self::DAC:
      return Pel::tra('Define arithmetic coding conditioning');
    case self::RST0:
      return Pel::fmt('Restart %d', 0);
    case self::RST1:
      return Pel::fmt('Restart %d', 1);
    case self::RST2:
      return Pel::fmt('Restart %d', 2);
    case self::RST3:
      return Pel::fmt('Restart %d', 3);
    case self::RST4:
      return Pel::fmt('Restart %d', 4);
    case self::RST5:
      return Pel::fmt('Restart %d', 5);
    case self::RST6:
      return Pel::fmt('Restart %d', 6);
    case self::RST7:
      return Pel::fmt('Restart %d', 7);
    case self::DQT:
      return Pel::tra('Define quantization table');
    case self::DNL:
      return Pel::tra('Define number of lines');
    case self::DRI:
      return Pel::tra('Define restart interval');
    case self::DHP:
      return Pel::tra('Define hierarchical progression');
    case self::EXP:
      return Pel::tra('Expand reference component');
    case self::APP0:
      return Pel::fmt('Application segment %d', 0);
    case self::APP1:
      return Pel::fmt('Application segment %d', 1);
    case self::APP2:
      return Pel::fmt('Application segment %d', 2);
    case self::APP3:
      return Pel::fmt('Application segment %d', 3);
    case self::APP4:
      return Pel::fmt('Application segment %d', 4);
    case self::APP5:
      return Pel::fmt('Application segment %d', 5);
    case self::APP6:
      return Pel::fmt('Application segment %d', 6);
    case self::APP7:
      return Pel::fmt('Application segment %d', 7);
    case self::APP8:
      return Pel::fmt('Application segment %d', 8);
    case self::APP9:
      return Pel::fmt('Application segment %d', 9);
    case self::APP10:
      return Pel::fmt('Application segment %d', 10);
    case self::APP11:
      return Pel::fmt('Application segment %d', 11);
    case self::APP12:
      return Pel::fmt('Application segment %d', 12);
    case self::APP13:
      return Pel::fmt('Application segment %d', 13);
    case self::APP14:
      return Pel::fmt('Application segment %d', 14);
    case self::APP15:
      return Pel::fmt('Application segment %d', 15);
    case self::JPG0:
      return Pel::fmt('Extension %d', 0);
    case self::JPG1:
      return Pel::fmt('Extension %d', 1);
    case self::JPG2:
      return Pel::fmt('Extension %d', 2);
    case self::JPG3:
      return Pel::fmt('Extension %d', 3);
    case self::JPG4:
      return Pel::fmt('Extension %d', 4);
    case self::JPG5:
      return Pel::fmt('Extension %d', 5);
    case self::JPG6:
      return Pel::fmt('Extension %d', 6);
    case self::JPG7:
      return Pel::fmt('Extension %d', 7);
    case self::JPG8:
      return Pel::fmt('Extension %d', 8);
    case self::JPG9:
      return Pel::fmt('Extension %d', 9);
    case self::JPG10:
      return Pel::fmt('Extension %d', 10);
    case self::JPG11:
      return Pel::fmt('Extension %d', 11);
    case self::JPG12:
      return Pel::fmt('Extension %d', 12);
    case self::JPG13:
      return Pel::fmt('Extension %d', 13);
    case self::COM:
      return Pel::tra('Comment');
    default:
      return Pel::fmt('Unknown marker: 0x%02X', $m);
    }
  }
}

?>