PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,228 @@
<?php
/**
* fast-image-size base class
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize;
class FastImageSize
{
/** @var array Size info that is returned */
protected $size = array();
/** @var string Data retrieved from remote */
protected $data = '';
/** @var array List of supported image types and associated image types */
protected $supportedTypes = array(
'png' => array('png'),
'gif' => array('gif'),
'jpeg' => array(
'jpeg',
'jpg',
'jpe',
'jif',
'jfif',
'jfi',
),
'jp2' => array(
'jp2',
'j2k',
'jpf',
'jpg2',
'jpx',
'jpm',
),
'psd' => array(
'psd',
'photoshop',
),
'bmp' => array('bmp'),
'tif' => array(
'tif',
'tiff',
),
'wbmp' => array(
'wbm',
'wbmp',
'vnd.wap.wbmp',
),
'iff' => array(
'iff',
'x-iff',
),
'ico' => array(
'ico',
'vnd.microsoft.icon',
'x-icon',
'icon',
),
'webp' => array(
'webp',
)
);
/** @var array Class map that links image extensions/mime types to class */
protected $classMap;
/** @var array An array containing the classes of supported image types */
protected $type;
/**
* Constructor for fastImageSize class
*/
public function __construct()
{
foreach ($this->supportedTypes as $imageType => $extension)
{
$className = '\FastImageSize\Type\Type' . mb_convert_case(mb_strtolower($imageType), MB_CASE_TITLE);
$this->type[$imageType] = new $className($this);
// Create class map
foreach ($extension as $ext)
{
/** @var Type\TypeInterface */
$this->classMap[$ext] = $this->type[$imageType];
}
}
}
/**
* Get image dimensions of supplied image
*
* @param string $file Path to image that should be checked
* @param string $type Mimetype of image
* @return array|bool Array with image dimensions if successful, false if not
*/
public function getImageSize($file, $type = '')
{
// Reset values
$this->resetValues();
// Treat image type as unknown if extension or mime type is unknown
if (!preg_match('/\.([a-z0-9]+)$/i', $file, $match) && empty($type))
{
$this->getImagesizeUnknownType($file);
}
else
{
$extension = (empty($type) && isset($match[1])) ? $match[1] : preg_replace('/.+\/([a-z0-9-.]+)$/i', '$1', $type);
$this->getImageSizeByExtension($file, $extension);
}
return sizeof($this->size) > 1 ? $this->size : false;
}
/**
* Get dimensions of image if type is unknown
*
* @param string $filename Path to file
*/
protected function getImagesizeUnknownType($filename)
{
// Grab the maximum amount of bytes we might need
$data = $this->getImage($filename, 0, Type\TypeJpeg::JPEG_MAX_HEADER_SIZE, false);
if ($data !== false)
{
foreach ($this->type as $imageType)
{
$imageType->getSize($filename);
if (sizeof($this->size) > 1)
{
break;
}
}
}
}
/**
* Get image size by file extension
*
* @param string $file Path to image that should be checked
* @param string $extension Extension/type of image
*/
protected function getImageSizeByExtension($file, $extension)
{
$extension = strtolower($extension);
if (isset($this->classMap[$extension]))
{
$this->classMap[$extension]->getSize($file);
}
}
/**
* Reset values to default
*/
protected function resetValues()
{
$this->size = array();
$this->data = '';
}
/**
* Set mime type based on supplied image
*
* @param int $type Type of image
*/
public function setImageType($type)
{
$this->size['type'] = $type;
}
/**
* Set size info
*
* @param array $size Array containing size info for image
*/
public function setSize($size)
{
$this->size = $size;
}
/**
* Get image from specified path/source
*
* @param string $filename Path to image
* @param int $offset Offset at which reading of the image should start
* @param int $length Maximum length that should be read
* @param bool $forceLength True if the length needs to be the specified
* length, false if not. Default: true
*
* @return false|string Image data or false if result was empty
*/
public function getImage($filename, $offset, $length, $forceLength = true)
{
if (empty($this->data))
{
$this->data = @file_get_contents($filename, null, null, $offset, $length);
}
// Force length to expected one. Return false if data length
// is smaller than expected length
if ($forceLength === true)
{
return (strlen($this->data) < $length) ? false : substr($this->data, $offset, $length) ;
}
return empty($this->data) ? false : $this->data;
}
/**
* Get return data
*
* @return array|bool Size array if dimensions could be found, false if not
*/
protected function getReturnData()
{
return sizeof($this->size) > 1 ? $this->size : false;
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* fast-image-size image type base
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
use \FastImageSize\FastImageSize;
abstract class TypeBase implements TypeInterface
{
/** @var FastImageSize */
protected $fastImageSize;
/**
* Base constructor for image types
*
* @param FastImageSize $fastImageSize
*/
public function __construct(FastImageSize $fastImageSize)
{
$this->fastImageSize = $fastImageSize;
}
}

View File

@ -0,0 +1,43 @@
<?php
/**
* fast-image-size image type bmp
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeBmp extends TypeBase
{
/** @var int BMP header size needed for retrieving dimensions */
const BMP_HEADER_SIZE = 26;
/** @var string BMP signature */
const BMP_SIGNATURE = "\x42\x4D";
/** qvar int BMP dimensions offset */
const BMP_DIMENSIONS_OFFSET = 18;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
$data = $this->fastImageSize->getImage($filename, 0, self::BMP_HEADER_SIZE);
// Check if supplied file is a BMP file
if (substr($data, 0, 2) !== self::BMP_SIGNATURE)
{
return;
}
$size = unpack('lwidth/lheight', substr($data, self::BMP_DIMENSIONS_OFFSET, 2 * self::LONG_SIZE));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_BMP);
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* fast-image-size image type gif
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeGif extends TypeBase
{
/** @var string GIF87a header */
const GIF87A_HEADER = "\x47\x49\x46\x38\x37\x61";
/** @var string GIF89a header */
const GIF89A_HEADER = "\x47\x49\x46\x38\x39\x61";
/** @var int GIF header size */
const GIF_HEADER_SIZE = 6;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
// Get data needed for reading image dimensions as outlined by GIF87a
// and GIF89a specifications
$data = $this->fastImageSize->getImage($filename, 0, self::GIF_HEADER_SIZE + self::SHORT_SIZE * 2);
$type = substr($data, 0, self::GIF_HEADER_SIZE);
if ($type !== self::GIF87A_HEADER && $type !== self::GIF89A_HEADER)
{
return;
}
$size = unpack('vwidth/vheight', substr($data, self::GIF_HEADER_SIZE, self::SHORT_SIZE * 2));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_GIF);
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* fast-image-size image type ico
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeIco extends TypeBase
{
/** @var string ICO reserved field */
const ICO_RESERVED = 0;
/** @var int ICO type field */
const ICO_TYPE = 1;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
// Retrieve image data for ICO header and header of first entry.
// We assume the first entry to have the same size as the other ones.
$data = $this->fastImageSize->getImage($filename, 0, 2 * self::LONG_SIZE);
if ($data === false)
{
return;
}
// Check if header fits expected format
if (!$this->isValidIco($data))
{
return;
}
$size = unpack('Cwidth/Cheight', substr($data, self::LONG_SIZE + self::SHORT_SIZE, self::SHORT_SIZE));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_ICO);
}
/**
* Return whether image is a valid ICO file
*
* @param string $data Image data string
*
* @return bool True if file is a valid ICO file, false if not
*/
protected function isValidIco($data)
{
// Get header
$header = unpack('vreserved/vtype/vimages', $data);
return $header['reserved'] === self::ICO_RESERVED && $header['type'] === self::ICO_TYPE && $header['images'] > 0 && $header['images'] <= 255;
}
}

View File

@ -0,0 +1,117 @@
<?php
/**
* fast-image-size image type iff
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeIff extends TypeBase
{
/** @var int IFF header size. Grab more than what should be needed to make
* sure we have the necessary data */
const IFF_HEADER_SIZE = 32;
/** @var string IFF header for Amiga type */
const IFF_HEADER_AMIGA = 'FORM';
/** @var string IFF header for Maya type */
const IFF_HEADER_MAYA = 'FOR4';
/** @var string IFF BTMHD for Amiga type */
const IFF_AMIGA_BTMHD = 'BMHD';
/** @var string IFF BTMHD for Maya type */
const IFF_MAYA_BTMHD = 'BHD';
/** @var string PHP pack format for unsigned short */
const PACK_UNSIGNED_SHORT = 'n';
/** @var string PHP pack format for unsigned long */
const PACK_UNSIGNED_LONG = 'N';
/** @var string BTMHD of current image */
protected $btmhd;
/** @var int Size of current BTMHD */
protected $btmhdSize;
/** @var string Current byte type */
protected $byteType;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
$data = $this->fastImageSize->getImage($filename, 0, self::IFF_HEADER_SIZE);
$signature = $this->getIffSignature($data);
// Check if image is IFF
if ($signature === false)
{
return;
}
// Set type constraints
$this->setTypeConstraints($signature);
// Get size from data
$btmhdPosition = strpos($data, $this->btmhd);
$size = unpack("{$this->byteType}width/{$this->byteType}height", substr($data, $btmhdPosition + self::LONG_SIZE + strlen($this->btmhd), $this->btmhdSize));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_IFF);
}
/**
* Get IFF signature from data string
*
* @param string|bool $data Image data string
*
* @return false|string Signature if file is a valid IFF file, false if not
*/
protected function getIffSignature($data)
{
$signature = substr($data, 0, self::LONG_SIZE);
// Check if image is IFF
if ($signature !== self::IFF_HEADER_AMIGA && $signature !== self::IFF_HEADER_MAYA)
{
return false;
}
else
{
return $signature;
}
}
/**
* Set type constraints for current image
*
* @param string $signature IFF signature of image
*/
protected function setTypeConstraints($signature)
{
// Amiga version of IFF
if ($signature === 'FORM')
{
$this->btmhd = self::IFF_AMIGA_BTMHD;
$this->btmhdSize = self::LONG_SIZE;
$this->byteType = self::PACK_UNSIGNED_SHORT;
}
// Maya version
else
{
$this->btmhd = self::IFF_MAYA_BTMHD;
$this->btmhdSize = self::LONG_SIZE * 2;
$this->byteType = self::PACK_UNSIGNED_LONG;
}
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* fast-image-size image type interface
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
interface TypeInterface
{
/** @var int 4-byte long size */
const LONG_SIZE = 4;
/** @var int 2-byte short size */
const SHORT_SIZE = 2;
/**
* Get size of supplied image
*
* @param string $filename File name of image
*
* @return null
*/
public function getSize($filename);
}

View File

@ -0,0 +1,51 @@
<?php
/**
* fast-image-size image type jpeg 2000
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeJp2 extends TypeBase
{
/** @var string JPEG 2000 signature */
const JPEG_2000_SIGNATURE = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A";
/** @var string JPEG 2000 SOC marker */
const JPEG_2000_SOC_MARKER = "\xFF\x4F";
/** @var string JPEG 2000 SIZ marker */
const JPEG_2000_SIZ_MARKER = "\xFF\x51";
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
$data = $this->fastImageSize->getImage($filename, 0, TypeJpeg::JPEG_MAX_HEADER_SIZE, false);
// Check if file is jpeg 2000
if (substr($data, 0, strlen(self::JPEG_2000_SIGNATURE)) !== self::JPEG_2000_SIGNATURE)
{
return;
}
// Get SOC position before starting to search for SIZ.
// Make sure we do not get SIZ before SOC by cutting at SOC.
$data = substr($data, strpos($data, self::JPEG_2000_SOC_MARKER));
// Remove SIZ and everything before
$data = substr($data, strpos($data, self::JPEG_2000_SIZ_MARKER) + self::SHORT_SIZE);
// Acquire size info from data
$size = unpack('Nwidth/Nheight', substr($data, self::LONG_SIZE, self::LONG_SIZE * 2));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_JPEG2000);
}
}

View File

@ -0,0 +1,204 @@
<?php
/**
* fast-image-size image type jpeg
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeJpeg extends TypeBase
{
/** @var int JPEG max header size. Headers can be bigger, but we'll abort
* going through the header after this */
const JPEG_MAX_HEADER_SIZE = 124576;
/** @var string JPEG header */
const JPEG_HEADER = "\xFF\xD8";
/** @var string Start of frame marker */
const SOF_START_MARKER = "\xFF";
/** @var string End of image (EOI) marker */
const JPEG_EOI_MARKER = "\xD9";
/** @var array JPEG SOF markers */
protected $sofMarkers = array(
"\xC0",
"\xC1",
"\xC2",
"\xC3",
"\xC5",
"\xC6",
"\xC7",
"\xC9",
"\xCA",
"\xCB",
"\xCD",
"\xCE",
"\xCF"
);
/** @var array JPEG APP markers */
protected $appMarkers = array(
"\xE0",
"\xE1",
"\xE2",
"\xE3",
"\xEC",
"\xED",
"\xEE",
);
/** @var string|bool JPEG data stream */
protected $data = '';
/** @var int Data length */
protected $dataLength = 0;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
// Do not force the data length
$this->data = $this->fastImageSize->getImage($filename, 0, self::JPEG_MAX_HEADER_SIZE, false);
// Check if file is jpeg
if ($this->data === false || substr($this->data, 0, self::SHORT_SIZE) !== self::JPEG_HEADER)
{
return;
}
// Look through file for SOF marker
$size = $this->getSizeInfo();
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_JPEG);
}
/**
* Get size info from image data
*
* @return array An array with the image's size info or an empty array if
* size info couldn't be found
*/
protected function getSizeInfo()
{
$size = array();
// since we check $i + 1 we need to stop one step earlier
$this->dataLength = strlen($this->data) - 1;
$sofStartRead = true;
// Look through file for SOF marker
for ($i = 2; $i < $this->dataLength; $i++)
{
$marker = $this->getNextMarker($i, $sofStartRead);
if (in_array($marker, $this->sofMarkers))
{
// Extract size info from SOF marker
return $this->extractSizeInfo($i);
}
else
{
// Extract length only
$markerLength = $this->extractMarkerLength($i);
if ($markerLength < 2)
{
return $size;
}
$i += $markerLength - 1;
continue;
}
}
return $size;
}
/**
* Extract marker length from data
*
* @param int $i Current index
* @return int Length of current marker
*/
protected function extractMarkerLength($i)
{
// Extract length only
list(, $unpacked) = unpack("H*", substr($this->data, $i, self::LONG_SIZE));
// Get width and height from unpacked size info
$markerLength = hexdec(substr($unpacked, 0, 4));
return $markerLength;
}
/**
* Extract size info from data
*
* @param int $i Current index
* @return array Size info of current marker
*/
protected function extractSizeInfo($i)
{
// Extract size info from SOF marker
list(, $unpacked) = unpack("H*", substr($this->data, $i - 1 + self::LONG_SIZE, self::LONG_SIZE));
// Get width and height from unpacked size info
$size = array(
'width' => hexdec(substr($unpacked, 4, 4)),
'height' => hexdec(substr($unpacked, 0, 4)),
);
return $size;
}
/**
* Get next JPEG marker in file
*
* @param int $i Current index
* @param bool $sofStartRead Flag whether SOF start padding was already read
*
* @return string Next JPEG marker in file
*/
protected function getNextMarker(&$i, &$sofStartRead)
{
$this->skipStartPadding($i, $sofStartRead);
do {
if ($i >= $this->dataLength)
{
return self::JPEG_EOI_MARKER;
}
$marker = $this->data[$i];
$i++;
} while ($marker == self::SOF_START_MARKER);
return $marker;
}
/**
* Skip over any possible padding until we reach a byte without SOF start
* marker. Extraneous bytes might need to require proper treating.
*
* @param int $i Current index
* @param bool $sofStartRead Flag whether SOF start padding was already read
*/
protected function skipStartPadding(&$i, &$sofStartRead)
{
if (!$sofStartRead)
{
while ($this->data[$i] !== self::SOF_START_MARKER)
{
$i++;
}
}
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* fast-image-size image type png
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypePng extends TypeBase
{
/** @var string PNG header */
const PNG_HEADER = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a";
/** @var int PNG IHDR offset */
const PNG_IHDR_OFFSET = 12;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
// Retrieve image data including the header, the IHDR tag, and the
// following 2 chunks for the image width and height
$data = $this->fastImageSize->getImage($filename, 0, self::PNG_IHDR_OFFSET + 3 * self::LONG_SIZE);
// Check if header fits expected format specified by RFC 2083
if (substr($data, 0, self::PNG_IHDR_OFFSET - self::LONG_SIZE) !== self::PNG_HEADER || substr($data, self::PNG_IHDR_OFFSET, self::LONG_SIZE) !== 'IHDR')
{
return;
}
$size = unpack('Nwidth/Nheight', substr($data, self::PNG_IHDR_OFFSET + self::LONG_SIZE, self::LONG_SIZE * 2));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_PNG);
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* fast-image-size image type psd
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypePsd extends TypeBase
{
/** @var string PSD signature */
const PSD_SIGNATURE = "8BPS";
/** @var int PSD header size */
const PSD_HEADER_SIZE = 22;
/** @var int PSD dimensions info offset */
const PSD_DIMENSIONS_OFFSET = 14;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
$data = $this->fastImageSize->getImage($filename, 0, self::PSD_HEADER_SIZE);
if ($data === false)
{
return;
}
// Offset for version info is length of header but version is only a
// 16-bit unsigned value
$version = unpack('n', substr($data, self::LONG_SIZE, 2));
// Check if supplied file is a PSD file
if (!$this->validPsd($data, $version))
{
return;
}
$size = unpack('Nheight/Nwidth', substr($data, self::PSD_DIMENSIONS_OFFSET, 2 * self::LONG_SIZE));
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_PSD);
}
/**
* Return whether file is a valid PSD file
*
* @param string $data Image data string
* @param array $version Version array
*
* @return bool True if image is a valid PSD file, false if not
*/
protected function validPsd($data, $version)
{
return substr($data, 0, self::LONG_SIZE) === self::PSD_SIGNATURE && $version[1] === 1;
}
}

View File

@ -0,0 +1,152 @@
<?php
/**
* fast-image-size image type tif
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeTif extends TypeBase
{
/** @var int TIF header size. The header might be larger but the dimensions
* should be in the first 51200 bytes */
const TIF_HEADER_SIZE = 51200;
/** @var int TIF tag for image height */
const TIF_TAG_IMAGE_HEIGHT = 257;
/** @var int TIF tag for image width */
const TIF_TAG_IMAGE_WIDTH = 256;
/** @var int TIF tag for exif IFD offset */
const TIF_TAG_EXIF_OFFSET = 34665;
/** @var int TIF tag for Image X resolution in pixels */
const TIF_TAG_EXIF_IMAGE_WIDTH = 0xA002;
/** @var int TIF tag for Image Y resolution in pixels */
const TIF_TAG_EXIF_IMAGE_HEIGHT = 0xA003;
/** @var int TIF tag type for short */
const TIF_TAG_TYPE_SHORT = 3;
/** @var int TIF IFD entry size */
const TIF_IFD_ENTRY_SIZE = 12;
/** @var string TIF signature of intel type */
const TIF_SIGNATURE_INTEL = 'II';
/** @var string TIF signature of motorola type */
const TIF_SIGNATURE_MOTOROLA = 'MM';
/** @var array Size info array */
protected $size;
/** @var string Bit type of long field */
public $typeLong;
/** @var string Bit type of short field */
public $typeShort;
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
// Do not force length of header
$data = $this->fastImageSize->getImage($filename, 0, self::TIF_HEADER_SIZE, false);
$this->size = array();
$signature = substr($data, 0, self::SHORT_SIZE);
if (!in_array($signature, array(self::TIF_SIGNATURE_INTEL, self::TIF_SIGNATURE_MOTOROLA)))
{
return;
}
// Set byte type
$this->setByteType($signature);
// Get offset of IFD
list(, $offset) = unpack($this->typeLong, substr($data, self::LONG_SIZE, self::LONG_SIZE));
// Get size of IFD
list(, $sizeIfd) = unpack($this->typeShort, substr($data, $offset, self::SHORT_SIZE));
// Skip 2 bytes that define the IFD size
$offset += self::SHORT_SIZE;
// Ensure size can't exceed data length
$sizeIfd = min($sizeIfd, floor((strlen($data) - $offset) / self::TIF_IFD_ENTRY_SIZE));
// Filter through IFD
for ($i = 0; $i < $sizeIfd; $i++)
{
// Get IFD tag
$type = unpack($this->typeShort, substr($data, $offset, self::SHORT_SIZE));
// Get field type of tag
$fieldType = unpack($this->typeShort . 'type', substr($data, $offset + self::SHORT_SIZE, self::SHORT_SIZE));
// Get IFD entry
$ifdValue = substr($data, $offset + 2 * self::LONG_SIZE, self::LONG_SIZE);
// Set size of field
$this->setSizeInfo($type[1], $fieldType['type'], $ifdValue);
$offset += self::TIF_IFD_ENTRY_SIZE;
}
$this->fastImageSize->setSize($this->size);
}
/**
* Set byte type based on signature in header
*
* @param string $signature Header signature
*/
public function setByteType($signature)
{
if ($signature === self::TIF_SIGNATURE_INTEL)
{
$this->typeLong = 'V';
$this->typeShort = 'v';
$this->size['type'] = IMAGETYPE_TIFF_II;
}
else
{
$this->typeLong = 'N';
$this->typeShort = 'n';
$this->size['type'] = IMAGETYPE_TIFF_MM;
}
}
/**
* Set size info
*
* @param int $dimensionType Type of dimension. Either width or height
* @param int $fieldLength Length of field. Either short or long
* @param string $ifdValue String value of IFD field
*/
protected function setSizeInfo($dimensionType, $fieldLength, $ifdValue)
{
// Set size of field
$fieldSize = $fieldLength === self::TIF_TAG_TYPE_SHORT ? $this->typeShort : $this->typeLong;
// Get actual dimensions from IFD
if ($dimensionType === self::TIF_TAG_IMAGE_HEIGHT)
{
$this->size = array_merge($this->size, unpack($fieldSize . 'height', $ifdValue));
}
else if ($dimensionType === self::TIF_TAG_IMAGE_WIDTH)
{
$this->size = array_merge($this->size, unpack($fieldSize . 'width', $ifdValue));
}
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* fast-image-size image type wbmp
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
class TypeWbmp extends TypeBase
{
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
$data = $this->fastImageSize->getImage($filename, 0, self::LONG_SIZE);
// Check if image is WBMP
if ($data === false || !$this->validWBMP($data))
{
return;
}
$size = unpack('Cwidth/Cheight', substr($data, self::SHORT_SIZE, self::SHORT_SIZE));
// Check if dimensions are valid. A file might be recognised as WBMP
// rather easily (see extra check for JPEG2000).
if (!$this->validDimensions($size))
{
return;
}
$this->fastImageSize->setSize($size);
$this->fastImageSize->setImageType(IMAGETYPE_WBMP);
}
/**
* Return if supplied data might be part of a valid WBMP file
*
* @param bool|string $data
*
* @return bool True if data might be part of a valid WBMP file, else false
*/
protected function validWBMP($data)
{
return ord($data[0]) === 0 && ord($data[1]) === 0 && $data !== substr(TypeJp2::JPEG_2000_SIGNATURE, 0, self::LONG_SIZE);
}
/**
* Return whether dimensions are valid
*
* @param array $size Size array
*
* @return bool True if dimensions are valid, false if not
*/
protected function validDimensions($size)
{
return $size['height'] > 0 && $size['width'] > 0;
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
* fast-image-size image type webp
* @package fast-image-size
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FastImageSize\Type;
use \FastImageSize\FastImageSize;
class TypeWebp extends TypeBase
{
/** @var string RIFF header */
const WEBP_RIFF_HEADER = "RIFF";
/** @var string Webp header */
const WEBP_HEADER = "WEBP";
/** @var string VP8 chunk header */
const VP8_HEADER = "VP8";
/** @var string Simple(lossy) webp format */
const WEBP_FORMAT_SIMPLE = ' ';
/** @var string Lossless webp format */
const WEBP_FORMAT_LOSSLESS = 'L';
/** @var string Extended webp format */
const WEBP_FORMAT_EXTENDED = 'X';
/** @var int WEBP header size needed for retrieving image size */
const WEBP_HEADER_SIZE = 30;
/** @var array Size info array */
protected $size;
/**
* Constructor for webp image type. Adds missing constant if necessary.
*
* @param FastImageSize $fastImageSize
*/
public function __construct(FastImageSize $fastImageSize)
{
parent::__construct($fastImageSize);
if (!defined('IMAGETYPE_WEBP'))
{
define('IMAGETYPE_WEBP', 18);
}
}
/**
* {@inheritdoc}
*/
public function getSize($filename)
{
// Do not force length of header
$data = $this->fastImageSize->getImage($filename, 0, self::WEBP_HEADER_SIZE);
$this->size = array();
$webpFormat = substr($data, 15, 1);
if (!$this->hasWebpHeader($data) || !$this->isValidFormat($webpFormat))
{
return;
}
$data = substr($data, 16, 14);
$this->getWebpSize($data, $webpFormat);
$this->fastImageSize->setSize($this->size);
$this->fastImageSize->setImageType(IMAGETYPE_WEBP);
}
/**
* Check if $data has valid WebP header
*
* @param string $data Image data
*
* @return bool True if $data has valid WebP header, false if not
*/
protected function hasWebpHeader($data)
{
$riffSignature = substr($data, 0, self::LONG_SIZE);
$webpSignature = substr($data, 8, self::LONG_SIZE);
$vp8Signature = substr($data, 12, self::SHORT_SIZE + 1);
return !empty($data) && $riffSignature === self::WEBP_RIFF_HEADER &&
$webpSignature === self::WEBP_HEADER && $vp8Signature === self::VP8_HEADER;
}
/**
* Check if $format is a valid WebP format
*
* @param string $format Format string
* @return bool True if format is valid WebP format, false if not
*/
protected function isValidFormat($format)
{
return in_array($format, array(self::WEBP_FORMAT_SIMPLE, self::WEBP_FORMAT_LOSSLESS, self::WEBP_FORMAT_EXTENDED));
}
/**
* Get webp size info depending on format type and set size array values
*
* @param string $data Data string
* @param string $format Format string
*/
protected function getWebpSize($data, $format)
{
switch ($format)
{
case self::WEBP_FORMAT_SIMPLE:
$this->size = unpack('vwidth/vheight', substr($data, 10, 4));
break;
case self::WEBP_FORMAT_LOSSLESS:
// Lossless uses 14-bit values so we'll have to use bitwise shifting
$this->size = array(
'width' => ord($data[5]) + ((ord($data[6]) & 0x3F) << 8) + 1,
'height' => (ord($data[6]) >> 6) + (ord($data[7]) << 2) + ((ord($data[8]) & 0xF) << 10) + 1,
);
break;
case self::WEBP_FORMAT_EXTENDED:
// Extended uses 24-bit values cause 14-bit for lossless wasn't weird enough
$this->size = array(
'width' => ord($data[8]) + (ord($data[9]) << 8) + (ord($data[10]) << 16) + 1,
'height' => ord($data[11]) + (ord($data[12]) << 8) + (ord($data[13]) << 16) + 1,
);
break;
}
}
}