diff options
Diffstat (limited to 'modules/autorotate/lib/pel/PelDataWindow.php')
| -rw-r--r-- | modules/autorotate/lib/pel/PelDataWindow.php | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/modules/autorotate/lib/pel/PelDataWindow.php b/modules/autorotate/lib/pel/PelDataWindow.php new file mode 100644 index 0000000..b40722c --- /dev/null +++ b/modules/autorotate/lib/pel/PelDataWindow.php @@ -0,0 +1,540 @@ +<?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, 2007 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$ */ + + +/** + * A container for bytes with a limited window of accessible bytes. + * + * @author Martin Geisler <mgeisler@users.sourceforge.net> + * @version $Revision$ + * @date $Date$ + * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL) + * @package PEL + */ + +/**#@+ Required class definitions. */ +require_once('PelException.php'); +require_once('PelConvert.php'); +/**#@-*/ + + +/** + * An exception thrown when an invalid offset is encountered. + * + * @package PEL + * @subpackage Exception + */ +class PelDataWindowOffsetException extends PelException {} + +/** + * An exception thrown when an invalid window is encountered. + * + * @package PEL + * @subpackage Exception + */ +class PelDataWindowWindowException extends PelException {} + +/** + * The window. + * + * @package PEL + */ +class PelDataWindow { + + /** + * The data held by this window. + * + * The string can contain any kind of data, including binary data. + * + * @var string + */ + private $data = ''; + + /** + * The byte order currently in use. + * + * This will be the byte order used when data is read using the for + * example the {@link getShort} function. It must be one of {@link + * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}. + * + * @var PelByteOrder + * @see setByteOrder, getByteOrder + */ + private $order; + + /** + * The start of the current window. + * + * All offsets used for access into the data will count from this + * offset, effectively limiting access to a window starting at this + * byte. + * + * @var int + * @see setWindowStart + */ + private $start = 0; + + /** + * The size of the current window. + * + * All offsets used for access into the data will be limited by this + * variable. A valid offset must be strictly less than this + * variable. + * + * @var int + * @see setWindowSize + */ + private $size = 0; + + + /** + * Construct a new data window with the data supplied. + * + * @param mixed the data that this window will contain. This can + * either be given as a string (interpreted litteraly as a sequence + * of bytes) or a PHP image resource handle. The data will be copied + * into the new data window. + * + * @param boolean the initial byte order of the window. This must + * be either {@link PelConvert::LITTLE_ENDIAN} or {@link + * PelConvert::BIG_ENDIAN}. This will be used when integers are + * read from the data, and it can be changed later with {@link + * setByteOrder()}. + */ + function __construct($data = '', $endianess = PelConvert::LITTLE_ENDIAN) { + if (is_string($data)) { + $this->data = $data; + } elseif (is_resource($data) && get_resource_type($data) == 'gd') { + /* The ImageJpeg() function insists on printing the bytes + * instead of returning them in a more civil way as a string, so + * we have to buffer the output... */ + ob_start(); + ImageJpeg($data, null, Pel::getJPEGQuality()); + $this->data = ob_get_clean(); + } else { + throw new PelInvalidArgumentException('Bad type for $data: %s', + gettype($data)); + } + + $this->order = $endianess; + $this->size = strlen($this->data); + } + + + /** + * Get the size of the data window. + * + * @return int the number of bytes covered by the window. The + * allowed offsets go from 0 up to this number minus one. + * + * @see getBytes() + */ + function getSize() { + return $this->size; + } + + + /** + * Change the byte order of the data. + * + * @param PelByteOrder the new byte order. This must be either + * {@link PelConvert::LITTLE_ENDIAN} or {@link + * PelConvert::BIG_ENDIAN}. + */ + function setByteOrder($o) { + $this->order = $o; + } + + + /** + * Get the currently used byte order. + * + * @return PelByteOrder this will be either {@link + * PelConvert::LITTLE_ENDIAN} or {@link PelConvert::BIG_ENDIAN}. + */ + function getByteOrder() { + return $this->order; + } + + + /* Move the start of the window forward. + * + * @param int the new start of the window. All new offsets will be + * calculated from this new start offset, and the size of the window + * will shrink to keep the end of the window in place. + */ + function setWindowStart($start) { + if ($start < 0 || $start > $this->size) + throw new PelDataWindowWindowException('Window [%d, %d] does ' . + 'not fit in window [0, %d]', + $start, $this->size, $this->size); + + $this->start += $start; + $this->size -= $start; + } + + + /** + * Adjust the size of the window. + * + * The size can only be made smaller. + * + * @param int the desired size of the window. If the argument is + * negative, the window will be shrunk by the argument. + */ + function setWindowSize($size) { + if ($size < 0) + $size += $this->size; + + if ($size < 0 || $size > $this->size) + throw new PelDataWindowWindowException('Window [0, %d] ' . + 'does not fit in window [0, %d]', + $size, $this->size); + $this->size = $size; + } + + + /** + * Make a new data window with the same data as the this window. + * + * @param mixed if an integer is supplied, then it will be the start + * of the window in the clone. If left unspecified, then the clone + * will inherit the start from this object. + * + * @param mixed if an integer is supplied, then it will be the size + * of the window in the clone. If left unspecified, then the clone + * will inherit the size from this object. + * + * @return PelDataWindow a new window that operates on the same data + * as this window, but (optionally) with a smaller window size. + */ + function getClone($start = false, $size = false) { + $c = clone $this; + + if (is_int($start)) + $c->setWindowStart($start); + + if (is_int($size)) + $c->setWindowSize($size); + + return $c; + } + + + /** + * Validate an offset against the current window. + * + * @param int the offset to be validated. If the offset is negative + * or if it is greater than or equal to the current window size, + * then a {@link PelDataWindowOffsetException} is thrown. + * + * @return void if the offset is valid nothing is returned, if it is + * invalid a new {@link PelDataWindowOffsetException} is thrown. + */ + private function validateOffset($o) { + if ($o < 0 || $o >= $this->size) + throw new PelDataWindowOffsetException('Offset %d not within [%d, %d]', + $o, 0, $this->size-1); + } + + + /** + * Return some or all bytes visible in the window. + * + * This method works just like the standard {@link substr()} + * function in PHP with the exception that it works within the + * window of accessible bytes and does strict range checking. + * + * @param int the offset to the first byte returned. If a negative + * number is given, then the counting will be from the end of the + * window. Invalid offsets will result in a {@link + * PelDataWindowOffsetException} being thrown. + * + * @param int the size of the sub-window. If a negative number is + * given, then that many bytes will be omitted from the result. + * + * @return string a subset of the bytes in the window. This will + * always return no more than {@link getSize()} bytes. + */ + function getBytes($start = false, $size = false) { + if (is_int($start)) { + if ($start < 0) + $start += $this->size; + + $this->validateOffset($start); + } else { + $start = 0; + } + + if (is_int($size)) { + if ($size <= 0) + $size += $this->size - $start; + + $this->validateOffset($start+$size); + } else { + $size = $this->size - $start; + } + + return substr($this->data, $this->start + $start, $size); + } + + + /** + * Return an unsigned byte from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first byte in the current allowed window. The last + * valid offset is equal to {@link getSize()}-1. Invalid offsets + * will result in a {@link PelDataWindowOffsetException} being + * thrown. + * + * @return int the unsigned byte found at offset. + */ + function getByte($o = 0) { + /* Validate the offset --- this throws an exception if offset is + * out of range. */ + $this->validateOffset($o); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Return an unsigned byte. */ + return PelConvert::bytesToByte($this->data, $o); + } + + + /** + * Return a signed byte from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first byte in the current allowed window. The last + * valid offset is equal to {@link getSize()}-1. Invalid offsets + * will result in a {@link PelDataWindowOffsetException} being + * thrown. + * + * @return int the signed byte found at offset. + */ + function getSByte($o = 0) { + /* Validate the offset --- this throws an exception if offset is + * out of range. */ + $this->validateOffset($o); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Return a signed byte. */ + return PelConvert::bytesToSByte($this->data, $o); + } + + + /** + * Return an unsigned short read from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first short available in the current allowed window. + * The last valid offset is equal to {@link getSize()}-2. Invalid + * offsets will result in a {@link PelDataWindowOffsetException} + * being thrown. + * + * @return int the unsigned short found at offset. + */ + function getShort($o = 0) { + /* Validate the offset+1 to see if we can safely get two bytes --- + * this throws an exception if offset is out of range. */ + $this->validateOffset($o); + $this->validateOffset($o+1); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Return an unsigned short. */ + return PelConvert::bytesToShort($this->data, $o, $this->order); + } + + + /** + * Return a signed short read from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first short available in the current allowed window. + * The last valid offset is equal to {@link getSize()}-2. Invalid + * offsets will result in a {@link PelDataWindowOffsetException} + * being thrown. + * + * @return int the signed short found at offset. + */ + function getSShort($o = 0) { + /* Validate the offset+1 to see if we can safely get two bytes --- + * this throws an exception if offset is out of range. */ + $this->validateOffset($o); + $this->validateOffset($o+1); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Return a signed short. */ + return PelConvert::bytesToSShort($this->data, $o, $this->order); + } + + + /** + * Return an unsigned long read from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first long available in the current allowed window. + * The last valid offset is equal to {@link getSize()}-4. Invalid + * offsets will result in a {@link PelDataWindowOffsetException} + * being thrown. + * + * @return int the unsigned long found at offset. + */ + function getLong($o = 0) { + /* Validate the offset+3 to see if we can safely get four bytes + * --- this throws an exception if offset is out of range. */ + $this->validateOffset($o); + $this->validateOffset($o+3); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Return an unsigned long. */ + return PelConvert::bytesToLong($this->data, $o, $this->order); + } + + + /** + * Return a signed long read from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first long available in the current allowed window. + * The last valid offset is equal to {@link getSize()}-4. Invalid + * offsets will result in a {@link PelDataWindowOffsetException} + * being thrown. + * + * @return int the signed long found at offset. + */ + function getSLong($o = 0) { + /* Validate the offset+3 to see if we can safely get four bytes + * --- this throws an exception if offset is out of range. */ + $this->validateOffset($o); + $this->validateOffset($o+3); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Return a signed long. */ + return PelConvert::bytesToSLong($this->data, $o, $this->order); + } + + + /** + * Return an unsigned rational read from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first rational available in the current allowed + * window. The last valid offset is equal to {@link getSize()}-8. + * Invalid offsets will result in a {@link + * PelDataWindowOffsetException} being thrown. + * + * @return array the unsigned rational found at offset. A rational + * number is represented as an array of two numbers: the enumerator + * and denominator. Both of these numbers will be unsigned longs. + */ + function getRational($o = 0) { + return array($this->getLong($o), $this->getLong($o+4)); + } + + + /** + * Return a signed rational read from the data. + * + * @param int the offset into the data. An offset of zero will + * return the first rational available in the current allowed + * window. The last valid offset is equal to {@link getSize()}-8. + * Invalid offsets will result in a {@link + * PelDataWindowOffsetException} being thrown. + * + * @return array the signed rational found at offset. A rational + * number is represented as an array of two numbers: the enumerator + * and denominator. Both of these numbers will be signed longs. + */ + function getSRational($o = 0) { + return array($this->getSLong($o), $this->getSLong($o+4)); + } + + + /** + * String comparison on substrings. + * + * @param int the offset into the data. An offset of zero will make + * the comparison start with the very first byte available in the + * window. The last valid offset is equal to {@link getSize()} + * minus the length of the string. If the string is too long, then + * a {@link PelDataWindowOffsetException} will be thrown. + * + * @param string the string to compare with. + * + * @return boolean true if the string given matches the data in the + * window, at the specified offset, false otherwise. The comparison + * will stop as soon as a mismatch if found. + */ + function strcmp($o, $str) { + /* Validate the offset of the final character we might have to + * check. */ + $s = strlen($str); + $this->validateOffset($o); + $this->validateOffset($o + $s - 1); + + /* Translate the offset into an offset into the data. */ + $o += $this->start; + + /* Check each character, return as soon as the answer is known. */ + for ($i = 0; $i < $s; $i++) { + if ($this->data{$o + $i} != $str{$i}) + return false; + } + + /* All characters matches each other, return true. */ + return true; + } + + + /** + * Return a string representation of the data window. + * + * @return string a description of the window with information about + * the number of bytes accessible, the total number of bytes, and + * the window start and stop. + */ + function __toString() { + return Pel::fmt('DataWindow: %d bytes in [%d, %d] of %d bytes', + $this->size, + $this->start, $this->start + $this->size, + strlen($this->data)); + } + +} + |
