<?php
/**
 * Pimcore
 *
 * This source file is available under two different licenses:
 * - GNU General Public License version 3 (GPLv3)
 * - Pimcore Enterprise License (PEL)
 * Full copyright and license information is available in
 * LICENSE.md which is distributed with this source code.
 *
 * @copyright  Copyright (c) 2009-2016 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     GPLv3 and PEL
 */

namespace Pimcore\Image\Adapter;

use Pimcore\Image\Adapter;
use Pimcore\File;
use Pimcore\Config;
use Pimcore\Logger;

class Imagick extends Adapter
{


    /**
     * @var string
     */
    protected static $RGBColorProfile;

    /**
     * @var string
     */
    protected static $CMYKColorProfile;

    /**
     * @var \Imagick
     */
    protected $resource;

    /**
     * @var string
     */
    protected $imagePath;

    /**
     * @param $imagePath
     * @param array $options
     * @return $this|bool|self
     */
    public function load($imagePath, $options = [])
    {

        // support image URLs
        if (preg_match("@^https?://@", $imagePath)) {
            $tmpFilename = "imagick_auto_download_" . md5($imagePath) . "." . File::getFileExtension($imagePath);
            $tmpFilePath = PIMCORE_SYSTEM_TEMP_DIRECTORY . "/" . $tmpFilename;

            $this->tmpFiles[] = $tmpFilePath;

            File::put($tmpFilePath, \Pimcore\Tool::getHttpData($imagePath));
            $imagePath = $tmpFilePath;
        }

        if (!stream_is_local($imagePath)) {
            // imagick is only able to deal with local files
            // if your're using custom stream wrappers this wouldn't work, so we create a temp. local copy
            $tmpFilePath = PIMCORE_SYSTEM_TEMP_DIRECTORY . "/imagick-tmp-" . uniqid() . "." . File::getFileExtension($imagePath);
            copy($imagePath, $tmpFilePath);
            $imagePath = $tmpFilePath;
            $this->tmpFiles[] = $imagePath;
        }

        if ($this->resource) {
            unset($this->resource);
            $this->resource = null;
        }

        try {
            $i = new \Imagick();
            $this->imagePath = $imagePath;

            if (!$this->isPreserveColor() && method_exists($i, "setcolorspace")) {
                $i->setcolorspace(\Imagick::COLORSPACE_SRGB);
            }

            if (!$this->isPreserveColor() && $this->isVectorGraphic($imagePath)) {
                // only for vector graphics
                // the below causes problems with PSDs when target format is PNG32 (nobody knows why ;-))
                $i->setBackgroundColor(new \ImagickPixel('transparent'));
            }

            if (isset($options["resolution"])) {
                // set the resolution to 2000x2000 for known vector formats
                // otherwise this will cause problems with eg. cropPercent in the image editable (select specific area)
                // maybe there's a better solution but for now this fixes the problem
                $i->setResolution($options["resolution"]["x"], $options["resolution"]["y"]);
            }

            $imagePathLoad = $imagePath;
            if (!defined("HHVM_VERSION")) {
                $imagePathLoad .= "[0]"; // not supported by HHVM implementation - selects the first layer/page in layered/pages file formats
            }

            if (!$i->readImage($imagePathLoad) || !filesize($imagePath)) {
                return false;
            }

            $this->resource = $i; // this is because of HHVM which has problems with $this->resource->readImage();

            // set dimensions
            $dimensions = $this->getDimensions();
            $this->setWidth($dimensions["width"]);
            $this->setHeight($dimensions["height"]);

            // check if image can have alpha channel
            if (!$this->reinitializing) {
                $alphaChannel = $i->getImageAlphaChannel();
                if ($alphaChannel) {
                    $this->setIsAlphaPossible(true);
                }
            }

            if (!$this->isPreserveColor()) {
                $this->setColorspaceToRGB();
            }
        } catch (\Exception $e) {
            \Pimcore\Log\Simple::log('imagick', "Unable to load image: " . $imagePath);
            \Pimcore\Log\Simple::log('imagick', $e->getMessage() ."\n" . $e->getTraceAsString());

            return false;
        }


        $this->setModified(false);

        return $this;
    }

    /**
     * @param $path
     * @param null $format
     * @param null $quality
     * @return $this|mixed
     * @throws \Exception
     */
    public function save($path, $format = null, $quality = null)
    {
        if (!$format) {
            $format = "png32";
        }
        $format = strtolower($format);

        if ($format == "png") {
            // we need to force imagick to create png32 images, otherwise this can cause some strange effects
            // when used with gray-scale images
            $format = "png32";
        }
        if ($format == "original") {
            $format = strtolower($this->resource->getImageFormat());
        }

        $originalFilename = null;
        if (!$this->reinitializing) {
            if ($this->getUseContentOptimizedFormat()) {
                $format = "jpeg";
                if ($this->hasAlphaChannel()) {
                    $format = "png32";
                }
            }
        }

        $i = $this->resource; // this is because of HHVM which has problems with $this->resource->writeImage();

        if (in_array($format, ["jpeg", "pjpeg", "jpg"]) && $this->isAlphaPossible) {
            // set white background for transparent pixels
            $i->setImageBackgroundColor("#ffffff");

            // Imagick version compatibility
            $alphaChannel = 11; // This works at least as far back as version 3.1.0~rc1-1
            if (defined("Imagick::ALPHACHANNEL_REMOVE")) {
                // Imagick::ALPHACHANNEL_REMOVE has been added in 3.2.0b2
                $alphaChannel = \Imagick::ALPHACHANNEL_REMOVE;
            }

            $i->setImageAlphaChannel($alphaChannel);
            $i->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
        }

        if (!$this->isPreserveMetaData()) {
            $i->stripImage();
        }
        if (!$this->isPreserveColor()) {
            $i->profileImage('*', null);
        }
        $i->setImageFormat($format);

        if ($quality && !$this->isPreserveColor()) {
            $i->setCompressionQuality((int) $quality);
            $i->setImageCompressionQuality((int) $quality);
        }

        if ($format == "tiff") {
            $i->setCompression(\Imagick::COMPRESSION_LZW);
        }

        // force progressive JPEG if filesize >= 10k
        // normally jpeg images are bigger than 10k so we avoid the double compression (baseline => filesize check => if necessary progressive)
        // and check the dimensions here instead to faster generate the image
        // progressive JPEG - better compression, smaller filesize, especially for web optimization
        if ($format == "jpeg" && !$this->isPreserveColor()) {
            if (($this->getWidth() * $this->getHeight()) > 35000) {
                $i->setInterlaceScheme(\Imagick::INTERLACE_PLANE);
            }
        }

        // Imagick isn't able to work with custom stream wrappers, so we make a workaround
        $realTargetPath = null;
        if (!stream_is_local($path)) {
            $realTargetPath = $path;
            $path = PIMCORE_SYSTEM_TEMP_DIRECTORY . "/imagick-tmp-" . uniqid() . "." . File::getFileExtension($path);
        }

        if (defined("HHVM_VERSION")) {
            $success = $i->writeImage($path);
        } else {
            $success = $i->writeImage($format . ":" . $path);
        }

        if (!$success) {
            throw new \Exception("Unable to write image: ", $path);
        }

        if ($realTargetPath) {
            File::rename($path, $realTargetPath);
        }

        return $this;
    }

    /**
     * @return  void
     */
    protected function destroy()
    {
        if ($this->resource) {
            $this->resource->clear();
            $this->resource->destroy();
            $this->resource = null;
        }
    }

    /**
     * @return bool
     */
    protected function hasAlphaChannel()
    {
        if ($this->isAlphaPossible) {
            $width = $this->resource->getImageWidth(); // Get the width of the image
            $height = $this->resource->getImageHeight(); // Get the height of the image

            // We run the image pixel by pixel and as soon as we find a transparent pixel we stop and return true.
            for ($i = 0; $i < $width; $i++) {
                for ($j = 0; $j < $height; $j++) {
                    $pixel = $this->resource->getImagePixelColor($i, $j);
                    $color = $pixel->getColor(true); // get the real alpha not just 1/0
                    if ($color["a"] < 1) { // if there's an alpha pixel, return true
                        return true;
                    }
                }
            }
        }

        // If we dont find any pixel the function will return false.
        return false;
    }

    /**
     * @return $this
     */
    public function setColorspaceToRGB()
    {
        $imageColorspace = $this->resource->getImageColorspace();

        if ($imageColorspace == \Imagick::COLORSPACE_CMYK) {
            if (self::getCMYKColorProfile() && self::getRGBColorProfile()) {
                $profiles = $this->resource->getImageProfiles('*', false);
                // we're only interested if ICC profile(s) exist
                $has_icc_profile = (array_search('icc', $profiles) !== false);
                // if it doesn't have a CMYK ICC profile, we add one
                if ($has_icc_profile === false) {
                    $this->resource->profileImage('icc', self::getCMYKColorProfile());
                }
                // then we add an RGB profile
                $this->resource->profileImage('icc', self::getRGBColorProfile());
                $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB); // we have to use SRGB here, no clue why but it works
            } else {
                $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB);
            }
        } elseif ($imageColorspace == \Imagick::COLORSPACE_GRAY) {
            $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB);
        } elseif (!in_array($imageColorspace, [\Imagick::COLORSPACE_RGB, \Imagick::COLORSPACE_SRGB])) {
            $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB);
        } else {
            // this is to handle embedded icc profiles in the RGB/sRGB colorspace
            $profiles = $this->resource->getImageProfiles('*', false);
            $has_icc_profile = (array_search('icc', $profiles) !== false);
            if ($has_icc_profile) {
                try {
                    // if getImageColorspace() says SRGB but the embedded icc profile is CMYK profileImage() will throw an exception
                    $this->resource->profileImage('icc', self::getRGBColorProfile());
                } catch (\Exception $e) {
                    \Pimcore\Log\Simple::log('imagick', $e->getMessage() ."\n" . $e->getTraceAsString());
                }
            }
        }

        // this is a HACK to force grayscale images to be real RGB - truecolor, this is important if you want to use
        // thumbnails in PDF's because they do not support "real" grayscale JPEGs or PNGs
        // problem is described here: http://imagemagick.org/Usage/basics/#type
        // and here: http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=6888#p31891
        $currentLocale = setlocale(LC_ALL, "0"); // this locale hack thing is also a hack for imagick
        setlocale(LC_ALL, "en"); // Set locale to "en" for ImagickDraw::point() to ensure the involved tostring() methods keep the decimal point

        $draw = new \ImagickDraw();
        $draw->setFillColor("#ff0000");
        $draw->setfillopacity(.01);
        $draw->point(floor($this->getWidth()/2), floor($this->getHeight()/2)); // place it in the middle of the image
        $this->resource->drawImage($draw);

        setlocale(LC_ALL, $currentLocale); // see setlocale() above, for details ;-)

        return $this;
    }

    /**
     * @param string $CMYKColorProfile
     */
    public static function setCMYKColorProfile($CMYKColorProfile)
    {
        self::$CMYKColorProfile = $CMYKColorProfile;
    }

    /**
     * @return string
     */
    public static function getCMYKColorProfile()
    {
        if (!self::$CMYKColorProfile) {
            $path = Config::getSystemConfig()->assets->icc_cmyk_profile;
            if (!$path || !file_exists($path)) {
                $path = __DIR__ . "/../icc-profiles/ISOcoated_v2_eci.icc"; // default profile
            }

            if ($path && file_exists($path)) {
                self::$CMYKColorProfile = file_get_contents($path);
            }
        }

        return self::$CMYKColorProfile;
    }

    /**
     * @param string $RGBColorProfile
     */
    public static function setRGBColorProfile($RGBColorProfile)
    {
        self::$RGBColorProfile = $RGBColorProfile;
    }

    /**
     * @return string
     */
    public static function getRGBColorProfile()
    {
        if (!self::$RGBColorProfile) {
            $path = Config::getSystemConfig()->assets->icc_rgb_profile;
            if (!$path || !file_exists($path)) {
                $path = __DIR__ . "/../icc-profiles/sRGB_IEC61966-2-1_black_scaled.icc"; // default profile
            }

            if (file_exists($path)) {
                self::$RGBColorProfile = file_get_contents($path);
            }
        }

        return self::$RGBColorProfile;
    }

    /**
     * @param  $width
     * @param  $height
     * @return self
     */
    public function resize($width, $height)
    {
        $this->preModify();

        // this is the check for vector formats because they need to have a resolution set
        // this does only work if "resize" is the first step in the image-pipeline

        if ($this->isVectorGraphic()) {
            // the resolution has to be set before loading the image, that's why we have to destroy the instance and load it again
            $res = $this->resource->getImageResolution();
            $x_ratio = $res['x'] / $this->getWidth();
            $y_ratio = $res['y'] / $this->getHeight();
            $this->resource->removeImage();

            $newRes = ["x" => $width * $x_ratio, "y" => $height * $y_ratio];

            // only use the calculated resolution if we need a higher one that the one we got from the metadata (getImageResolution)
            // this is because sometimes the quality is much better when using the "native" resolution from the metadata
            if ($newRes["x"] > $res["x"] && $newRes["y"] > $res["y"]) {
                $this->resource->setResolution($newRes["x"], $newRes["y"]);
            } else {
                $this->resource->setResolution($res["x"], $res["y"]);
            }

            $this->resource->readImage($this->imagePath);
            $this->setColorspaceToRGB();
        }

        $width  = (int)$width;
        $height = (int)$height;

        $this->resource->resizeimage($width, $height, \Imagick::FILTER_UNDEFINED, 1, false);

        $this->setWidth($width);
        $this->setHeight($height);

        $this->postModify();

        return $this;
    }

    /**
     * @param  $x
     * @param  $y
     * @param  $width
     * @param  $height
     * @return self
     */
    public function crop($x, $y, $width, $height)
    {
        $this->preModify();

        $this->resource->cropImage($width, $height, $x, $y);
        $this->resource->setImagePage($width, $height, 0, 0);

        $this->setWidth($width);
        $this->setHeight($height);

        $this->postModify();

        return $this;
    }


    /**
     * @param $width
     * @param $height
     * @return $this
     */
    public function frame($width, $height)
    {
        $this->preModify();

        $this->contain($width, $height);

        $x = ($width - $this->getWidth()) / 2;
        $y = ($height - $this->getHeight()) / 2;


        $newImage = $this->createImage($width, $height);
        $newImage->compositeImage($this->resource, \Imagick::COMPOSITE_DEFAULT, $x, $y);
        $this->resource = $newImage;

        $this->setWidth($width);
        $this->setHeight($height);

        $this->postModify();

        $this->setIsAlphaPossible(true);

        return $this;
    }

    /**
     * @param  $tolerance
     * @return self
     */
    public function trim($tolerance)
    {
        $this->preModify();

        $this->resource->trimimage($tolerance);

        $dimensions = $this->getDimensions();
        $this->setWidth($dimensions['width']);
        $this->setHeight($dimensions['height']);

        $this->postModify();

        return $this;
    }

    /**
     * @param  $color
     * @return self
     */
    public function setBackgroundColor($color)
    {
        $this->preModify();

        $newImage = $this->createImage($this->getWidth(), $this->getHeight(), $color);
        $newImage->compositeImage($this->resource, \Imagick::COMPOSITE_DEFAULT, 0, 0);
        $this->resource = $newImage;

        $this->postModify();

        $this->setIsAlphaPossible(false);

        return $this;
    }

    /**
     * @param $width
     * @param $height
     * @return Imagick
     */
    protected function createImage($width, $height, $color = "transparent")
    {
        $newImage = new \Imagick();
        $newImage->newimage($width, $height, $color);
        $newImage->setImageFormat($this->resource->getImageFormat());

        return $newImage;
    }


    /**
     * @param $angle
     * @return $this
     */
    public function rotate($angle)
    {
        $this->preModify();

        $this->resource->rotateImage(new \ImagickPixel('none'), $angle);
        $this->setWidth($this->resource->getimagewidth());
        $this->setHeight($this->resource->getimageheight());

        $this->postModify();

        $this->setIsAlphaPossible(true);

        return $this;
    }


    /**
     * @param $width
     * @param $height
     * @return $this
     */
    public function roundCorners($width, $height)
    {
        $this->preModify();

        $this->resource->roundCorners($width, $height);

        $this->postModify();

        $this->setIsAlphaPossible(true);

        return $this;
    }


    /**
     * @param $image
     * @param null|string $mode
     * @return $this
     */
    public function setBackgroundImage($image, $mode = null)
    {
        $this->preModify();

        $image = ltrim($image, "/");
        $image = PIMCORE_DOCUMENT_ROOT . "/" . $image;

        if (is_file($image)) {
            $newImage = new \Imagick();
            $newImage->readimage($image);

            if ($mode == "cropTopLeft") {
                $newImage->cropImage($this->getWidth(), $this->getHeight(), 0, 0);
            } else {
                // default behavior (fit)
                $newImage->resizeimage($this->getWidth(), $this->getHeight(), \Imagick::FILTER_UNDEFINED, 1, false);
            }

            $newImage->compositeImage($this->resource, \Imagick::COMPOSITE_DEFAULT, 0, 0);
            $this->resource = $newImage;
        }

        $this->postModify();

        return $this;
    }

    /**
     * @param string $image
     * @param int $x Amount of horizontal pixels the overlay should be offset from the origin
     * @param int $y Amount of vertical pixels the overlay should be offset from the origin
     * @param int $alpha Opacity in a scale of 0 (transparent) to 100 (opaque)
     * @param string $origin Origin of the X and Y coordinates (top-left, top-right, bottom-left, bottom-right or center)
     * @return self
     */
    public function addOverlay($image, $x = 0, $y = 0, $alpha = 100, $composite = "COMPOSITE_DEFAULT", $origin = 'top-left')
    {
        $this->preModify();

        // 100 alpha is default
        if (empty($alpha)) {
            $alpha = 100;
        }
        $alpha = round($alpha / 100, 1);

        //Make sure the composite constant exists.
        if (is_null(constant("Imagick::" . $composite))) {
            $composite = "COMPOSITE_DEFAULT";
        }

        $newImage = null;

        if (is_string($image)) {
            $image = ltrim($image, "/");
            $image = PIMCORE_DOCUMENT_ROOT . "/" . $image;

            $newImage = new \Imagick();
            $newImage->readimage($image);
        } elseif ($image instanceof \Imagick) {
            $newImage = $image;
        }

        if ($newImage) {
            if ($origin == 'top-right') {
                $x = $this->resource->getImageWidth() - $newImage->getImageWidth() - $x;
            } elseif ($origin == 'bottom-left') {
                $y = $this->resource->getImageHeight() - $newImage->getImageHeight() - $y;
            } elseif ($origin == 'bottom-right') {
                $x = $this->resource->getImageWidth() - $newImage->getImageWidth() - $x;
                $y = $this->resource->getImageHeight() - $newImage->getImageHeight() - $y;
            } elseif ($origin == 'center') {
                $x = round($this->resource->getImageWidth() / 2) - round($newImage->getImageWidth() / 2) + $x;
                $y = round($this->resource->getImageHeight() / 2) -round($newImage->getImageHeight() / 2) + $y;
            }

            $newImage->evaluateImage(\Imagick::EVALUATE_MULTIPLY, $alpha, \Imagick::CHANNEL_ALPHA);
            $this->resource->compositeImage($newImage, constant("Imagick::" . $composite), $x, $y);
        }

        $this->postModify();

        return $this;
    }

    /**
     * @param $image
     * @param string $composite
     * @return $this
     */
    public function addOverlayFit($image, $composite = "COMPOSITE_DEFAULT")
    {
        $image = ltrim($image, "/");
        $image = PIMCORE_DOCUMENT_ROOT . "/" . $image;

        $newImage = new \Imagick();
        $newImage->readimage($image);
        $newImage->resizeimage($this->getWidth(), $this->getHeight(), \Imagick::FILTER_UNDEFINED, 1, false);

        $this->addOverlay($newImage, 0, 0, 100, $composite);

        return $this;
    }

    /**
     * @param  $image
     * @return self
     */
    public function applyMask($image)
    {
        $this->preModify();
        $image = ltrim($image, "/");
        $image = PIMCORE_DOCUMENT_ROOT . "/" . $image;

        if (is_file($image)) {
            $this->resource->setImageMatte(1);
            $newImage = new \Imagick();
            $newImage->readimage($image);
            $newImage->resizeimage($this->getWidth(), $this->getHeight(), \Imagick::FILTER_UNDEFINED, 1, false);
            $this->resource->compositeImage($newImage, \Imagick::COMPOSITE_COPYOPACITY, 0, 0, \Imagick::CHANNEL_ALPHA);
        }

        $this->postModify();

        $this->setIsAlphaPossible(true);

        return $this;
    }


    /**
     * @return self
     */
    public function grayscale()
    {
        $this->preModify();
        $this->resource->setImageType(\Imagick::IMGTYPE_GRAYSCALEMATTE);
        $this->postModify();

        return $this;
    }

    /**
     * @return self
     */
    public function sepia()
    {
        $this->preModify();
        $this->resource->sepiatoneimage(85);
        $this->postModify();

        return $this;
    }

    /**
     * @param int $radius
     * @param float $sigma
     * @param float $amount
     * @param float $threshold
     * @return $this|Adapter
     */
    public function sharpen($radius = 0, $sigma = 1.0, $amount = 1.0, $threshold = 0.05)
    {
        $this->preModify();
        $this->resource->normalizeImage();
        $this->resource->unsharpMaskImage($radius, $sigma, $amount, $threshold);
        $this->postModify();

        return $this;
    }

    /**
     * @param int $radius
     * @param float $sigma
     * @return $this|Adapter
     */
    public function gaussianBlur($radius = 0, $sigma = 1.0)
    {
        $this->preModify();
        $this->resource->gaussianBlurImage($radius, $sigma);
        $this->postModify();

        return $this;
    }

    /**
     * @param int $brightness
     * @param int $saturation
     * @param int $hue
     * @return $this
     */
    public function brightnessSaturation($brightness = 100, $saturation = 100, $hue = 100)
    {
        $this->preModify();
        $this->resource->modulateImage($brightness, $saturation, $hue);
        $this->postModify();

        return $this;
    }

    /**
     * @param $mode
     * @return $this|Adapter
     */
    public function mirror($mode)
    {
        $this->preModify();

        if ($mode == "vertical") {
            $this->resource->flipImage();
        } elseif ($mode == "horizontal") {
            $this->resource->flopImage();
        }

        $this->postModify();

        return $this;
    }

    /**
     * @param null $imagePath
     * @return bool
     */
    public function isVectorGraphic($imagePath = null)
    {
        if (!$imagePath) {
            $imagePath = $this->imagePath;
        }

        // we need to do this check first, because ImageMagick using the inkscape delegate returns "PNG" when calling
        // getimageformat() onto SVG graphics, this is a workaround to avoid problems
        if (preg_match("@\.(svgz?|eps|pdf|ps|ai|indd)$@", $imagePath)) {
            return true;
        }

        try {
            if ($this->resource) {
                $type = $this->resource->getimageformat();
                $vectorTypes = [
                    "EPT",
                    "EPDF",
                    "EPI",
                    "EPS",
                    "EPS2",
                    "EPS3",
                    "EPSF",
                    "EPSI",
                    "EPT",
                    "PDF",
                    "PFA",
                    "PFB",
                    "PFM",
                    "PS",
                    "PS2",
                    "PS3",
                    "SVG",
                    "SVGZ",
                    "MVG"
                ];

                if (in_array(strtoupper($type), $vectorTypes)) {
                    return true;
                }
            }
        } catch (\Exception $e) {
            \Pimcore\Log\Simple::log('imagick', $e->getMessage() ."\n" . $e->getTraceAsString());
        }

        return false;
    }

    /**
     * @return array
     */
    public function getDimensions()
    {
        if ($vectorDimensions = $this->getVectorFormatEmbeddedRasterDimensions()) {
            return $vectorDimensions;
        }

        return [
            "width" => $this->resource->getImageWidth(),
            "height" => $this->resource->getImageHeight()
        ];
    }

    /**
     * @return array|null
     */
    public function getVectorFormatEmbeddedRasterDimensions()
    {
        if (in_array($this->resource->getimageformat(), ["EPT", "EPDF", "EPI", "EPS", "EPS2", "EPS3", "EPSF", "EPSI", "EPT", "PDF", "PFA", "PFB", "PFM", "PS", "PS2", "PS3"])) {
            // we need a special handling for PhotoShop EPS
            $i = 0;

            ini_set("auto_detect_line_endings", true); // we need to turn this on, as the damn f****** Mac has different line endings in EPS files, Prost Mahlzeit!

            $epsFile = fopen($this->imagePath, 'r');
            while (($eps_line = fgets($epsFile)) && ($i < 100)) {
                if (preg_match("/%ImageData: ([0-9]+) ([0-9]+)/i", $eps_line, $matches)) {
                    return [
                        "width" => $matches[1],
                        "height" => $matches[2]
                    ];
                    break;
                }
                $i++;
            }
        }

        return null;
    }

    /**
     * @return array
     */
    public function getVectorRasterDimensions()
    {
        if ($vectorDimensions = $this->getVectorFormatEmbeddedRasterDimensions()) {
            return $vectorDimensions;
        }

        return parent::getVectorRasterDimensions();
    }
}
