Your IP : 216.73.216.190


Current Path : /proc/1908984/root/proc/2603263/cwd/
Upload File :
Current File : //proc/1908984/root/proc/2603263/cwd/FastImageSize.tar

FastImageSize.php000064400000016426152414333200007756 0ustar00<?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 Nextend\Framework\FastImageSize;

use Nextend\Framework\Pattern\SingletonTrait;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;

class FastImageSize {

    use SingletonTrait;

    private static $cache = array();

    /**
     * @param string $image
     * @param array  $attributes
     */
    public static function initAttributes($image, &$attributes) {

        $size = self::getSize($image);

        if ($size) {
            $attributes['width']  = $size['width'];
            $attributes['height'] = $size['height'];
        }
    }

    public static function getWidth($image) {

        $size = self::getSize($image);

        if ($size) {
            return $size['width'];
        }

        return 0;
    }

    public static function getSize($image) {
        $imagePath = ResourceTranslator::toPath($image);

        if (!isset(self::$cache[$imagePath])) {
            if (empty($imagePath)) {
                self::$cache[$imagePath] = false;
            } else {
                self::$cache[$imagePath] = self::getInstance()
                                               ->getImageSize($imagePath);
            }
        }

        return self::$cache[$imagePath];
    }

    /** @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'
        ),
        'webp' => array(
            'webp',
        ),
        'svg'  => array(
            'svg',
        )
    );

    /** @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;

    /**
     * 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) {
            $this->loadAllTypes();
            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);
        $this->loadExtension($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, false, 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;
    }

    /**
     * Load all supported types
     */
    protected function loadAllTypes() {
        foreach ($this->supportedTypes as $imageType => $extension) {
            $this->loadType($imageType);
        }
    }

    /**
     * Load an image type by extension
     *
     * @param string $extension Extension of image
     */
    protected function loadExtension($extension) {
        if (isset($this->classMap[$extension])) {
            return;
        }
        foreach ($this->supportedTypes as $imageType => $extensions) {
            if (in_array($extension, $extensions, true)) {
                $this->loadType($imageType);
            }
        }
    }

    /**
     * Load an image type
     *
     * @param string $imageType Mimetype
     */
    protected function loadType($imageType) {
        if (isset($this->type[$imageType])) {
            return;
        }

        $className = '\\' . __NAMESPACE__ . '\Type\Type' . ucfirst($imageType);

        $this->type[$imageType] = new $className($this);

        // Create class map
        foreach ($this->supportedTypes[$imageType] as $ext) {
            /** @var Type\TypeInterface */
            $this->classMap[$ext] = $this->type[$imageType];
        }
    }
}
Type/TypeBase.php000064400000001346152414333210007714 0ustar00<?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 Nextend\Framework\FastImageSize\Type;

use Nextend\Framework\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;
    }
}
Type/TypeGif.php000064400000002467152414333210007554 0ustar00<?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 Nextend\Framework\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);
    }
}
Type/TypeInterface.php000064400000001261152414333240010741 0ustar00<?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 Nextend\Framework\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);
}
Type/TypeJpeg.php000064400000012123152414333270007730 0ustar00<?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 Nextend\Framework\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 = 786432; // = 768 kiB

    /** @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 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++;
            }
        }
    }
}
Type/TypePng.php000064400000002537152414333270007577 0ustar00<?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 Nextend\Framework\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);
    }
}
Type/TypeSvg.php000064400000002014152414333310007573 0ustar00<?php

namespace Nextend\Framework\FastImageSize\Type;

class TypeSvg extends TypeBase {

    /**
     * {@inheritdoc}
     */
    public function getSize($filename) {

        $data = $this->fastImageSize->getImage($filename, 0, 100);

        preg_match('/width="([0-9]+)"/', $data, $matches);
        if ($matches && $matches[1] > 0) {
            $size          = array();
            $size['width'] = $matches[1];

            preg_match('/height="([0-9]+)"/', $data, $matches);
            if ($matches && $matches[1] > 0) {
                $size['height'] = $matches[1];
                $this->fastImageSize->setSize($size);

                return;
            }
        }

        preg_match('/viewBox=["\']([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)["\']/i', $data, $matches);

        if ($matches) {
            $this->fastImageSize->setSize(array(
                'width'  => $matches[3] - $matches[1],
                'height' => $matches[4] - $matches[2],
            ));
        }

    }
}
Type/TypeWebp.php000064400000010423152414333310007734 0ustar00<?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 Nextend\Framework\FastImageSize\Type;

use Nextend\Framework\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;
        }
    }
}