The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
└── src
    ├── Draw
        ├── AlphaBlendingAwareDrawerInterface.php
        └── DrawerInterface.php
    ├── Driver
        ├── AbstractInfo.php
        ├── Info.php
        └── InfoProvider.php
    ├── Effects
        └── EffectsInterface.php
    ├── Exception
        ├── Exception.php
        ├── InvalidArgumentException.php
        ├── NotFoundException.php
        ├── NotSupportedException.php
        ├── OutOfBoundsException.php
        └── RuntimeException.php
    ├── Factory
        ├── ClassFactory.php
        ├── ClassFactoryAwareInterface.php
        └── ClassFactoryInterface.php
    ├── File
        ├── Loader.php
        └── LoaderInterface.php
    ├── Filter
        ├── Advanced
        │   ├── BlackWhite.php
        │   ├── Border.php
        │   ├── BorderDetection.php
        │   ├── Canvas.php
        │   ├── Grayscale.php
        │   ├── Negation.php
        │   ├── Neighborhood.php
        │   ├── OnPixelBased.php
        │   └── RelativeResize.php
        ├── Basic
        │   ├── ApplyMask.php
        │   ├── Autorotate.php
        │   ├── Copy.php
        │   ├── Crop.php
        │   ├── Fill.php
        │   ├── FlipHorizontally.php
        │   ├── FlipVertically.php
        │   ├── Paste.php
        │   ├── Resize.php
        │   ├── Rotate.php
        │   ├── Save.php
        │   ├── Show.php
        │   ├── Strip.php
        │   ├── Thumbnail.php
        │   └── WebOptimization.php
        ├── FilterInterface.php
        ├── ImagineAware.php
        └── Transformation.php
    ├── Gd
        ├── Drawer.php
        ├── DriverInfo.php
        ├── Effects.php
        ├── Font.php
        ├── Image.php
        ├── Imagine.php
        └── Layers.php
    ├── Gmagick
        ├── Drawer.php
        ├── DriverInfo.php
        ├── Effects.php
        ├── Font.php
        ├── Image.php
        ├── Imagine.php
        └── Layers.php
    ├── Image
        ├── AbstractFont.php
        ├── AbstractImage.php
        ├── AbstractImagine.php
        ├── AbstractLayers.php
        ├── Box.php
        ├── BoxInterface.php
        ├── Fill
        │   ├── FillInterface.php
        │   └── Gradient
        │   │   ├── Horizontal.php
        │   │   ├── Linear.php
        │   │   └── Vertical.php
        ├── FontInterface.php
        ├── Format.php
        ├── FormatList.php
        ├── Histogram
        │   ├── Bucket.php
        │   └── Range.php
        ├── ImageInterface.php
        ├── ImagineInterface.php
        ├── LayersInterface.php
        ├── ManipulatorInterface.php
        ├── Metadata
        │   ├── AbstractMetadataReader.php
        │   ├── DefaultMetadataReader.php
        │   ├── ExifMetadataReader.php
        │   ├── MetadataBag.php
        │   └── MetadataReaderInterface.php
        ├── Palette
        │   ├── CMYK.php
        │   ├── Color
        │   │   ├── CMYK.php
        │   │   ├── ColorInterface.php
        │   │   ├── Gray.php
        │   │   └── RGB.php
        │   ├── ColorParser.php
        │   ├── Grayscale.php
        │   ├── PaletteInterface.php
        │   └── RGB.php
        ├── Point.php
        ├── Point
        │   └── Center.php
        ├── PointInterface.php
        ├── PointSigned.php
        ├── Profile.php
        └── ProfileInterface.php
    ├── Imagick
        ├── Drawer.php
        ├── DriverInfo.php
        ├── Effects.php
        ├── Font.php
        ├── Image.php
        ├── Imagine.php
        └── Layers.php
    ├── Utils
        ├── ErrorHandling.php
        └── Matrix.php
    └── resources
        ├── Adobe
            ├── CMYK
            │   ├── CoatedFOGRA27.icc
            │   ├── CoatedFOGRA39.icc
            │   ├── CoatedGRACoL2006.icc
            │   ├── JapanColor2001Coated.icc
            │   ├── JapanColor2001Uncoated.icc
            │   ├── JapanColor2002Newspaper.icc
            │   ├── JapanColor2003WebCoated.icc
            │   ├── JapanWebCoated.icc
            │   ├── USWebCoatedSWOP.icc
            │   ├── USWebUncoated.icc
            │   ├── UncoatedFOGRA29.icc
            │   ├── WebCoatedFOGRA28.icc
            │   ├── WebCoatedSWOP2006Grade3.icc
            │   └── WebCoatedSWOP2006Grade5.icc
            ├── Color Profile Bundling License_10.15.08.md
            ├── RGB
            │   ├── AdobeRGB1998.icc
            │   ├── AppleRGB.icc
            │   ├── ColorMatchRGB.icc
            │   ├── PAL_SECAM.icc
            │   ├── SMPTE-C.icc
            │   ├── VideoHD.icc
            │   ├── VideoNTSC.icc
            │   └── VideoPAL.icc
            └── Trademark Information.md
        ├── color.org
            ├── sRGB_IEC61966-2-1_black_scaled.icc
            └── sRGB_IEC61966-2-1_no_black_scaling.icc
        └── colormanagement.org
            └── ISOcoated_v2_grey1c_bas.ICC


/LICENSE:
--------------------------------------------------------------------------------
 1 | Copyright (c) 2004-2012 Bulat Shakirzyanov
 2 | 
 3 | Permission is hereby granted, free of charge, to any person obtaining a copy
 4 | of this software and associated documentation files (the "Software"), to deal
 5 | in the Software without restriction, including without limitation the rights
 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 7 | copies of the Software, and to permit persons to whom the Software is furnished
 8 | to do so, subject to the following conditions:
 9 | 
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 | 
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 | 
21 | This software embeds Adobe ICC Profiles, see license at
22 | http://www.adobe.com/support/downloads/iccprofiles/icc_eula_mac_dist.html .
23 | 
24 | This software also embeds ICC Profile from colormanagement.org. Please
25 | find information about their license at http://colormanagement.org/ .
26 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | # Imagine
  2 | [![PHPUnit](https://github.com/php-imagine/Imagine/actions/workflows/phpunit.yml/badge.svg)](https://github.com/php-imagine/Imagine/actions/workflows/phpunit.yml)
  3 | [![Coding Style](https://github.com/php-imagine/Imagine/actions/workflows/coding-style.yml/badge.svg)](https://github.com/php-imagine/Imagine/actions/workflows/coding-style.yml)
  4 | 
  5 | Tweet about it using the [#php_imagine](https://twitter.com/search?q=%23php_imagine) hashtag.
  6 | 
  7 | Image manipulation library for PHP inspired by Python's PIL and other image
  8 | libraries.
  9 | 
 10 | ## Requirements
 11 | 
 12 | The Imagine library has the following requirements:
 13 | 
 14 |  - PHP 7.1+
 15 | 
 16 | Older version of the library support also older PHP Version:
 17 | 
 18 |  - PHP 5.5 - 7.0 use version ^1.3
 19 |  - PHP 5.3 - 5.4 use version ^1.2
 20 | 
 21 | Depending on the chosen Image implementation, you may need one of the following PHP extensions:
 22 | 
 23 |  - GD2
 24 |  - Imagick (with ImageMagick version 6.2.9 or later, except version 7.0.7-32)
 25 |  - Gmagick
 26 | 
 27 | To read EXIF metadata (e.g. for autorotation), activate the PHP ``exif`` extension. This is optional: Imagine works
 28 | without the PHP ``exif`` extension, but then it can't read and act on image orientation or other EXIF metadata.
 29 | 
 30 | ### Installation using composer
 31 | `php composer.phar require imagine/imagine`
 32 | 
 33 | ## Basic Principles
 34 | 
 35 | The main purpose of Imagine is to provide all the necessary functionality to bring all native low level image processing libraries in PHP to the same simple and intuitive OO API.
 36 | 
 37 | Several things are necessary to accomplish that:
 38 | 
 39 | * Image manipulation tools, such as resize, crop, etc.
 40 | * Drawing API - to create basic shapes and advanced charts, write text on the image
 41 | * Masking functionality - ability to apply black&white or grayscale images as masks, leading to semi-transparency or absolute transparency of the image the mask is being applied to
 42 | 
 43 | The above tools should be the basic foundation for a more powerful set of tools that are called ``Filters`` in Imagine.
 44 | 
 45 | Some of the ideas for upcoming filters:
 46 | 
 47 | * Charting and graphing filters - pie and bar charts, linear graphs with annotations
 48 | * Reflection - apple style
 49 | * Rounded corners - web 2.0
 50 | 
 51 | ## Documentation ##
 52 | 
 53 |  - [Hosted by Read The Docs](http://imagine.readthedocs.org/)
 54 | 
 55 | ## Presentations ##
 56 | 
 57 |  - [Introduction to Imagine](http://www.slideshare.net/avalanche123/introduction-toimagine)
 58 |  - [How to Take Over the World with Lithium](http://speakerdeck.com/u/nateabele/p/how-to-take-over-the-world-with-lithium?slide=33)
 59 | 
 60 | ## Articles ##
 61 | 
 62 |  - [Image Processing with Imagine](http://www.phparch.com/2011/03/image-processing-with-imagine)
 63 | 
 64 | ## Contributing ##
 65 | 
 66 | ### Branches
 67 | 
 68 | New pull requests should be based on the `develop` branch.
 69 | The `master` branch is the stable branch: it usually matches the latest a release but in can be a bit ahead.
 70 | 
 71 | ### Test groups
 72 | 
 73 | Some PHPUnit test is marked as skipped (for example, tests that require a driver that support multiple layers and executed with the GD driver).
 74 | In addition, if you don't have installed gmagick, the gmagick tests will be marked as skipped.
 75 | 
 76 | If you don't want to run tests that are marked as "always skipped" you can tell PHPUnit to exclude the `always-skipped` group.
 77 | The same for the tests that require a specific driver (`gd`, `imagick`, `imagick`).
 78 | 
 79 | So, for example, to exclude the `always-skipped` and the `gmagick` tests, you can launch phpunit with this command options:
 80 | 
 81 | ```
 82 | composer run test -- --exclude-group always-skipped,gmagick
 83 | ```
 84 | 
 85 | 
 86 | ### Development environment
 87 | 
 88 | Setting up an environment with all the required libraries may be very hard.
 89 | In order to run the tests locally, you can use the same [docker images](https://github.com/php-imagine/docker-builder/pkgs/container/test) used by Imagine to test the pull requests.
 90 | 
 91 | For example, if you have Imagine locally in the `/home/me/imagine` folder, you can run tests for PHP 8.1 with the GD and Imagick with this very simple approach:
 92 | 
 93 | 1. Launch a temporary docker container with:
 94 |    ```sh
 95 |    docker run --rm -it -v /home/me/imagine:/app -w /app ghcr.io/php-imagine/test:8.1-gd-imagick bash
 96 |    ```
 97 | 2. Inside the docker container, run these commands:
 98 |    ```sh
 99 |    # Start a local web server: some tests require it
100 |    cd tests
101 |    php -n -S 0.0.0.0:8013 >/dev/null 2>&1 &
102 |    cd ..
103 |    # Tell the tests that the local web server is available at the port 8013
104 |    export IMAGINE_TEST_WEBSERVERURL=http://localhost:8013
105 |    # Install the composer dependencies
106 |    composer update
107 |    # Run the tests
108 |    composer run test -- --exclude-group always-skipped,gmagick
109 |    ```
110 | 
111 | > Note: This approach works on Windows too: simply launch the docker container with
112 | > ```
113 | > docker run --rm -it -v C:\Path\To\Imagine:/app -w /app ghcr.io/php-imagine/test:8.1-gd-imagick bash
114 | > ```
115 | 
116 | ### Built test files
117 | 
118 | Many tests create temporary files (in the `tests/tmp` directory) containing built images.
119 | Those temporary files are compared with expected images, and then are deleted.
120 | If you want to keep those temporary files (for example, to check what's being built), you can set the `IMAGINE_TEST_KEEP_TEMPFILES` environment variable.
121 | If the `IMAGINE_TEST_KEEP_TEMPFILES` is configured in the GitHub Action tests, those temporary files are attached to tests as an articact.
122 | 


--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
 1 | {
 2 |     "name": "imagine/imagine",
 3 |     "description": "Image processing for PHP",
 4 |     "keywords": [
 5 |         "image manipulation",
 6 |         "image processing",
 7 |         "drawing",
 8 |         "graphics"
 9 |     ],
10 |     "homepage": "http://imagine.readthedocs.org/",
11 |     "license": "MIT",
12 |     "authors": [
13 |         {
14 |             "name": "Bulat Shakirzyanov",
15 |             "email": "mallluhuct@gmail.com",
16 |             "homepage": "http://avalanche123.com"
17 |         }
18 |     ],
19 |     "require": {
20 |         "php": ">=7.1"
21 |     },
22 |     "require-dev": {
23 |         "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4 || ^9.3"
24 |     },
25 |     "suggest": {
26 |         "ext-exif": "to read EXIF metadata",
27 |         "ext-gd": "to use the GD implementation",
28 |         "ext-imagick": "to use the Imagick implementation",
29 |         "ext-gmagick": "to use the Gmagick implementation"
30 |     },
31 |     "autoload": {
32 |         "psr-4": {
33 |             "Imagine\\": "src/"
34 |         }
35 |     },
36 |     "autoload-dev": {
37 |         "psr-4": {
38 |             "Imagine\\Test\\": "tests/tests/"
39 |         }
40 |     },
41 |     "extra": {
42 |         "branch-alias": {
43 |             "dev-develop": "1.x-dev"
44 |         }
45 |     },
46 |     "archive": {
47 |         "exclude": [
48 |             "/.*",
49 |             "/tests",
50 |             "/vendor",
51 |             "/bin",
52 |             "docs/_build",
53 |             "Imagine-*.tgz",
54 |             "imagine-*.phar",
55 |             "composer.phar"
56 |         ]
57 |     },
58 |     "scripts": {
59 |         "test": "phpunit --verbose"
60 |     }
61 | }
62 | 


--------------------------------------------------------------------------------
/src/Draw/AlphaBlendingAwareDrawerInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | namespace Imagine\Draw;
 4 | 
 5 | /**
 6 |  * Interface for the drawers that support configuring the alpha blending.
 7 |  */
 8 | interface AlphaBlendingAwareDrawerInterface extends DrawerInterface
 9 | {
10 |     /**
11 |      * Is the alpha blending activated?
12 |      *
13 |      * @return bool
14 |      */
15 |     public function getAlphaBlending();
16 | 
17 |     /**
18 |      * Enable/disable the alpha blending.
19 |      *
20 |      * @param bool $value
21 |      *
22 |      * @return $this
23 |      */
24 |     public function setAlphaBlending($value);
25 | 
26 |     /**
27 |      * Create a new instance of this drawer with the specified alpha blending value.
28 |      *
29 |      * @param bool $value
30 |      *
31 |      * @return static
32 |      */
33 |     public function withAlphaBlending($value);
34 | }
35 | 


--------------------------------------------------------------------------------
/src/Draw/DrawerInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Draw;
 13 | 
 14 | use Imagine\Image\AbstractFont;
 15 | use Imagine\Image\BoxInterface;
 16 | use Imagine\Image\Palette\Color\ColorInterface;
 17 | use Imagine\Image\PointInterface;
 18 | 
 19 | /**
 20 |  * Interface for the drawer.
 21 |  */
 22 | interface DrawerInterface
 23 | {
 24 |     /**
 25 |      * Draws an arc on a starting at a given x, y coordinates under a given
 26 |      * start and end angles.
 27 |      *
 28 |      * @param \Imagine\Image\PointInterface $center
 29 |      * @param \Imagine\Image\BoxInterface $size
 30 |      * @param int $start
 31 |      * @param int $end
 32 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 33 |      * @param int $thickness
 34 |      *
 35 |      * @throws \Imagine\Exception\RuntimeException
 36 |      *
 37 |      * @return $this
 38 |      */
 39 |     public function arc(PointInterface $center, BoxInterface $size, $start, $end, ColorInterface $color, $thickness = 1);
 40 | 
 41 |     /**
 42 |      * Same as arc, but also connects end points with a straight line.
 43 |      *
 44 |      * @param \Imagine\Image\PointInterface $center
 45 |      * @param \Imagine\Image\BoxInterface $size
 46 |      * @param int $start
 47 |      * @param int $end
 48 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 49 |      * @param bool $fill
 50 |      * @param int $thickness
 51 |      *
 52 |      * @throws \Imagine\Exception\RuntimeException
 53 |      *
 54 |      * @return $this
 55 |      */
 56 |     public function chord(PointInterface $center, BoxInterface $size, $start, $end, ColorInterface $color, $fill = false, $thickness = 1);
 57 | 
 58 |     /**
 59 |      * Draws and circle with center at the given x, y coordinates, and given radius.
 60 |      *
 61 |      * @param \Imagine\Image\PointInterface $center
 62 |      * @param int $radius
 63 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 64 |      * @param bool $fill
 65 |      * @param int $thickness
 66 |      *
 67 |      * @throws \Imagine\Exception\RuntimeException
 68 |      *
 69 |      * @return $this
 70 |      */
 71 |     public function circle(PointInterface $center, $radius, ColorInterface $color, $fill = false, $thickness = 1);
 72 | 
 73 |     /**
 74 |      * Draws and ellipse with center at the given x, y coordinates, and given width and height.
 75 |      *
 76 |      * @param \Imagine\Image\PointInterface $center
 77 |      * @param \Imagine\Image\BoxInterface $size
 78 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 79 |      * @param bool $fill
 80 |      * @param int $thickness
 81 |      *
 82 |      * @throws \Imagine\Exception\RuntimeException
 83 |      *
 84 |      * @return $this
 85 |      */
 86 |     public function ellipse(PointInterface $center, BoxInterface $size, ColorInterface $color, $fill = false, $thickness = 1);
 87 | 
 88 |     /**
 89 |      * Draws a line from start(x, y) to end(x, y) coordinates.
 90 |      *
 91 |      * @param \Imagine\Image\PointInterface $start
 92 |      * @param \Imagine\Image\PointInterface $end
 93 |      * @param \Imagine\Image\Palette\Color\ColorInterface $outline
 94 |      * @param int $thickness
 95 |      *
 96 |      * @return $this
 97 |      */
 98 |     public function line(PointInterface $start, PointInterface $end, ColorInterface $outline, $thickness = 1);
 99 | 
100 |     /**
101 |      * Same as arc, but connects end points and the center.
102 |      *
103 |      * @param \Imagine\Image\PointInterface $center
104 |      * @param \Imagine\Image\BoxInterface $size
105 |      * @param int $start
106 |      * @param int $end
107 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
108 |      * @param bool $fill
109 |      * @param int $thickness
110 |      *
111 |      * @throws \Imagine\Exception\RuntimeException
112 |      *
113 |      * @return $this
114 |      */
115 |     public function pieSlice(PointInterface $center, BoxInterface $size, $start, $end, ColorInterface $color, $fill = false, $thickness = 1);
116 | 
117 |     /**
118 |      * Places a one pixel point at specific coordinates and fills it with
119 |      * specified color.
120 |      *
121 |      * @param \Imagine\Image\PointInterface $position
122 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
123 |      *
124 |      * @throws \Imagine\Exception\RuntimeException
125 |      *
126 |      * @return $this
127 |      */
128 |     public function dot(PointInterface $position, ColorInterface $color);
129 | 
130 |     /**
131 |      * Draws a rectangle from left, top(x, y) to right, bottom(x, y) coordinates.
132 |      *
133 |      * @param \Imagine\Image\PointInterface $leftTop
134 |      * @param \Imagine\Image\PointInterface $rightBottom
135 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
136 |      * @param bool $fill
137 |      * @param int $thickness
138 |      *
139 |      * @throws \Imagine\Exception\RuntimeException
140 |      *
141 |      * @return $this
142 |      */
143 |     public function rectangle(PointInterface $leftTop, PointInterface $rightBottom, ColorInterface $color, $fill = false, $thickness = 1);
144 | 
145 |     /**
146 |      * Draws a polygon using array of x, y coordinates. Must contain at least three coordinates.
147 |      *
148 |      * @param \Imagine\Image\PointInterface[] $coordinates
149 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
150 |      * @param bool $fill
151 |      * @param int $thickness
152 |      *
153 |      * @throws \Imagine\Exception\RuntimeException
154 |      *
155 |      * @return $this
156 |      */
157 |     public function polygon(array $coordinates, ColorInterface $color, $fill = false, $thickness = 1);
158 | 
159 |     /**
160 |      * Annotates image with specified text at a given position starting on the top left of the final text box.
161 |      *
162 |      * The rotation is done CW
163 |      *
164 |      * @param string $string
165 |      * @param \Imagine\Image\AbstractFont $font
166 |      * @param \Imagine\Image\PointInterface $position
167 |      * @param int $angle
168 |      * @param int $width
169 |      *
170 |      * @throws \Imagine\Exception\RuntimeException
171 |      *
172 |      * @return $this
173 |      */
174 |     public function text($string, AbstractFont $font, PointInterface $position, $angle = 0, $width = null);
175 | }
176 | 


--------------------------------------------------------------------------------
/src/Driver/AbstractInfo.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | namespace Imagine\Driver;
  4 | 
  5 | use Imagine\Exception\NotSupportedException;
  6 | use Imagine\Image\Palette\PaletteInterface;
  7 | 
  8 | /**
  9 |  * Base class for the default DriverInfo classes.
 10 |  *
 11 |  * @since 1.3.0
 12 |  */
 13 | abstract class AbstractInfo implements Info
 14 | {
 15 |     /**
 16 |      * @var static|\Imagine\Exception\NotSupportedException|null
 17 |      */
 18 |     private static $instance;
 19 | 
 20 |     /**
 21 |      * @var string
 22 |      */
 23 |     private $driverRawVersion;
 24 | 
 25 |     /**
 26 |      * @var string
 27 |      */
 28 |     private $driverSemverVersion;
 29 | 
 30 |     /**
 31 |      * @var string
 32 |      */
 33 |     private $engineRawVersion;
 34 | 
 35 |     /**
 36 |      * @var string
 37 |      */
 38 |     private $engineSemverVersion;
 39 | 
 40 |     /**
 41 |      * @var \Imagine\Image\FormatList|null
 42 |      */
 43 |     private $supportedFormats = null;
 44 | 
 45 |     /**
 46 |      * @param string $driverRawVersion
 47 |      * @param string $driverSemverVersion
 48 |      * @param string $engineRawVersion
 49 |      * @param string $engineSemverVersion
 50 |      */
 51 |     protected function __construct($driverRawVersion, $driverSemverVersion, $engineRawVersion, $engineSemverVersion)
 52 |     {
 53 |         $this->driverRawVersion = $driverRawVersion;
 54 |         $this->driverSemverVersion = $driverSemverVersion;
 55 |         $this->engineRawVersion = $engineRawVersion;
 56 |         $this->engineSemverVersion = $engineSemverVersion;
 57 |     }
 58 | 
 59 |     /**
 60 |      * {@inheritdoc}
 61 |      *
 62 |      * @see \Imagine\Driver\Info::getDriverVersion()
 63 |      */
 64 |     public function getDriverVersion($raw = false)
 65 |     {
 66 |         return $raw ? $this->driverRawVersion : $this->driverSemverVersion;
 67 |     }
 68 | 
 69 |     /**
 70 |      * {@inheritdoc}
 71 |      *
 72 |      * @see \Imagine\Driver\Info::getEngineVersion()
 73 |      */
 74 |     public function getEngineVersion($raw = false)
 75 |     {
 76 |         return $raw ? $this->engineRawVersion : $this->engineSemverVersion;
 77 |     }
 78 | 
 79 |     /**
 80 |      * Check if the driver has a specific feature.
 81 |      *
 82 |      * @param int $feature The feature to be checked (see the Info::FEATURE_... constants)
 83 |      *
 84 |      * @throws \Imagine\Exception\NotSupportedException if any of the requested features is not supported
 85 |      */
 86 |     abstract protected function checkFeature($feature);
 87 | 
 88 |     /**
 89 |      * {@inheritdoc}
 90 |      *
 91 |      * @see \Imagine\Driver\Info::checkVersionIsSupported()
 92 |      */
 93 |     public function checkVersionIsSupported()
 94 |     {
 95 |         if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70100) {
 96 |             throw new NotSupportedException('Imagine requires PHP 7.1 or later');
 97 |         }
 98 |     }
 99 | 
100 |     /**
101 |      * {@inheritdoc}
102 |      *
103 |      * @see \Imagine\Driver\Info::requireFeature()
104 |      */
105 |     public function requireFeature($features)
106 |     {
107 |         $features = array_map('intval', is_array($features) ? $features : array($features));
108 |         foreach ($features as $feature) {
109 |             $this->checkFeature($feature);
110 |         }
111 |     }
112 | 
113 |     /**
114 |      * {@inheritdoc}
115 |      *
116 |      * @see \Imagine\Driver\Info::hasFeature()
117 |      */
118 |     public function hasFeature($features)
119 |     {
120 |         try {
121 |             $this->requireFeature($features);
122 |         } catch (NotSupportedException $x) {
123 |             return false;
124 |         }
125 | 
126 |         return true;
127 |     }
128 | 
129 |     /**
130 |      * Build the list of supported file formats.
131 |      *
132 |      * @return \Imagine\Image\FormatList
133 |      */
134 |     abstract protected function buildSupportedFormats();
135 | 
136 |     /**
137 |      * {@inheritdoc}
138 |      *
139 |      * @see \Imagine\Driver\Info::getSupportedFormats()
140 |      */
141 |     public function getSupportedFormats()
142 |     {
143 |         if ($this->supportedFormats === null) {
144 |             $this->supportedFormats = $this->buildSupportedFormats();
145 |         }
146 | 
147 |         return $this->supportedFormats;
148 |     }
149 | 
150 |     /**
151 |      * {@inheritdoc}
152 |      *
153 |      * @see \Imagine\Driver\Info::isFormatSupported()
154 |      */
155 |     public function isFormatSupported($format)
156 |     {
157 |         return $this->getSupportedFormats()->find($format) !== null;
158 |     }
159 | 
160 |     /**
161 |      * {@inheritdoc}
162 |      *
163 |      * @see \Imagine\Driver\Info::requirePaletteSupport()
164 |      */
165 |     public function requirePaletteSupport(PaletteInterface $palette)
166 |     {
167 |     }
168 | 
169 |     /**
170 |      * {@inheritdoc}
171 |      *
172 |      * @see \Imagine\Driver\Info::isPaletteSupported()
173 |      */
174 |     public function isPaletteSupported(PaletteInterface $palette)
175 |     {
176 |         try {
177 |             $this->requirePaletteSupport($palette);
178 |         } catch (NotSupportedException $x) {
179 |             return false;
180 |         }
181 | 
182 |         return true;
183 |     }
184 | }
185 | 


--------------------------------------------------------------------------------
/src/Driver/InfoProvider.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | namespace Imagine\Driver;
 4 | 
 5 | /**
 6 |  * Interface implemented by classes that provide info about a graphics driver.
 7 |  *
 8 |  * @since 1.3.0
 9 |  */
10 | interface InfoProvider
11 | {
12 |     /**
13 |      * Get the info about this driver.
14 |      *
15 |      * @param bool $required when the driver is not available: if FALSE the function returns NULL, if TRUE the driver throws a \Imagine\Exception\NotSupportedException
16 |      *
17 |      * @return \Imagine\Driver\Info|null
18 |      */
19 |     public static function getDriverInfo($required = true);
20 | }
21 | 


--------------------------------------------------------------------------------
/src/Effects/EffectsInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Effects;
 13 | 
 14 | use Imagine\Image\Palette\Color\ColorInterface;
 15 | use Imagine\Utils\Matrix;
 16 | 
 17 | /**
 18 |  * Interface for the effects.
 19 |  */
 20 | interface EffectsInterface
 21 | {
 22 |     /**
 23 |      * Apply gamma correction.
 24 |      *
 25 |      * @param float $correction
 26 |      *
 27 |      * @throws \Imagine\Exception\RuntimeException
 28 |      *
 29 |      * @return $this
 30 |      */
 31 |     public function gamma($correction);
 32 | 
 33 |     /**
 34 |      * Invert the colors of the image.
 35 |      *
 36 |      * @throws \Imagine\Exception\RuntimeException
 37 |      *
 38 |      * @return $this
 39 |      */
 40 |     public function negative();
 41 | 
 42 |     /**
 43 |      * Grayscale the image.
 44 |      *
 45 |      * @throws \Imagine\Exception\RuntimeException
 46 |      *
 47 |      * @return $this
 48 |      */
 49 |     public function grayscale();
 50 | 
 51 |     /**
 52 |      * Colorize the image.
 53 |      *
 54 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 55 |      *
 56 |      * @throws \Imagine\Exception\RuntimeException
 57 |      *
 58 |      * @return $this
 59 |      */
 60 |     public function colorize(ColorInterface $color);
 61 | 
 62 |     /**
 63 |      * Sharpens the image.
 64 |      *
 65 |      * @throws \Imagine\Exception\RuntimeException
 66 |      *
 67 |      * @return $this
 68 |      */
 69 |     public function sharpen();
 70 | 
 71 |     /**
 72 |      * Blur the image.
 73 |      *
 74 |      * @param float|int $sigma
 75 |      *
 76 |      * @throws \Imagine\Exception\RuntimeException
 77 |      *
 78 |      * @return $this
 79 |      */
 80 |     public function blur($sigma);
 81 | 
 82 |     /**
 83 |      * Changes the brightness of the image.
 84 |      *
 85 |      * @param int $brightness The level of brightness (-100 (black) to 100 (white))
 86 |      *
 87 |      * @throws \Imagine\Exception\RuntimeException
 88 |      *
 89 |      * @return $this
 90 |      */
 91 |     public function brightness($brightness);
 92 | 
 93 |     /**
 94 |      * Convolves the image.
 95 |      *
 96 |      * @param \Imagine\Utils\Matrix $matrix The matrix from which derive the convolution kernel
 97 |      *
 98 |      * @throws \Imagine\Exception\RuntimeException
 99 |      *
100 |      * @return $this
101 |      */
102 |     public function convolve(Matrix $matrix);
103 | }
104 | 


--------------------------------------------------------------------------------
/src/Exception/Exception.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Exception;
13 | 
14 | /**
15 |  * Imagine-specific exception.
16 |  */
17 | interface Exception
18 | {
19 | }
20 | 


--------------------------------------------------------------------------------
/src/Exception/InvalidArgumentException.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Exception;
13 | 
14 | /**
15 |  * Imagine-specific invalid argument exception.
16 |  */
17 | class InvalidArgumentException extends \InvalidArgumentException implements Exception
18 | {
19 | }
20 | 


--------------------------------------------------------------------------------
/src/Exception/NotFoundException.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Exception;
13 | 
14 | /**
15 |  * Imagine-specific invalid not found exception.
16 |  */
17 | class NotFoundException extends InvalidArgumentException
18 | {
19 | }
20 | 


--------------------------------------------------------------------------------
/src/Exception/NotSupportedException.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Exception;
13 | 
14 | /**
15 |  * Should be used when a driver does not support an operation.
16 |  */
17 | class NotSupportedException extends RuntimeException implements Exception
18 | {
19 | }
20 | 


--------------------------------------------------------------------------------
/src/Exception/OutOfBoundsException.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Exception;
13 | 
14 | /**
15 |  * Imagine-specific out of bounds exception.
16 |  */
17 | class OutOfBoundsException extends \OutOfBoundsException implements Exception
18 | {
19 | }
20 | 


--------------------------------------------------------------------------------
/src/Exception/RuntimeException.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Exception;
13 | 
14 | /**
15 |  * Imagine-specific runtime exception.
16 |  */
17 | class RuntimeException extends \RuntimeException implements Exception
18 | {
19 | }
20 | 


--------------------------------------------------------------------------------
/src/Factory/ClassFactoryAwareInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | namespace Imagine\Factory;
 4 | 
 5 | /**
 6 |  * An interface that classes that accepts a class factory should implement.
 7 |  */
 8 | interface ClassFactoryAwareInterface
 9 | {
10 |     /**
11 |      * Set the class factory instance to be used.
12 |      *
13 |      * @param \Imagine\Factory\ClassFactoryInterface $classFactory
14 |      *
15 |      * @return $this
16 |      */
17 |     public function setClassFactory(ClassFactoryInterface $classFactory);
18 | 
19 |     /**
20 |      * Get the class factory instance to be used.
21 |      *
22 |      * @return \Imagine\Factory\ClassFactoryInterface
23 |      */
24 |     public function getClassFactory();
25 | }
26 | 


--------------------------------------------------------------------------------
/src/Factory/ClassFactoryInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | namespace Imagine\Factory;
  4 | 
  5 | use Imagine\Image\Palette\Color\ColorInterface;
  6 | 
  7 | /**
  8 |  * The interface that class factories must implement.
  9 |  */
 10 | interface ClassFactoryInterface
 11 | {
 12 |     /**
 13 |      * The handle to be used for the GD manipulation library.
 14 |      *
 15 |      * @var string
 16 |      */
 17 |     const HANDLE_GD = 'gd';
 18 | 
 19 |     /**
 20 |      * The handle to be used for the Gmagick manipulation library.
 21 |      *
 22 |      * @var string
 23 |      */
 24 |     const HANDLE_GMAGICK = 'gmagick';
 25 | 
 26 |     /**
 27 |      * The handle to be used for the Imagick manipulation library.
 28 |      *
 29 |      * @var string
 30 |      */
 31 |     const HANDLE_IMAGICK = 'imagick';
 32 | 
 33 |     /**
 34 |      * Create a new instance of a metadata reader.
 35 |      *
 36 |      * @return \Imagine\Image\Metadata\MetadataReaderInterface
 37 |      */
 38 |     public function createMetadataReader();
 39 | 
 40 |     /**
 41 |      * Create new BoxInterface instance.
 42 |      *
 43 |      * @param int $width The box width
 44 |      * @param int $height The box height
 45 |      *
 46 |      * @return \Imagine\Image\BoxInterface
 47 |      */
 48 |     public function createBox($width, $height);
 49 | 
 50 |     /**
 51 |      * Create new FontInterface instance.
 52 |      *
 53 |      * @param string $handle The handle that identifies the manipulation library (one of the HANDLE_... constants, or your own implementation).
 54 |      * @param string $file
 55 |      * @param int $size the font size in points (e.g. 10pt means 10)
 56 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 57 |      *
 58 |      * @return \Imagine\Image\FontInterface
 59 |      */
 60 |     public function createFont($handle, $file, $size, ColorInterface $color);
 61 | 
 62 |     /**
 63 |      * Create a new instance of a file loader.
 64 |      *
 65 |      * @param string|mixed $path
 66 |      *
 67 |      * @return \Imagine\File\LoaderInterface
 68 |      */
 69 |     public function createFileLoader($path);
 70 | 
 71 |     /**
 72 |      * Crate a new instance of a layers interface.
 73 |      *
 74 |      * @param string $handle The handle that identifies the manipulation library (one of the HANDLE_... constants, or your own implementation).
 75 |      * @param \Imagine\Image\ImageInterface $image
 76 |      * @param mixed|null $initialKey the key of the initially selected layer
 77 |      *
 78 |      * @return \Imagine\Image\LayersInterface
 79 |      */
 80 |     public function createLayers($handle, \Imagine\Image\ImageInterface $image, $initialKey = null);
 81 | 
 82 |     /**
 83 |      * Create a new ImageInterface instance.
 84 |      *
 85 |      * @param string $handle The handle that identifies the manipulation library (one of the HANDLE_... constants, or your own implementation).
 86 |      * @param mixed $resource
 87 |      * @param \Imagine\Image\Palette\PaletteInterface $palette
 88 |      * @param \Imagine\Image\Metadata\MetadataBag $metadata
 89 |      *
 90 |      * @return \Imagine\Image\ImageInterface
 91 |      */
 92 |     public function createImage($handle, $resource, \Imagine\Image\Palette\PaletteInterface $palette, \Imagine\Image\Metadata\MetadataBag $metadata);
 93 | 
 94 |     /**
 95 |      * Create a new DrawerInterface instance.
 96 |      *
 97 |      * @param string $handle The handle that identifies the manipulation library (one of the HANDLE_... constants, or your own implementation).
 98 |      * @param mixed $resource
 99 |      *
100 |      * @return \Imagine\Draw\DrawerInterface
101 |      */
102 |     public function createDrawer($handle, $resource);
103 | 
104 |     /**
105 |      * Create a new EffectsInterface instance.
106 |      *
107 |      * @param string $handle The handle that identifies the manipulation library (one of the HANDLE_... constants, or your own implementation).
108 |      * @param mixed $resource
109 |      *
110 |      * @return \Imagine\Effects\EffectsInterface
111 |      */
112 |     public function createEffects($handle, $resource);
113 | }
114 | 


--------------------------------------------------------------------------------
/src/File/LoaderInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * For the full copyright and license information, please view the LICENSE file that was distributed with this source code.
 7 |  */
 8 | 
 9 | namespace Imagine\File;
10 | 
11 | /**
12 |  * Interface for classes that can load local or remote files.
13 |  */
14 | interface LoaderInterface
15 | {
16 |     /**
17 |      * Is this a local file.
18 |      *
19 |      * @return bool
20 |      */
21 |     public function isLocalFile();
22 | 
23 |     /**
24 |      * Get the path of the file (local or remote).
25 |      *
26 |      * @return string
27 |      */
28 |     public function getPath();
29 | 
30 |     /**
31 |      * Is the binary content already loaded?
32 |      *
33 |      * @return bool
34 |      */
35 |     public function hasReadData();
36 | 
37 |     /**
38 |      * Get the file binary contents.
39 |      *
40 |      * @return string
41 |      */
42 |     public function getData();
43 | 
44 |     /**
45 |      * The string representation of this object must be the file path (local or remote).
46 |      *
47 |      * @return string
48 |      */
49 |     public function __toString();
50 | }
51 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/BlackWhite.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | use Imagine\Filter\FilterInterface;
16 | use Imagine\Image\ImageInterface;
17 | use Imagine\Image\Palette\Color\ColorInterface;
18 | use Imagine\Image\Palette\RGB;
19 | use Imagine\Image\Point;
20 | 
21 | /**
22 |  * This filter calculates, for each pixel of an image, whether it is ligher or darker than a threshold.
23 |  * If the pixel is lighter than the thresold it will be black, otherwise it will be light.
24 |  * The result is an image with only black and white pixels (black pixels for ligher colors, white pixels for darker colors).
25 |  */
26 | class BlackWhite extends OnPixelBased implements FilterInterface
27 | {
28 |     /**
29 |      * @var \Imagine\Filter\Advanced\Grayscale
30 |      */
31 |     protected $grayScaleFilter;
32 | 
33 |     /**
34 |      * Initialize this filter.
35 |      *
36 |      * @param int $threshold the dask/light threshold, from 0 (all black) to 255 (all white)
37 |      *
38 |      * @throws \Imagine\Exception\InvalidArgumentException
39 |      */
40 |     public function __construct($threshold)
41 |     {
42 |         if (!($threshold >= 0 && $threshold <= 255)) {
43 |             throw new InvalidArgumentException('$threshold has to be between 0 and 255');
44 |         }
45 | 
46 |         $this->grayScaleFilter = new Grayscale();
47 | 
48 |         $rgb = new RGB();
49 |         parent::__construct(
50 |             function (ImageInterface $image, Point $point) use ($threshold, $rgb) {
51 |                 $newRedValue = $image->getColorAt($point)->getValue(ColorInterface::COLOR_RED) < $threshold ? 255 : 0;
52 |                 $image->draw()->dot($point, $rgb->color(array($newRedValue, $newRedValue, $newRedValue)));
53 |             }
54 |         );
55 |     }
56 | 
57 |     /**
58 |      * {@inheritdoc}
59 |      *
60 |      * @see \Imagine\Filter\Advanced\OnPixelBased::apply()
61 |      */
62 |     public function apply(ImageInterface $image)
63 |     {
64 |         $grayScaledImage = $this->grayScaleFilter->apply($image);
65 | 
66 |         return parent::apply($grayScaledImage);
67 |     }
68 | }
69 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/Border.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Filter\Advanced;
 13 | 
 14 | use Imagine\Filter\FilterInterface;
 15 | use Imagine\Image\ImageInterface;
 16 | use Imagine\Image\Palette\Color\ColorInterface;
 17 | use Imagine\Image\Point;
 18 | 
 19 | /**
 20 |  * A border filter.
 21 |  */
 22 | class Border implements FilterInterface
 23 | {
 24 |     /**
 25 |      * @var \Imagine\Image\Palette\Color\ColorInterface
 26 |      */
 27 |     private $color;
 28 | 
 29 |     /**
 30 |      * @var int
 31 |      */
 32 |     private $width;
 33 | 
 34 |     /**
 35 |      * @var int
 36 |      */
 37 |     private $height;
 38 | 
 39 |     /**
 40 |      * Constructs Border filter with given color, width and height.
 41 |      *
 42 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 43 |      * @param int $width Width of the border on the left and right sides of the image
 44 |      * @param int $height Height of the border on the top and bottom sides of the image
 45 |      */
 46 |     public function __construct(ColorInterface $color, $width = 1, $height = 1)
 47 |     {
 48 |         $this->color = $color;
 49 |         $this->width = $width;
 50 |         $this->height = $height;
 51 |     }
 52 | 
 53 |     /**
 54 |      * {@inheritdoc}
 55 |      *
 56 |      * @see \Imagine\Filter\FilterInterface::apply()
 57 |      */
 58 |     public function apply(ImageInterface $image)
 59 |     {
 60 |         $size = $image->getSize();
 61 |         $width = $size->getWidth();
 62 |         $height = $size->getHeight();
 63 | 
 64 |         $draw = $image->draw();
 65 | 
 66 |         // Draw top and bottom lines
 67 |         $draw
 68 |             ->line(
 69 |                 new Point(0, 0),
 70 |                 new Point($width - 1, 0),
 71 |                 $this->color,
 72 |                 $this->height
 73 |             )
 74 |             ->line(
 75 |                 new Point($width - 1, $height - 1),
 76 |                 new Point(0, $height - 1),
 77 |                 $this->color,
 78 |                 $this->height
 79 |             )
 80 |         ;
 81 | 
 82 |         // Draw sides
 83 |         $draw
 84 |             ->line(
 85 |                 new Point(0, 0),
 86 |                 new Point(0, $height - 1),
 87 |                 $this->color,
 88 |                 $this->width
 89 |             )
 90 |             ->line(
 91 |                 new Point($width - 1, 0),
 92 |                 new Point($width - 1, $height - 1),
 93 |                 $this->color,
 94 |                 $this->width
 95 |             )
 96 |         ;
 97 | 
 98 |         return $image;
 99 |     }
100 | }
101 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/BorderDetection.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | use Imagine\Filter\FilterInterface;
16 | use Imagine\Utils\Matrix;
17 | 
18 | /**
19 |  * BorderDetection based on Laplace-Operator. Three different variants are offered:.
20 |  * <code><pre>
21 |  *   First          Second            Third
22 |  *  0,  1, 0       1,  1, 1,       -1,  2, -1,
23 |  *  1, -4, 1  and  1, -8, 1,  and   2, -4,  2,
24 |  *  0,  1, 0       1,  1, 1        -1,  2, -1
25 |  * </pre></code>.
26 |  *
27 |  * Consider to apply this filter on a grayscaled image.
28 |  */
29 | class BorderDetection extends Neighborhood implements FilterInterface
30 | {
31 |     /**
32 |      * First variant of the detection matrix.
33 |      *
34 |      * @var int
35 |      */
36 |     const VARIANT_ONE = 0;
37 | 
38 |     /**
39 |      * Second variant of the detection matrix.
40 |      *
41 |      * @var int
42 |      */
43 |     const VARIANT_TWO = 1;
44 | 
45 |     /**
46 |      * Third variant of the detection matrix.
47 |      *
48 |      * @var int
49 |      */
50 |     const VARIANT_THREE = 2;
51 | 
52 |     /**
53 |      * Initialize this filter.
54 |      *
55 |      * @param int $variant One of the BorderDetection::VARIANT_... constants.
56 |      *
57 |      * @throws \Imagine\Exception\InvalidArgumentException throws an InvalidArgumentException if $variant is not valid
58 |      */
59 |     public function __construct($variant = self::VARIANT_ONE)
60 |     {
61 |         $matrix = null;
62 | 
63 |         switch ($variant) {
64 |             case self::VARIANT_ONE:
65 |                 $matrix = new Matrix(3, 3, array(
66 |                     0,  1, 0,
67 |                     1, -4, 1,
68 |                     0,  1, 0,
69 |                 ));
70 |                 break;
71 |             case self::VARIANT_TWO:
72 |                 $matrix = new Matrix(3, 3, array(
73 |                     1,  1, 1,
74 |                     1, -8, 1,
75 |                     1,  1, 1,
76 |                 ));
77 |                 break;
78 |             case self::VARIANT_THREE:
79 |                 $matrix = new Matrix(3, 3, array(
80 |                     -1,  2, -1,
81 |                     2, -4,  2,
82 |                     -1,  2, -1,
83 |                 ));
84 |                 break;
85 |             default:
86 |                 throw new InvalidArgumentException('Unknown variant ' . $variant);
87 |         }
88 | 
89 |         parent::__construct($matrix);
90 |     }
91 | }
92 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/Canvas.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\BoxInterface;
16 | use Imagine\Image\ImageInterface;
17 | use Imagine\Image\ImagineInterface;
18 | use Imagine\Image\Palette\Color\ColorInterface;
19 | use Imagine\Image\Point;
20 | use Imagine\Image\PointInterface;
21 | 
22 | /**
23 |  * A canvas filter.
24 |  */
25 | class Canvas implements FilterInterface
26 | {
27 |     /**
28 |      * @var \Imagine\Image\BoxInterface
29 |      */
30 |     private $size;
31 | 
32 |     /**
33 |      * @var \Imagine\Image\PointInterface
34 |      */
35 |     private $placement;
36 | 
37 |     /**
38 |      * @var \Imagine\Image\Palette\Color\ColorInterface
39 |      */
40 |     private $background;
41 | 
42 |     /**
43 |      * @var \Imagine\Image\ImagineInterface
44 |      */
45 |     private $imagine;
46 | 
47 |     /**
48 |      * Constructs Canvas filter with given width and height and the placement of the current image inside the new canvas.
49 |      *
50 |      * @param \Imagine\Image\ImagineInterface $imagine
51 |      * @param \Imagine\Image\BoxInterface $size
52 |      * @param \Imagine\Image\PointInterface $placement
53 |      * @param \Imagine\Image\Palette\Color\ColorInterface $background
54 |      */
55 |     public function __construct(ImagineInterface $imagine, BoxInterface $size, ?PointInterface $placement = null, ?ColorInterface $background = null)
56 |     {
57 |         $this->imagine = $imagine;
58 |         $this->size = $size;
59 |         $this->placement = $placement ?: new Point(0, 0);
60 |         $this->background = $background;
61 |     }
62 | 
63 |     /**
64 |      * {@inheritdoc}
65 |      *
66 |      * @see \Imagine\Filter\FilterInterface::apply()
67 |      */
68 |     public function apply(ImageInterface $image)
69 |     {
70 |         $canvas = $this->imagine->create($this->size, $this->background);
71 |         $canvas->paste($image, $this->placement);
72 | 
73 |         return $canvas;
74 |     }
75 | }
76 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/Grayscale.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | use Imagine\Image\Point;
17 | 
18 | /**
19 |  * The Grayscale filter calculates the gray-value based on RGB.
20 |  */
21 | class Grayscale extends OnPixelBased implements FilterInterface
22 | {
23 |     public function __construct()
24 |     {
25 |         parent::__construct(function (ImageInterface $image, Point $point) {
26 |             $color = $image->getColorAt($point);
27 |             $image->draw()->dot($point, $color->grayscale());
28 |         });
29 |     }
30 | }
31 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/Negation.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * This filter negates every color of every pixel of an image.
19 |  */
20 | class Negation implements FilterInterface
21 | {
22 |     /**
23 |      * {@inheritdoc}
24 |      *
25 |      * @see \Imagine\Filter\FilterInterface::apply()
26 |      */
27 |     public function apply(ImageInterface $image)
28 |     {
29 |         $image->effects()->negative();
30 | 
31 |         return $image;
32 |     }
33 | }
34 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/Neighborhood.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Filter\Advanced;
 13 | 
 14 | use Imagine\Filter\FilterInterface;
 15 | use Imagine\Image\ImageInterface;
 16 | use Imagine\Image\Point;
 17 | use Imagine\Utils\Matrix;
 18 | 
 19 | /**
 20 |  * The Neighborhood filter takes a matrix and calculates the color current pixel based on its neighborhood.
 21 |  *
 22 |  * @example
 23 |  * <code><pre>
 24 |  *           a, b, c
 25 |  * Matrix =  d, e, f
 26 |  *           g, h, i
 27 |  * </pre></code>
 28 |  *
 29 |  * and color{i, j} the color of the pixel at position (i, j). It calculates the color of pixel (x, y) like that:
 30 |  *
 31 |  * <code><pre>
 32 |  * color (x, y) =   a * color(x - 1, y - 1) + b * color(x, y - 1) + c * color(x + 1, y - 1)
 33 |  *                + d * color(x - 1, y)     + e * color(x, y)     + f * color(x + 1, y)
 34 |  *                + g * color(x - 1, y + 1) + h * color(x, y + 1) + i * color(x + 1, y + 1)
 35 |  * </pre></code>
 36 |  */
 37 | class Neighborhood implements FilterInterface
 38 | {
 39 |     /**
 40 |      * @var \Imagine\Utils\Matrix
 41 |      */
 42 |     protected $matrix;
 43 | 
 44 |     /**
 45 |      * Initialize the instance.
 46 |      *
 47 |      * @param \Imagine\Utils\Matrix $matrix
 48 |      */
 49 |     public function __construct(Matrix $matrix)
 50 |     {
 51 |         $this->matrix = $matrix;
 52 |     }
 53 | 
 54 |     /**
 55 |      * {@inheritdoc}
 56 |      *
 57 |      * @see \Imagine\Filter\FilterInterface::apply()
 58 |      */
 59 |     public function apply(ImageInterface $image)
 60 |     {
 61 |         // We reduce the usage of methods on the image to dramatically increase the performance of this algorithm.
 62 |         // Really... We need that performance...
 63 |         // Therefore we first build a matrix, that holds the colors of the image.
 64 |         $width = $image->getSize()->getWidth();
 65 |         $height = $image->getSize()->getHeight();
 66 |         $byteData = new Matrix($width, $height);
 67 | 
 68 |         for ($y = 0; $y < $height; $y++) {
 69 |             for ($x = 0; $x < $width; $x++) {
 70 |                 $byteData->setElementAt($x, $y, $image->getColorAt(new Point($x, $y)));
 71 |             }
 72 |         }
 73 | 
 74 |         $dWidth = (int) (($this->matrix->getWidth() - 1) / 2);
 75 |         $dHeight = (int) (($this->matrix->getHeight() - 1) / 2);
 76 | 
 77 |         // foreach point, which has a big enough neighborhood
 78 |         for ($y = $dHeight; $y < $height - $dHeight; $y++) {
 79 |             for ($x = $dWidth; $x < $width - $dWidth; $x++) {
 80 |                 $currentColor = array_fill(0, count($image->palette()->pixelDefinition()), 0);
 81 | 
 82 |                 // calculate the new color based on the neighborhood
 83 |                 for ($boxY = $y - $dHeight, $matrixY = 0; $boxY <= $y + $dHeight; $boxY++, $matrixY++) {
 84 |                     for ($boxX = $x - $dWidth, $matrixX = 0; $boxX <= $x + $dWidth; $boxX++, $matrixX++) {
 85 |                         foreach ($image->palette()->pixelDefinition() as $index => $stream) {
 86 |                             $currentColor[$index] +=
 87 |                                 $byteData->getElementAt($boxX, $boxY)->getValue($stream) *
 88 |                                 $this->matrix->getElementAt($matrixX, $matrixY)
 89 |                             ;
 90 |                         }
 91 |                     }
 92 |                 }
 93 | 
 94 |                 $image->draw()->dot(new Point($x, $y), $image->palette()->color($currentColor));
 95 |             }
 96 |         }
 97 | 
 98 |         return $image;
 99 |     }
100 | }
101 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/OnPixelBased.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | use Imagine\Filter\FilterInterface;
16 | use Imagine\Image\ImageInterface;
17 | use Imagine\Image\Point;
18 | 
19 | /**
20 |  * The OnPixelBased takes a callable, and for each pixel, this callable is called with the
21 |  * image (\Imagine\Image\ImageInterface) and the current point (\Imagine\Image\Point).
22 |  */
23 | class OnPixelBased implements FilterInterface
24 | {
25 |     /**
26 |      * @var callable
27 |      */
28 |     protected $callback;
29 | 
30 |     /**
31 |      * Initialize the instance.
32 |      *
33 |      * @param callable $callback
34 |      *
35 |      * @throws \Imagine\Exception\InvalidArgumentException
36 |      */
37 |     public function __construct($callback)
38 |     {
39 |         if (!is_callable($callback)) {
40 |             throw new InvalidArgumentException('$callback has to be callable');
41 |         }
42 | 
43 |         $this->callback = $callback;
44 |     }
45 | 
46 |     /**
47 |      * {@inheritdoc}
48 |      *
49 |      * @see \Imagine\Filter\FilterInterface::apply()
50 |      */
51 |     public function apply(ImageInterface $image)
52 |     {
53 |         $size = $image->getSize();
54 |         $w = $size->getWidth();
55 |         $h = $size->getHeight();
56 |         for ($y = 0; $y < $h; $y++) {
57 |             for ($x = 0; $x < $w; $x++) {
58 |                 call_user_func($this->callback, $image, new Point($x, $y));
59 |             }
60 |         }
61 | 
62 |         return $image;
63 |     }
64 | }
65 | 


--------------------------------------------------------------------------------
/src/Filter/Advanced/RelativeResize.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Advanced;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | use Imagine\Filter\FilterInterface;
16 | use Imagine\Image\ImageInterface;
17 | 
18 | /**
19 |  * The RelativeResize filter allows images to be resized relative to their existing dimensions.
20 |  */
21 | class RelativeResize implements FilterInterface
22 | {
23 |     /**
24 |      * @var string
25 |      */
26 |     private $method;
27 | 
28 |     /**
29 |      * @var mixed
30 |      */
31 |     private $parameter;
32 | 
33 |     /**
34 |      * Constructs a RelativeResize filter with the given method and argument.
35 |      *
36 |      * @param string $method BoxInterface method
37 |      * @param mixed $parameter Parameter for BoxInterface method
38 |      */
39 |     public function __construct($method, $parameter)
40 |     {
41 |         if (!in_array($method, array('heighten', 'increase', 'scale', 'widen'))) {
42 |             throw new InvalidArgumentException(sprintf('Unsupported method: ', $method));
43 |         }
44 | 
45 |         $this->method = $method;
46 |         $this->parameter = $parameter;
47 |     }
48 | 
49 |     /**
50 |      * {@inheritdoc}
51 |      *
52 |      * @see \Imagine\Filter\FilterInterface::apply()
53 |      */
54 |     public function apply(ImageInterface $image)
55 |     {
56 |         return $image->resize(call_user_func(array($image->getSize(), $this->method), $this->parameter));
57 |     }
58 | }
59 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/ApplyMask.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * An apply mask filter.
19 |  */
20 | class ApplyMask implements FilterInterface
21 | {
22 |     /**
23 |      * @var \Imagine\Image\ImageInterface
24 |      */
25 |     private $mask;
26 | 
27 |     /**
28 |      * Initialize the instance.
29 |      *
30 |      * @param \Imagine\Image\ImageInterface $mask
31 |      */
32 |     public function __construct(ImageInterface $mask)
33 |     {
34 |         $this->mask = $mask;
35 |     }
36 | 
37 |     /**
38 |      * {@inheritdoc}
39 |      *
40 |      * @see \Imagine\Filter\FilterInterface::apply()
41 |      */
42 |     public function apply(ImageInterface $image)
43 |     {
44 |         return $image->applyMask($this->mask);
45 |     }
46 | }
47 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Autorotate.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Filter\Basic;
 13 | 
 14 | use Imagine\Filter\FilterInterface;
 15 | use Imagine\Image\ImageInterface;
 16 | use Imagine\Image\Palette\Color\ColorInterface;
 17 | 
 18 | /**
 19 |  * Rotates an image automatically based on exif information.
 20 |  *
 21 |  * Your attention please: This filter requires the use of the
 22 |  * ExifMetadataReader to work.
 23 |  *
 24 |  * @see https://imagine.readthedocs.org/en/latest/usage/metadata.html
 25 |  */
 26 | class Autorotate implements FilterInterface
 27 | {
 28 |     /**
 29 |      * Image transformation: flip vertically.
 30 |      *
 31 |      * @var string
 32 |      */
 33 |     const FLIP_VERTICALLY = 'V';
 34 | 
 35 |     /**
 36 |      * Image transformation: flip horizontally.
 37 |      *
 38 |      * @var string
 39 |      */
 40 |     const FLIP_HORIZONTALLY = 'H';
 41 | 
 42 |     /**
 43 |      * @var string|array|\Imagine\Image\Palette\Color\ColorInterface
 44 |      */
 45 |     private $color;
 46 | 
 47 |     /**
 48 |      * @param string|array|\Imagine\Image\Palette\Color\ColorInterface $color A color
 49 |      */
 50 |     public function __construct($color = '000000')
 51 |     {
 52 |         $this->color = $color;
 53 |     }
 54 | 
 55 |     /**
 56 |      * {@inheritdoc}
 57 |      *
 58 |      * @see \Imagine\Filter\FilterInterface::apply()
 59 |      */
 60 |     public function apply(ImageInterface $image)
 61 |     {
 62 |         foreach ($this->getTransformations($image) as $transformation) {
 63 |             if ($transformation === self::FLIP_HORIZONTALLY) {
 64 |                 $image->flipHorizontally();
 65 |             } elseif ($transformation === self::FLIP_VERTICALLY) {
 66 |                 $image->flipVertically();
 67 |             } elseif (is_int($transformation)) {
 68 |                 $image->rotate($transformation, $this->getColor($image));
 69 |             }
 70 |         }
 71 | 
 72 |         return $image;
 73 |     }
 74 | 
 75 |     /**
 76 |      * Get the transformations.
 77 |      *
 78 |      * @param \Imagine\Image\ImageInterface $image
 79 |      *
 80 |      * @return array an array containing Autorotate::FLIP_VERTICALLY, Autorotate::FLIP_HORIZONTALLY, rotation degrees
 81 |      */
 82 |     public function getTransformations(ImageInterface $image)
 83 |     {
 84 |         $transformations = array();
 85 |         $metadata = $image->metadata();
 86 |         switch (isset($metadata['ifd0.Orientation']) ? $metadata['ifd0.Orientation'] : null) {
 87 |             case 1: // top-left
 88 |                 break;
 89 |             case 2: // top-right
 90 |                 $transformations[] = self::FLIP_HORIZONTALLY;
 91 |                 break;
 92 |             case 3: // bottom-right
 93 |                 $transformations[] = 180;
 94 |                 break;
 95 |             case 4: // bottom-left
 96 |                 $transformations[] = self::FLIP_HORIZONTALLY;
 97 |                 $transformations[] = 180;
 98 |                 break;
 99 |             case 5: // left-top
100 |                 $transformations[] = self::FLIP_HORIZONTALLY;
101 |                 $transformations[] = -90;
102 |                 break;
103 |             case 6: // right-top
104 |                 $transformations[] = 90;
105 |                 break;
106 |             case 7: // right-bottom
107 |                 $transformations[] = self::FLIP_HORIZONTALLY;
108 |                 $transformations[] = 90;
109 |                 break;
110 |             case 8: // left-bottom
111 |                 $transformations[] = -90;
112 |                 break;
113 |             default: // Invalid orientation
114 |                 break;
115 |         }
116 | 
117 |         return $transformations;
118 |     }
119 | 
120 |     /**
121 |      * @param \Imagine\Image\ImageInterface $image
122 |      *
123 |      * @return \Imagine\Image\Palette\Color\ColorInterface
124 |      */
125 |     private function getColor(ImageInterface $image)
126 |     {
127 |         if ($this->color instanceof ColorInterface) {
128 |             return $this->color;
129 |         }
130 | 
131 |         return $image->palette()->color($this->color);
132 |     }
133 | }
134 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Copy.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * A copy filter.
19 |  */
20 | class Copy implements FilterInterface
21 | {
22 |     /**
23 |      * {@inheritdoc}
24 |      *
25 |      * @see \Imagine\Filter\FilterInterface::apply()
26 |      */
27 |     public function apply(ImageInterface $image)
28 |     {
29 |         return $image->copy();
30 |     }
31 | }
32 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Crop.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\BoxInterface;
16 | use Imagine\Image\ImageInterface;
17 | use Imagine\Image\PointInterface;
18 | 
19 | /**
20 |  * A crop filter.
21 |  */
22 | class Crop implements FilterInterface
23 | {
24 |     /**
25 |      * @var \Imagine\Image\PointInterface
26 |      */
27 |     private $start;
28 | 
29 |     /**
30 |      * @var \Imagine\Image\BoxInterface
31 |      */
32 |     private $size;
33 | 
34 |     /**
35 |      * Constructs a Crop filter with given x, y, coordinates and crop width and height values.
36 |      *
37 |      * @param \Imagine\Image\PointInterface $start
38 |      * @param \Imagine\Image\BoxInterface $size
39 |      */
40 |     public function __construct(PointInterface $start, BoxInterface $size)
41 |     {
42 |         $this->start = $start;
43 |         $this->size = $size;
44 |     }
45 | 
46 |     /**
47 |      * {@inheritdoc}
48 |      *
49 |      * @see \Imagine\Filter\FilterInterface::apply()
50 |      */
51 |     public function apply(ImageInterface $image)
52 |     {
53 |         return $image->crop($this->start, $this->size);
54 |     }
55 | }
56 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Fill.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\Fill\FillInterface;
16 | use Imagine\Image\ImageInterface;
17 | 
18 | /**
19 |  * A fill filter.
20 |  */
21 | class Fill implements FilterInterface
22 | {
23 |     /**
24 |      * @var \Imagine\Image\Fill\FillInterface
25 |      */
26 |     private $fill;
27 | 
28 |     /**
29 |      * @param \Imagine\Image\Fill\FillInterface $fill
30 |      */
31 |     public function __construct(FillInterface $fill)
32 |     {
33 |         $this->fill = $fill;
34 |     }
35 | 
36 |     /**
37 |      * {@inheritdoc}
38 |      *
39 |      * @see \Imagine\Filter\FilterInterface::apply()
40 |      */
41 |     public function apply(ImageInterface $image)
42 |     {
43 |         return $image->fill($this->fill);
44 |     }
45 | }
46 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/FlipHorizontally.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * A "flip horizontally" filter.
19 |  */
20 | class FlipHorizontally implements FilterInterface
21 | {
22 |     /**
23 |      * {@inheritdoc}
24 |      *
25 |      * @see \Imagine\Filter\FilterInterface::apply()
26 |      */
27 |     public function apply(ImageInterface $image)
28 |     {
29 |         return $image->flipHorizontally();
30 |     }
31 | }
32 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/FlipVertically.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * A "flip vertically" filter.
19 |  */
20 | class FlipVertically implements FilterInterface
21 | {
22 |     /**
23 |      * {@inheritdoc}
24 |      *
25 |      * @see \Imagine\Filter\FilterInterface::apply()
26 |      */
27 |     public function apply(ImageInterface $image)
28 |     {
29 |         return $image->flipVertically();
30 |     }
31 | }
32 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Paste.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | use Imagine\Filter\FilterInterface;
16 | use Imagine\Image\ImageInterface;
17 | use Imagine\Image\PointInterface;
18 | 
19 | /**
20 |  * A paste filter.
21 |  */
22 | class Paste implements FilterInterface
23 | {
24 |     /**
25 |      * @var \Imagine\Image\ImageInterface
26 |      */
27 |     private $image;
28 | 
29 |     /**
30 |      * @var \Imagine\Image\PointInterface
31 |      */
32 |     private $start;
33 | 
34 |     /**
35 |      * How to paste the image, from 0 (fully transparent) to 100 (fully opaque).
36 |      *
37 |      * @var int
38 |      */
39 |     private $alpha;
40 | 
41 |     /**
42 |      * Constructs a Paste filter with given ImageInterface to paste and x, y
43 |      * coordinates of target position.
44 |      *
45 |      * @param \Imagine\Image\ImageInterface $image
46 |      * @param \Imagine\Image\PointInterface $start
47 |      * @param int $alpha how to paste the image, from 0 (fully transparent) to 100 (fully opaque)
48 |      */
49 |     public function __construct(ImageInterface $image, PointInterface $start, $alpha = 100)
50 |     {
51 |         $this->image = $image;
52 |         $this->start = $start;
53 |         $alpha = (int) round($alpha);
54 |         if ($alpha < 0 || $alpha > 100) {
55 |             throw new InvalidArgumentException(sprintf('The %1$s argument can range from %2$d to %3$d, but you specified %4$d.', '$alpha', 0, 100, $alpha));
56 |         }
57 |         $this->alpha = $alpha;
58 |     }
59 | 
60 |     /**
61 |      * {@inheritdoc}
62 |      *
63 |      * @see \Imagine\Filter\FilterInterface::apply()
64 |      */
65 |     public function apply(ImageInterface $image)
66 |     {
67 |         return $image->paste($this->image, $this->start, $this->alpha);
68 |     }
69 | }
70 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Resize.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\BoxInterface;
16 | use Imagine\Image\ImageInterface;
17 | 
18 | /**
19 |  * A resize filter.
20 |  */
21 | class Resize implements FilterInterface
22 | {
23 |     /**
24 |      * @var \Imagine\Image\BoxInterface
25 |      */
26 |     private $size;
27 | 
28 |     /**
29 |      * @var string
30 |      */
31 |     private $filter;
32 | 
33 |     /**
34 |      * Constructs Resize filter with given width and height.
35 |      *
36 |      * @param \Imagine\Image\BoxInterface $size
37 |      * @param string $filter
38 |      */
39 |     public function __construct(BoxInterface $size, $filter = ImageInterface::FILTER_UNDEFINED)
40 |     {
41 |         $this->size = $size;
42 |         $this->filter = $filter;
43 |     }
44 | 
45 |     /**
46 |      * {@inheritdoc}
47 |      *
48 |      * @see \Imagine\Filter\FilterInterface::apply()
49 |      */
50 |     public function apply(ImageInterface $image)
51 |     {
52 |         return $image->resize($this->size, $this->filter);
53 |     }
54 | }
55 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Rotate.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | use Imagine\Image\Palette\Color\ColorInterface;
17 | 
18 | /**
19 |  * A rotate filter.
20 |  */
21 | class Rotate implements FilterInterface
22 | {
23 |     /**
24 |      * @var int
25 |      */
26 |     private $angle;
27 | 
28 |     /**
29 |      * @var \Imagine\Image\Palette\Color\ColorInterface
30 |      */
31 |     private $background;
32 | 
33 |     /**
34 |      * Constructs Rotate filter with given angle and background color.
35 |      *
36 |      * @param int $angle
37 |      * @param \Imagine\Image\Palette\Color\ColorInterface $background
38 |      */
39 |     public function __construct($angle, ?ColorInterface $background = null)
40 |     {
41 |         $this->angle = $angle;
42 |         $this->background = $background;
43 |     }
44 | 
45 |     /**
46 |      * {@inheritdoc}
47 |      *
48 |      * @see \Imagine\Filter\FilterInterface::apply()
49 |      */
50 |     public function apply(ImageInterface $image)
51 |     {
52 |         return $image->rotate($this->angle, $this->background);
53 |     }
54 | }
55 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Save.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * A save filter.
19 |  */
20 | class Save implements FilterInterface
21 | {
22 |     /**
23 |      * @var string
24 |      */
25 |     private $path;
26 | 
27 |     /**
28 |      * @var array
29 |      */
30 |     private $options;
31 | 
32 |     /**
33 |      * Constructs Save filter with given path and options.
34 |      *
35 |      * @param string $path
36 |      * @param array $options
37 |      */
38 |     public function __construct($path = null, array $options = array())
39 |     {
40 |         $this->path = $path;
41 |         $this->options = $options;
42 |     }
43 | 
44 |     /**
45 |      * {@inheritdoc}
46 |      *
47 |      * @see \Imagine\Filter\FilterInterface::apply()
48 |      */
49 |     public function apply(ImageInterface $image)
50 |     {
51 |         return $image->save($this->path, $this->options);
52 |     }
53 | }
54 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Show.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * A show filter.
19 |  */
20 | class Show implements FilterInterface
21 | {
22 |     /**
23 |      * @var string
24 |      */
25 |     private $format;
26 | 
27 |     /**
28 |      * @var array
29 |      */
30 |     private $options;
31 | 
32 |     /**
33 |      * Constructs the Show filter with given format and options.
34 |      *
35 |      * @param string $format
36 |      * @param array $options
37 |      */
38 |     public function __construct($format, array $options = array())
39 |     {
40 |         $this->format = $format;
41 |         $this->options = $options;
42 |     }
43 | 
44 |     /**
45 |      * {@inheritdoc}
46 |      *
47 |      * @see \Imagine\Filter\FilterInterface::apply()
48 |      */
49 |     public function apply(ImageInterface $image)
50 |     {
51 |         return $image->show($this->format, $this->options);
52 |     }
53 | }
54 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Strip.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | 
17 | /**
18 |  * A strip filter.
19 |  */
20 | class Strip implements FilterInterface
21 | {
22 |     /**
23 |      * {@inheritdoc}
24 |      *
25 |      * @see \Imagine\Filter\FilterInterface::apply()
26 |      */
27 |     public function apply(ImageInterface $image)
28 |     {
29 |         return $image->strip();
30 |     }
31 | }
32 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/Thumbnail.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\BoxInterface;
16 | use Imagine\Image\ImageInterface;
17 | 
18 | /**
19 |  * A thumbnail filter.
20 |  */
21 | class Thumbnail implements FilterInterface
22 | {
23 |     /**
24 |      * @var \Imagine\Image\BoxInterface
25 |      */
26 |     private $size;
27 | 
28 |     /**
29 |      * @var int|string
30 |      */
31 |     private $settings;
32 | 
33 |     /**
34 |      * @var string
35 |      */
36 |     private $filter;
37 | 
38 |     /**
39 |      * Constructs the Thumbnail filter.
40 |      *
41 |      * @param \Imagine\Image\BoxInterface $size
42 |      * @param int|string $settings One or more of the ManipulatorInterface::THUMBNAIL_ flags (joined with |). It may be a string for backward compatibility with old constant values that were strings.
43 |      * @param string $filter See ImageInterface::FILTER_... constants
44 |      */
45 |     public function __construct(BoxInterface $size, $settings = ImageInterface::THUMBNAIL_INSET, $filter = ImageInterface::FILTER_UNDEFINED)
46 |     {
47 |         $this->size = $size;
48 |         $this->settings = $settings;
49 |         $this->filter = $filter;
50 |     }
51 | 
52 |     /**
53 |      * {@inheritdoc}
54 |      *
55 |      * @see \Imagine\Filter\FilterInterface::apply()
56 |      */
57 |     public function apply(ImageInterface $image)
58 |     {
59 |         return $image->thumbnail($this->size, $this->settings, $this->filter);
60 |     }
61 | }
62 | 


--------------------------------------------------------------------------------
/src/Filter/Basic/WebOptimization.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter\Basic;
13 | 
14 | use Imagine\Filter\FilterInterface;
15 | use Imagine\Image\ImageInterface;
16 | use Imagine\Image\Palette\RGB;
17 | 
18 | /**
19 |  * A filter to render web-optimized images.
20 |  */
21 | class WebOptimization implements FilterInterface
22 | {
23 |     /**
24 |      * @var \Imagine\Image\Palette\RGB
25 |      */
26 |     private $palette;
27 | 
28 |     /**
29 |      * @var string|callable|null
30 |      */
31 |     private $path;
32 | 
33 |     /**
34 |      * @var array
35 |      */
36 |     private $options;
37 | 
38 |     /**
39 |      * @param string|callable|null $path
40 |      * @param array $options
41 |      */
42 |     public function __construct($path = null, array $options = array())
43 |     {
44 |         $this->path = $path;
45 |         $this->options = array_replace(array(
46 |             'resolution-units' => ImageInterface::RESOLUTION_PIXELSPERINCH,
47 |             'resolution-y' => 72,
48 |             'resolution-x' => 72,
49 |         ), $options);
50 |         $this->palette = new RGB();
51 |     }
52 | 
53 |     /**
54 |      * {@inheritdoc}
55 |      *
56 |      * @see \Imagine\Filter\FilterInterface::apply()
57 |      */
58 |     public function apply(ImageInterface $image)
59 |     {
60 |         $image
61 |             ->usePalette($this->palette)
62 |             ->strip();
63 | 
64 |         if (is_callable($this->path)) {
65 |             $path = call_user_func($this->path, $image);
66 |         } elseif ($this->path !== null) {
67 |             $path = $this->path;
68 |         } else {
69 |             return $image;
70 |         }
71 | 
72 |         return $image->save($path, $this->options);
73 |     }
74 | }
75 | 


--------------------------------------------------------------------------------
/src/Filter/FilterInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter;
13 | 
14 | use Imagine\Image\ImageInterface;
15 | 
16 | /**
17 |  * Interface for imagine filters.
18 |  */
19 | interface FilterInterface
20 | {
21 |     /**
22 |      * Applies scheduled transformation to an ImageInterface instance.
23 |      *
24 |      * @param \Imagine\Image\ImageInterface $image
25 |      *
26 |      * @return \Imagine\Image\ImageInterface returns the processed ImageInterface instance
27 |      */
28 |     public function apply(ImageInterface $image);
29 | }
30 | 


--------------------------------------------------------------------------------
/src/Filter/ImagineAware.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Filter;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | use Imagine\Image\ImagineInterface;
16 | 
17 | /**
18 |  * ImagineAware base class.
19 |  */
20 | abstract class ImagineAware implements FilterInterface
21 | {
22 |     /**
23 |      * An ImagineInterface instance.
24 |      *
25 |      * @var \Imagine\Image\ImagineInterface
26 |      */
27 |     private $imagine;
28 | 
29 |     /**
30 |      * Set ImagineInterface instance.
31 |      *
32 |      * @param \Imagine\Image\ImagineInterface $imagine An ImagineInterface instance
33 |      */
34 |     public function setImagine(ImagineInterface $imagine)
35 |     {
36 |         $this->imagine = $imagine;
37 |     }
38 | 
39 |     /**
40 |      * Get ImagineInterface instance.
41 |      *
42 |      * @throws \Imagine\Exception\InvalidArgumentException
43 |      *
44 |      * @return \Imagine\Image\ImagineInterface
45 |      */
46 |     public function getImagine()
47 |     {
48 |         if (!$this->imagine instanceof ImagineInterface) {
49 |             throw new InvalidArgumentException(sprintf('In order to use %s pass an Imagine\Image\ImagineInterface instance to filter constructor', get_class($this)));
50 |         }
51 | 
52 |         return $this->imagine;
53 |     }
54 | }
55 | 


--------------------------------------------------------------------------------
/src/Gd/Effects.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Gd;
 13 | 
 14 | use Imagine\Driver\InfoProvider;
 15 | use Imagine\Effects\EffectsInterface;
 16 | use Imagine\Exception\InvalidArgumentException;
 17 | use Imagine\Exception\RuntimeException;
 18 | use Imagine\Image\Palette\Color\ColorInterface;
 19 | use Imagine\Image\Palette\Color\RGB as RGBColor;
 20 | use Imagine\Utils\Matrix;
 21 | 
 22 | /**
 23 |  * Effects implementation using the GD PHP extension.
 24 |  */
 25 | class Effects implements EffectsInterface, InfoProvider
 26 | {
 27 |     /**
 28 |      * @var resource|\GdImage
 29 |      */
 30 |     private $resource;
 31 | 
 32 |     /**
 33 |      * Initialize the instance.
 34 |      *
 35 |      * @param resource|\GdImage $resource
 36 |      */
 37 |     public function __construct($resource)
 38 |     {
 39 |         $this->resource = $resource;
 40 |     }
 41 | 
 42 |     /**
 43 |      * {@inheritdoc}
 44 |      *
 45 |      * @see \Imagine\Driver\InfoProvider::getDriverInfo()
 46 |      * @since 1.3.0
 47 |      */
 48 |     public static function getDriverInfo($required = true)
 49 |     {
 50 |         return DriverInfo::get($required);
 51 |     }
 52 | 
 53 |     /**
 54 |      * {@inheritdoc}
 55 |      *
 56 |      * @see \Imagine\Effects\EffectsInterface::gamma()
 57 |      */
 58 |     public function gamma($correction)
 59 |     {
 60 |         if (imagegammacorrect($this->resource, 1.0, $correction) === false) {
 61 |             throw new RuntimeException('Failed to apply gamma correction to the image');
 62 |         }
 63 | 
 64 |         return $this;
 65 |     }
 66 | 
 67 |     /**
 68 |      * {@inheritdoc}
 69 |      *
 70 |      * @see \Imagine\Effects\EffectsInterface::negative()
 71 |      */
 72 |     public function negative()
 73 |     {
 74 |         if (imagefilter($this->resource, IMG_FILTER_NEGATE) === false) {
 75 |             throw new RuntimeException('Failed to negate the image');
 76 |         }
 77 | 
 78 |         return $this;
 79 |     }
 80 | 
 81 |     /**
 82 |      * {@inheritdoc}
 83 |      *
 84 |      * @see \Imagine\Effects\EffectsInterface::grayscale()
 85 |      */
 86 |     public function grayscale()
 87 |     {
 88 |         if (imagefilter($this->resource, IMG_FILTER_GRAYSCALE) === false) {
 89 |             throw new RuntimeException('Failed to grayscale the image');
 90 |         }
 91 | 
 92 |         return $this;
 93 |     }
 94 | 
 95 |     /**
 96 |      * {@inheritdoc}
 97 |      *
 98 |      * @see \Imagine\Effects\EffectsInterface::colorize()
 99 |      */
100 |     public function colorize(ColorInterface $color)
101 |     {
102 |         if (!$color instanceof RGBColor) {
103 |             throw new RuntimeException('Colorize effects only accepts RGB color in GD context');
104 |         }
105 | 
106 |         if (imagefilter($this->resource, IMG_FILTER_COLORIZE, $color->getRed(), $color->getGreen(), $color->getBlue()) === false) {
107 |             throw new RuntimeException('Failed to colorize the image');
108 |         }
109 | 
110 |         return $this;
111 |     }
112 | 
113 |     /**
114 |      * {@inheritdoc}
115 |      *
116 |      * @see \Imagine\Effects\EffectsInterface::sharpen()
117 |      */
118 |     public function sharpen()
119 |     {
120 |         $sharpenMatrix = array(array(-1, -1, -1), array(-1, 16, -1), array(-1, -1, -1));
121 |         $divisor = array_sum(array_map('array_sum', $sharpenMatrix));
122 | 
123 |         if (imageconvolution($this->resource, $sharpenMatrix, $divisor, 0) === false) {
124 |             throw new RuntimeException('Failed to sharpen the image');
125 |         }
126 | 
127 |         return $this;
128 |     }
129 | 
130 |     /**
131 |      * {@inheritdoc}
132 |      *
133 |      * @see \Imagine\Effects\EffectsInterface::blur()
134 |      */
135 |     public function blur($sigma = 1)
136 |     {
137 |         if (imagefilter($this->resource, IMG_FILTER_GAUSSIAN_BLUR) === false) {
138 |             throw new RuntimeException('Failed to blur the image');
139 |         }
140 | 
141 |         return $this;
142 |     }
143 | 
144 |     /**
145 |      * {@inheritdoc}
146 |      *
147 |      * @see \Imagine\Effects\EffectsInterface::brightness()
148 |      */
149 |     public function brightness($brightness)
150 |     {
151 |         $gdBrightness = (int) round($brightness / 100 * 255);
152 |         if ($gdBrightness < -255 || $gdBrightness > 255) {
153 |             throw new InvalidArgumentException(sprintf('The %1$s argument can range from %2$d to %3$d, but you specified %4$d.', '$brightness', -100, 100, $brightness));
154 |         }
155 |         if (imagefilter($this->resource, IMG_FILTER_BRIGHTNESS, $gdBrightness) === false) {
156 |             throw new RuntimeException('Failed to brightness the image');
157 |         }
158 | 
159 |         return $this;
160 |     }
161 | 
162 |     /**
163 |      * {@inheritdoc}
164 |      *
165 |      * @see \Imagine\Effects\EffectsInterface::convolve()
166 |      */
167 |     public function convolve(Matrix $matrix)
168 |     {
169 |         if ($matrix->getWidth() !== 3 || $matrix->getHeight() !== 3) {
170 |             throw new InvalidArgumentException(sprintf('A convolution matrix must be 3x3 (%dx%d provided).', $matrix->getWidth(), $matrix->getHeight()));
171 |         }
172 |         if (imageconvolution($this->resource, $matrix->getMatrix(), 1, 0) === false) {
173 |             throw new RuntimeException('Failed to convolve the image');
174 |         }
175 | 
176 |         return $this;
177 |     }
178 | }
179 | 


--------------------------------------------------------------------------------
/src/Gd/Font.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Gd;
13 | 
14 | use Imagine\Driver\InfoProvider;
15 | use Imagine\Image\AbstractFont;
16 | 
17 | /**
18 |  * Font implementation using the GD library.
19 |  */
20 | final class Font extends AbstractFont implements InfoProvider
21 | {
22 |     /**
23 |      * {@inheritdoc}
24 |      *
25 |      * @see \Imagine\Driver\InfoProvider::getDriverInfo()
26 |      * @since 1.3.0
27 |      */
28 |     public static function getDriverInfo($required = true)
29 |     {
30 |         return DriverInfo::get($required);
31 |     }
32 | 
33 |     /**
34 |      * {@inheritdoc}
35 |      *
36 |      * @see \Imagine\Image\FontInterface::box()
37 |      */
38 |     public function box($string, $angle = 0)
39 |     {
40 |         static::getDriverInfo()->requireFeature(DriverInfo::FEATURE_TEXTFUNCTIONS);
41 |         $fontfile = $this->file;
42 |         if ($fontfile && DIRECTORY_SEPARATOR === '\\') {
43 |             // On Windows imageftbbox() throws a "Could not find/open font" error if $fontfile is not an absolute path.
44 |             $fontfileRealpath = realpath($fontfile);
45 |             if ($fontfileRealpath !== false) {
46 |                 $fontfile = $fontfileRealpath;
47 |             }
48 |         }
49 | 
50 |         $angle = -1 * $angle;
51 |         $info = imageftbbox($this->size, $angle, $fontfile, $string);
52 |         $xs = array($info[0], $info[2], $info[4], $info[6]);
53 |         $ys = array($info[1], $info[3], $info[5], $info[7]);
54 |         $width = abs(max($xs) - min($xs));
55 |         $height = abs(max($ys) - min($ys));
56 | 
57 |         return $this->getClassFactory()->createBox($width, $height);
58 |     }
59 | }
60 | 


--------------------------------------------------------------------------------
/src/Gd/Layers.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Gd;
 13 | 
 14 | use Imagine\Driver\InfoProvider;
 15 | use Imagine\Exception\InvalidArgumentException;
 16 | use Imagine\Exception\NotSupportedException;
 17 | use Imagine\Exception\RuntimeException;
 18 | use Imagine\Factory\ClassFactoryInterface;
 19 | use Imagine\Image\AbstractLayers;
 20 | use Imagine\Image\Metadata\MetadataBag;
 21 | use Imagine\Image\Palette\PaletteInterface;
 22 | 
 23 | class Layers extends AbstractLayers implements InfoProvider
 24 | {
 25 |     /**
 26 |      * @var \Imagine\Gd\Image
 27 |      */
 28 |     private $image;
 29 | 
 30 |     /**
 31 |      * @var int
 32 |      */
 33 |     private $offset;
 34 | 
 35 |     /**
 36 |      * @var resource|\GdImage
 37 |      */
 38 |     private $resource;
 39 | 
 40 |     /**
 41 |      * @var \Imagine\Image\Palette\PaletteInterface
 42 |      */
 43 |     private $palette;
 44 | 
 45 |     /**
 46 |      * @param \Imagine\Gd\Image $image
 47 |      * @param \Imagine\Image\Palette\PaletteInterface $palette
 48 |      * @param resource|\GdImage $resource
 49 |      * @param int $initialOffset
 50 |      *
 51 |      * @throws \Imagine\Exception\RuntimeException
 52 |      */
 53 |     public function __construct(Image $image, PaletteInterface $palette, $resource, $initialOffset = 0)
 54 |     {
 55 |         if (!$resource instanceof \GdImage && !is_resource($resource)) {
 56 |             throw new RuntimeException('Invalid Gd resource provided');
 57 |         }
 58 | 
 59 |         $this->image = $image;
 60 |         $this->resource = $resource;
 61 |         $this->offset = (int) $initialOffset;
 62 |         $this->palette = $palette;
 63 |     }
 64 | 
 65 |     /**
 66 |      * {@inheritdoc}
 67 |      *
 68 |      * @see \Imagine\Driver\InfoProvider::getDriverInfo()
 69 |      * @since 1.3.0
 70 |      */
 71 |     public static function getDriverInfo($required = true)
 72 |     {
 73 |         return DriverInfo::get($required);
 74 |     }
 75 | 
 76 |     /**
 77 |      * {@inheritdoc}
 78 |      *
 79 |      * @see \Imagine\Image\LayersInterface::merge()
 80 |      */
 81 |     public function merge()
 82 |     {
 83 |     }
 84 | 
 85 |     /**
 86 |      * {@inheritdoc}
 87 |      *
 88 |      * @see \Imagine\Image\LayersInterface::coalesce()
 89 |      */
 90 |     public function coalesce()
 91 |     {
 92 |         return $this;
 93 |     }
 94 | 
 95 |     /**
 96 |      * {@inheritdoc}
 97 |      *
 98 |      * @see \Imagine\Image\LayersInterface::animate()
 99 |      */
100 |     public function animate($format, $delay, $loops)
101 |     {
102 |         return $this;
103 |     }
104 | 
105 |     /**
106 |      * {@inheritdoc}
107 |      *
108 |      * @see \Iterator::current()
109 |      *
110 |      * @return mixed
111 |      */
112 |     #[\ReturnTypeWillChange]
113 |     public function current()
114 |     {
115 |         return $this->getClassFactory()->createImage(ClassFactoryInterface::HANDLE_GD, $this->resource, $this->palette, new MetadataBag());
116 |     }
117 | 
118 |     /**
119 |      * {@inheritdoc}
120 |      *
121 |      * @see \Iterator::key()
122 |      *
123 |      * @return mixed
124 |      */
125 |     #[\ReturnTypeWillChange]
126 |     public function key()
127 |     {
128 |         return $this->offset;
129 |     }
130 | 
131 |     /**
132 |      * {@inheritdoc}
133 |      *
134 |      * @see \Iterator::next()
135 |      *
136 |      * @return mixed
137 |      */
138 |     #[\ReturnTypeWillChange]
139 |     public function next()
140 |     {
141 |         ++$this->offset;
142 |     }
143 | 
144 |     /**
145 |      * {@inheritdoc}
146 |      *
147 |      * @see \Iterator::rewind()
148 |      *
149 |      * @return void
150 |      */
151 |     #[\ReturnTypeWillChange]
152 |     public function rewind()
153 |     {
154 |         $this->offset = 0;
155 |     }
156 | 
157 |     /**
158 |      * {@inheritdoc}
159 |      *
160 |      * @see \Iterator::valid()
161 |      *
162 |      * @return bool
163 |      */
164 |     #[\ReturnTypeWillChange]
165 |     public function valid()
166 |     {
167 |         return $this->offset < 1;
168 |     }
169 | 
170 |     /**
171 |      * {@inheritdoc}
172 |      *
173 |      * @see \Countable::count()
174 |      *
175 |      * @return int
176 |      */
177 |     #[\ReturnTypeWillChange]
178 |     public function count()
179 |     {
180 |         return 1;
181 |     }
182 | 
183 |     /**
184 |      * {@inheritdoc}
185 |      *
186 |      * @see \ArrayAccess::offsetExists()
187 |      *
188 |      * @return bool
189 |      */
190 |     #[\ReturnTypeWillChange]
191 |     public function offsetExists($offset)
192 |     {
193 |         return $offset === 0;
194 |     }
195 | 
196 |     /**
197 |      * {@inheritdoc}
198 |      *
199 |      * @see \ArrayAccess::offsetGet()
200 |      *
201 |      * @return mixed
202 |      */
203 |     #[\ReturnTypeWillChange]
204 |     public function offsetGet($offset)
205 |     {
206 |         if ($offset === 0) {
207 |             return $this->getClassFactory()->createImage(ClassFactoryInterface::HANDLE_GD, $this->resource, $this->palette, new MetadataBag());
208 |         }
209 | 
210 |         throw new InvalidArgumentException('GD only supports one layer at offset 0');
211 |     }
212 | 
213 |     /**
214 |      * {@inheritdoc}
215 |      *
216 |      * @see \ArrayAccess::offsetSet()
217 |      *
218 |      * @return void
219 |      */
220 |     #[\ReturnTypeWillChange]
221 |     public function offsetSet($offset, $value)
222 |     {
223 |         throw new NotSupportedException('GD does not support layer set');
224 |     }
225 | 
226 |     /**
227 |      * {@inheritdoc}
228 |      *
229 |      * @see \ArrayAccess::offsetUnset()
230 |      *
231 |      * @return void
232 |      */
233 |     #[\ReturnTypeWillChange]
234 |     public function offsetUnset($offset)
235 |     {
236 |         throw new NotSupportedException('GD does not support layer unset');
237 |     }
238 | }
239 | 


--------------------------------------------------------------------------------
/src/Gmagick/DriverInfo.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | namespace Imagine\Gmagick;
  4 | 
  5 | use Imagine\Driver\AbstractInfo;
  6 | use Imagine\Exception\NotSupportedException;
  7 | use Imagine\Image\Format;
  8 | use Imagine\Image\FormatList;
  9 | 
 10 | /**
 11 |  * Provide information and features supported by the Gmagick graphics driver.
 12 |  *
 13 |  * @since 1.3.0
 14 |  */
 15 | class DriverInfo extends AbstractInfo
 16 | {
 17 |     /**
 18 |      * @var static|\Imagine\Exception\NotSupportedException|null
 19 |      */
 20 |     private static $instance;
 21 | 
 22 |     private $availableMethods = array();
 23 | 
 24 |     /**
 25 |      * @throws \Imagine\Exception\NotSupportedException
 26 |      */
 27 |     protected function __construct()
 28 |     {
 29 |         if (!class_exists('Gmagick') || !extension_loaded('gmagick')) {
 30 |             throw new NotSupportedException('Gmagick driver not installed');
 31 |         }
 32 |         $m = null;
 33 |         $extensionVersion = phpversion('gmagick');
 34 |         $driverRawVersion = is_string($extensionVersion) ? $extensionVersion : '';
 35 |         $driverSemverVersion = preg_match('/^.*?(\d+\.\d+\.\d+)/', $driverRawVersion, $m) ? $m[1] : '';
 36 |         $gmagick = new \Gmagick();
 37 |         $engineVersion = $gmagick->getversion();
 38 |         if (is_array($engineVersion) && isset($engineVersion['versionString']) && is_string($engineVersion['versionString'])) {
 39 |             if (preg_match('/^.*?(\d+\.\d+\.\d+(-\d+)?(\s+Q\d+)?)/i', $engineVersion['versionString'], $m)) {
 40 |                 $engineRawVersion = $m[1];
 41 |             } else {
 42 |                 $engineRawVersion = $engineVersion['versionString'];
 43 |             }
 44 |         } else {
 45 |             $engineRawVersion = '';
 46 |         }
 47 |         $engineSemverVersion = preg_match('/^.*?(\d+\.\d+\.\d+)/', $engineRawVersion, $m) ? $m[1] : '';
 48 |         parent::__construct($driverRawVersion, $driverSemverVersion, $engineRawVersion, $engineSemverVersion);
 49 |     }
 50 | 
 51 |     /**
 52 |      * {@inheritdoc}
 53 |      *
 54 |      * @see \Imagine\Driver\Info::get()
 55 |      */
 56 |     public static function get($required = true)
 57 |     {
 58 |         if (self::$instance === null) {
 59 |             try {
 60 |                 self::$instance = new static();
 61 |             } catch (NotSupportedException $x) {
 62 |                 self::$instance = $x;
 63 |             }
 64 |         }
 65 |         if (self::$instance instanceof self) {
 66 |             return self::$instance;
 67 |         }
 68 | 
 69 |         if ($required) {
 70 |             throw self::$instance;
 71 |         }
 72 | 
 73 |         return null;
 74 |     }
 75 | 
 76 |     /**
 77 |      * {@inheritdoc}
 78 |      *
 79 |      * @see \Imagine\Driver\AbstractInfo::checkFeature()
 80 |      */
 81 |     protected function checkFeature($feature)
 82 |     {
 83 |         switch ($feature) {
 84 |             case static::FEATURE_COALESCELAYERS:
 85 |                 throw new NotSupportedException('Gmagick does not support coalescing');
 86 |             case static::FEATURE_NEGATEIMAGE:
 87 |                 if (!$this->isMethodAvailale('negateimage')) {
 88 |                     throw new NotSupportedException('Gmagick version 1.1.0 RC3 is required for negative effect');
 89 |                 }
 90 |                 break;
 91 |             case static::FEATURE_COLORIZEIMAGE:
 92 |                 throw new NotSupportedException('Gmagick does not support colorize');
 93 |             case static::FEATURE_SHARPENIMAGE:
 94 |                 throw new NotSupportedException('Gmagick does not support sharpen yet');
 95 |             case static::FEATURE_CONVOLVEIMAGE:
 96 |                 if (!$this->isMethodAvailale('convolveimage')) {
 97 |                     throw new NotSupportedException('The version of Gmagick extension is too old: it does not support convolve (you need gmagick 2.0.1RC2 or later.');
 98 |                 }
 99 |                 break;
100 |             case static::FEATURE_CUSTOMRESOLUTION:
101 |                 throw new NotSupportedException('Gmagick does not support setting custom resolutions');
102 |             case static::FEATURE_GETCMYKCOLORSCORRECTLY:
103 |                 throw new NotSupportedException('Gmagick fails to read CMYK colors properly, see https://bugs.php.net/bug.php?id=67435');
104 |             case static::FEATURE_TRANSPARENCY:
105 |                 throw new NotSupportedException("Gmagick doesn't support transparency");
106 |             case static::FEATURE_ADDLAYERSTOEMPTYIMAGE:
107 |                 throw new NotSupportedException("Can't animate empty images because Gmagick is affected by bug https://bugs.php.net/bug.php?id=62309");
108 |             case static::FEATURE_DETECTGRAYCOLORSPACE:
109 |                 throw new NotSupportedException('Gmagick does not support gray colorspace, because of the lack of image type support');
110 |         }
111 |     }
112 | 
113 |     /**
114 |      * {@inheritdoc}
115 |      *
116 |      * @see \Imagine\Driver\AbstractInfo::buildSupportedFormats()
117 |      */
118 |     protected function buildSupportedFormats()
119 |     {
120 |         $supportedFormats = array();
121 |         $gmagick = new \Gmagick();
122 |         $magickFormats = array_map('strtolower', $gmagick->queryFormats());
123 |         foreach (Format::getAll() as $format) {
124 |             if (in_array($format->getID(), $magickFormats, true) || array_intersect($magickFormats, $format->getAlternativeIDs()) !== array()) {
125 |                 $supportedFormats[] = $format;
126 |             }
127 |         }
128 | 
129 |         return new FormatList($supportedFormats);
130 |     }
131 | 
132 |     /**
133 |      * @param string $methodName
134 |      *
135 |      * @return bool
136 |      */
137 |     private function isMethodAvailale($methodName)
138 |     {
139 |         if (!isset($this->availableMethods[$methodName])) {
140 |             $gmagick = new \Gmagick();
141 |             $this->availableMethods[$methodName] = method_exists($gmagick, $methodName);
142 |         }
143 | 
144 |         return $this->availableMethods[$methodName];
145 |     }
146 | }
147 | 


--------------------------------------------------------------------------------
/src/Gmagick/Effects.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Gmagick;
 13 | 
 14 | use Imagine\Driver\InfoProvider;
 15 | use Imagine\Effects\EffectsInterface;
 16 | use Imagine\Exception\InvalidArgumentException;
 17 | use Imagine\Exception\RuntimeException;
 18 | use Imagine\Image\Palette\Color\ColorInterface;
 19 | use Imagine\Utils\Matrix;
 20 | 
 21 | /**
 22 |  * Effects implementation using the Gmagick PHP extension.
 23 |  */
 24 | class Effects implements EffectsInterface, InfoProvider
 25 | {
 26 |     /**
 27 |      * @var \Gmagick
 28 |      */
 29 |     private $gmagick;
 30 | 
 31 |     /**
 32 |      * Initialize the instance.
 33 |      *
 34 |      * @param \Gmagick $gmagick
 35 |      */
 36 |     public function __construct(\Gmagick $gmagick)
 37 |     {
 38 |         $this->gmagick = $gmagick;
 39 |     }
 40 | 
 41 |     /**
 42 |      * {@inheritdoc}
 43 |      *
 44 |      * @see \Imagine\Driver\InfoProvider::getDriverInfo()
 45 |      * @since 1.3.0
 46 |      */
 47 |     public static function getDriverInfo($required = true)
 48 |     {
 49 |         return DriverInfo::get($required);
 50 |     }
 51 | 
 52 |     /**
 53 |      * {@inheritdoc}
 54 |      *
 55 |      * @see \Imagine\Effects\EffectsInterface::gamma()
 56 |      */
 57 |     public function gamma($correction)
 58 |     {
 59 |         try {
 60 |             $this->gmagick->gammaimage($correction);
 61 |         } catch (\GmagickException $e) {
 62 |             throw new RuntimeException('Failed to apply gamma correction to the image', $e->getCode(), $e);
 63 |         }
 64 | 
 65 |         return $this;
 66 |     }
 67 | 
 68 |     /**
 69 |      * {@inheritdoc}
 70 |      *
 71 |      * @see \Imagine\Effects\EffectsInterface::negative()
 72 |      */
 73 |     public function negative()
 74 |     {
 75 |         static::getDriverInfo()->requireFeature(DriverInfo::FEATURE_NEGATEIMAGE);
 76 |         try {
 77 |             $this->gmagick->negateimage(false, \Gmagick::CHANNEL_ALL);
 78 |         } catch (\GmagickException $e) {
 79 |             throw new RuntimeException('Failed to negate the image', $e->getCode(), $e);
 80 |         }
 81 | 
 82 |         return $this;
 83 |     }
 84 | 
 85 |     /**
 86 |      * {@inheritdoc}
 87 |      *
 88 |      * @see \Imagine\Effects\EffectsInterface::grayscale()
 89 |      */
 90 |     public function grayscale()
 91 |     {
 92 |         try {
 93 |             $this->gmagick->setimagetype(defined('Gmagick::IMGTYPE_GRAYSCALE') ? \Gmagick::IMGTYPE_GRAYSCALE : 2);
 94 |         } catch (\GmagickException $e) {
 95 |             throw new RuntimeException('Failed to grayscale the image', $e->getCode(), $e);
 96 |         }
 97 | 
 98 |         return $this;
 99 |     }
100 | 
101 |     /**
102 |      * {@inheritdoc}
103 |      *
104 |      * @see \Imagine\Effects\EffectsInterface::colorize()
105 |      */
106 |     public function colorize(ColorInterface $color)
107 |     {
108 |         static::getDriverInfo()->requireFeature(DriverInfo::FEATURE_COLORIZEIMAGE);
109 |     }
110 | 
111 |     /**
112 |      * {@inheritdoc}
113 |      *
114 |      * @see \Imagine\Effects\EffectsInterface::sharpen()
115 |      */
116 |     public function sharpen()
117 |     {
118 |         static::getDriverInfo()->requireFeature(DriverInfo::FEATURE_SHARPENIMAGE);
119 |     }
120 | 
121 |     /**
122 |      * {@inheritdoc}
123 |      *
124 |      * @see \Imagine\Effects\EffectsInterface::blur()
125 |      */
126 |     public function blur($sigma = 1)
127 |     {
128 |         try {
129 |             $this->gmagick->blurimage(0, $sigma);
130 |         } catch (\GmagickException $e) {
131 |             throw new RuntimeException('Failed to blur the image', $e->getCode(), $e);
132 |         }
133 | 
134 |         return $this;
135 |     }
136 | 
137 |     /**
138 |      * {@inheritdoc}
139 |      *
140 |      * @see \Imagine\Effects\EffectsInterface::brightness()
141 |      */
142 |     public function brightness($brightness)
143 |     {
144 |         $brightness = (int) round($brightness);
145 |         if ($brightness < -100 || $brightness > 100) {
146 |             throw new InvalidArgumentException(sprintf('The %1$s argument can range from %2$d to %3$d, but you specified %4$d.', '$brightness', -100, 100, $brightness));
147 |         }
148 |         try {
149 |             // This *emulates* setting the brightness
150 |             $sign = $brightness < 0 ? -1 : 1;
151 |             $v = abs($brightness) / 100;
152 |             if ($sign > 0) {
153 |                 $v = (2 / (sin(($v * .99999 * M_PI_2) + M_PI_2))) - 2;
154 |             }
155 |             $this->gmagick->modulateimage(100 + $sign * $v * 100, 100, 100);
156 |         } catch (\GmagickException $e) {
157 |             throw new RuntimeException('Failed to brightness the image');
158 |         }
159 | 
160 |         return $this;
161 |     }
162 | 
163 |     /**
164 |      * {@inheritdoc}
165 |      *
166 |      * @see \Imagine\Effects\EffectsInterface::convolve()
167 |      */
168 |     public function convolve(Matrix $matrix)
169 |     {
170 |         static::getDriverInfo()->requireFeature(DriverInfo::FEATURE_CONVOLVEIMAGE);
171 |         if ($matrix->getWidth() !== 3 || $matrix->getHeight() !== 3) {
172 |             throw new InvalidArgumentException(sprintf('A convolution matrix must be 3x3 (%dx%d provided).', $matrix->getWidth(), $matrix->getHeight()));
173 |         }
174 |         try {
175 |             $this->gmagick->convolveimage($matrix->getValueList());
176 |         } catch (\GmagickException $e) {
177 |             throw new RuntimeException('Failed to convolve the image');
178 |         }
179 | 
180 |         return $this;
181 |     }
182 | }
183 | 


--------------------------------------------------------------------------------
/src/Gmagick/Font.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Gmagick;
13 | 
14 | use Imagine\Driver\InfoProvider;
15 | use Imagine\Image\AbstractFont;
16 | use Imagine\Image\Palette\Color\ColorInterface;
17 | 
18 | /**
19 |  * Font implementation using the Gmagick PHP extension.
20 |  */
21 | final class Font extends AbstractFont implements InfoProvider
22 | {
23 |     /**
24 |      * @var \Gmagick
25 |      */
26 |     private $gmagick;
27 | 
28 |     /**
29 |      * @param \Gmagick $gmagick
30 |      * @param string $file
31 |      * @param int $size
32 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
33 |      */
34 |     public function __construct(\Gmagick $gmagick, $file, $size, ColorInterface $color)
35 |     {
36 |         $this->gmagick = $gmagick;
37 | 
38 |         parent::__construct($file, $size, $color);
39 |     }
40 | 
41 |     /**
42 |      * {@inheritdoc}
43 |      *
44 |      * @see \Imagine\Driver\InfoProvider::getDriverInfo()
45 |      * @since 1.3.0
46 |      */
47 |     public static function getDriverInfo($required = true)
48 |     {
49 |         return DriverInfo::get($required);
50 |     }
51 | 
52 |     /**
53 |      * {@inheritdoc}
54 |      *
55 |      * @see \Imagine\Image\FontInterface::box()
56 |      */
57 |     public function box($string, $angle = 0)
58 |     {
59 |         $text = new \GmagickDraw();
60 | 
61 |         $text->setfont($this->file);
62 |         /*
63 |          * @see http://www.php.net/manual/en/imagick.queryfontmetrics.php#101027
64 |          *
65 |          * ensure font resolution is the same as GD's hard-coded 96
66 |          */
67 |         $text->setfontsize((int) ($this->size * (96 / 72)));
68 |         $text->setfontstyle(\Gmagick::STYLE_OBLIQUE);
69 | 
70 |         $info = $this->gmagick->queryfontmetrics($text, $string);
71 | 
72 |         $box = $this->getClassFactory()->createBox($info['textWidth'], $info['textHeight']);
73 | 
74 |         return $box;
75 |     }
76 | }
77 | 


--------------------------------------------------------------------------------
/src/Image/AbstractFont.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | use Imagine\Factory\ClassFactory;
 16 | use Imagine\Factory\ClassFactoryAwareInterface;
 17 | use Imagine\Factory\ClassFactoryInterface;
 18 | use Imagine\Image\Palette\Color\ColorInterface;
 19 | 
 20 | /**
 21 |  * Abstract font base class.
 22 |  */
 23 | abstract class AbstractFont implements FontInterface, ClassFactoryAwareInterface
 24 | {
 25 |     /**
 26 |      * @var \Imagine\Factory\ClassFactoryInterface|null
 27 |      */
 28 |     private $classFactory;
 29 | 
 30 |     /**
 31 |      * @var string
 32 |      */
 33 |     protected $file;
 34 | 
 35 |     /**
 36 |      * @var int
 37 |      */
 38 |     protected $size;
 39 | 
 40 |     /**
 41 |      * @var \Imagine\Image\Palette\Color\ColorInterface
 42 |      */
 43 |     protected $color;
 44 | 
 45 |     /**
 46 |      * Constructs a font with specified $file, $size and $color.
 47 |      *
 48 |      * The font size is to be specified in points (e.g. 10pt means 10)
 49 |      *
 50 |      * @param string $file
 51 |      * @param int $size
 52 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 53 |      */
 54 |     public function __construct($file, $size, ColorInterface $color)
 55 |     {
 56 |         $this->file = $file;
 57 |         $this->size = $size;
 58 |         $this->color = $color;
 59 |     }
 60 | 
 61 |     /**
 62 |      * {@inheritdoc}
 63 |      *
 64 |      * @see \Imagine\Image\FontInterface::getFile()
 65 |      */
 66 |     final public function getFile()
 67 |     {
 68 |         return $this->file;
 69 |     }
 70 | 
 71 |     /**
 72 |      * {@inheritdoc}
 73 |      *
 74 |      * @see \Imagine\Image\FontInterface::getSize()
 75 |      */
 76 |     final public function getSize()
 77 |     {
 78 |         return $this->size;
 79 |     }
 80 | 
 81 |     /**
 82 |      * {@inheritdoc}
 83 |      *
 84 |      * @see \Imagine\Image\FontInterface::getColor()
 85 |      */
 86 |     final public function getColor()
 87 |     {
 88 |         return $this->color;
 89 |     }
 90 | 
 91 |     /**
 92 |      * {@inheritdoc}
 93 |      *
 94 |      * @see \Imagine\Image\FontInterface::wrapText()
 95 |      */
 96 |     public function wrapText($string, $maxWidth, $angle = 0)
 97 |     {
 98 |         $string = (string) $string;
 99 |         if ($string === '') {
100 |             return $string;
101 |         }
102 |         $maxWidth = (int) round($maxWidth);
103 |         if ($maxWidth < 1) {
104 |             throw new InvalidArgumentException(sprintf('The $maxWidth parameter of wrapText must be greater than 0.'));
105 |         }
106 |         $words = explode(' ', $string);
107 |         $lines = array();
108 |         $currentLine = null;
109 |         foreach ($words as $word) {
110 |             if ($currentLine === null) {
111 |                 $currentLine = $word;
112 |             } else {
113 |                 $testLine = $currentLine . ' ' . $word;
114 |                 $testbox = $this->box($testLine, $angle);
115 |                 if ($testbox->getWidth() <= $maxWidth) {
116 |                     $currentLine = $testLine;
117 |                 } else {
118 |                     $lines[] = $currentLine;
119 |                     $currentLine = $word;
120 |                 }
121 |             }
122 |         }
123 |         if ($currentLine !== null) {
124 |             $lines[] = $currentLine;
125 |         }
126 | 
127 |         return implode("\n", $lines);
128 |     }
129 | 
130 |     /**
131 |      * {@inheritdoc}
132 |      *
133 |      * @see \Imagine\Factory\ClassFactoryAwareInterface::getClassFactory()
134 |      */
135 |     public function getClassFactory()
136 |     {
137 |         if ($this->classFactory === null) {
138 |             $this->classFactory = new ClassFactory();
139 |         }
140 | 
141 |         return $this->classFactory;
142 |     }
143 | 
144 |     /**
145 |      * {@inheritdoc}
146 |      *
147 |      * @see \Imagine\Factory\ClassFactoryAwareInterface::setClassFactory()
148 |      */
149 |     public function setClassFactory(ClassFactoryInterface $classFactory)
150 |     {
151 |         $this->classFactory = $classFactory;
152 | 
153 |         return $this;
154 |     }
155 | }
156 | 


--------------------------------------------------------------------------------
/src/Image/AbstractImagine.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | use Imagine\Factory\ClassFactory;
 16 | use Imagine\Factory\ClassFactoryInterface;
 17 | use Imagine\Image\Metadata\MetadataReaderInterface;
 18 | 
 19 | abstract class AbstractImagine implements ImagineInterface
 20 | {
 21 |     /**
 22 |      * @var \Imagine\Image\Metadata\MetadataReaderInterface|null
 23 |      */
 24 |     private $metadataReader;
 25 | 
 26 |     /**
 27 |      * @var \Imagine\Factory\ClassFactoryInterface
 28 |      */
 29 |     private $classFactory;
 30 | 
 31 |     /**
 32 |      * {@inheritdoc}
 33 |      *
 34 |      * @see \Imagine\Image\ImagineInterface::setMetadataReader()
 35 |      */
 36 |     public function setMetadataReader(MetadataReaderInterface $metadataReader)
 37 |     {
 38 |         $this->metadataReader = $metadataReader;
 39 | 
 40 |         return $this;
 41 |     }
 42 | 
 43 |     /**
 44 |      * {@inheritdoc}
 45 |      *
 46 |      * @see \Imagine\Image\ImagineInterface::getMetadataReader()
 47 |      */
 48 |     public function getMetadataReader()
 49 |     {
 50 |         if ($this->metadataReader === null) {
 51 |             $this->metadataReader = $this->getClassFactory()->createMetadataReader();
 52 |         }
 53 | 
 54 |         return $this->metadataReader;
 55 |     }
 56 | 
 57 |     /**
 58 |      * {@inheritdoc}
 59 |      *
 60 |      * @see \Imagine\Factory\ClassFactoryAwareInterface::setClassFactory()
 61 |      */
 62 |     public function setClassFactory(ClassFactoryInterface $classFactory)
 63 |     {
 64 |         $this->classFactory = $classFactory;
 65 | 
 66 |         return $this;
 67 |     }
 68 | 
 69 |     /**
 70 |      * {@inheritdoc}
 71 |      *
 72 |      * @see \Imagine\Factory\ClassFactoryAwareInterface::getClassFactory()
 73 |      */
 74 |     public function getClassFactory()
 75 |     {
 76 |         if ($this->classFactory === null) {
 77 |             $this->classFactory = new ClassFactory();
 78 |         }
 79 | 
 80 |         return $this->classFactory;
 81 |     }
 82 | 
 83 |     /**
 84 |      * Checks a path that could be used with ImagineInterface::open and returns
 85 |      * a proper string.
 86 |      *
 87 |      * @param string|object $path
 88 |      *
 89 |      * @throws \Imagine\Exception\InvalidArgumentException in case the given path is invalid
 90 |      *
 91 |      * @return string
 92 |      */
 93 |     protected function checkPath($path)
 94 |     {
 95 |         // provide compatibility with objects such as \SplFileInfo
 96 |         if (is_object($path) && method_exists($path, '__toString')) {
 97 |             $path = (string) $path;
 98 |         }
 99 | 
100 |         $handle = @fopen($path, 'r');
101 | 
102 |         if ($handle === false) {
103 |             throw new InvalidArgumentException(sprintf('File %s does not exist.', $path));
104 |         }
105 | 
106 |         fclose($handle);
107 | 
108 |         return $path;
109 |     }
110 | }
111 | 


--------------------------------------------------------------------------------
/src/Image/AbstractLayers.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | use Imagine\Factory\ClassFactory;
 15 | use Imagine\Factory\ClassFactoryAwareInterface;
 16 | use Imagine\Factory\ClassFactoryInterface;
 17 | 
 18 | abstract class AbstractLayers implements LayersInterface, ClassFactoryAwareInterface
 19 | {
 20 |     /**
 21 |      * @var \Imagine\Factory\ClassFactoryInterface|null
 22 |      */
 23 |     private $classFactory;
 24 | 
 25 |     /**
 26 |      * {@inheritdoc}
 27 |      *
 28 |      * @see \Imagine\Image\LayersInterface::add()
 29 |      */
 30 |     public function add(ImageInterface $image)
 31 |     {
 32 |         $this[] = $image;
 33 | 
 34 |         return $this;
 35 |     }
 36 | 
 37 |     /**
 38 |      * {@inheritdoc}
 39 |      *
 40 |      * @see \Imagine\Image\LayersInterface::set()
 41 |      */
 42 |     public function set($offset, ImageInterface $image)
 43 |     {
 44 |         $this[$offset] = $image;
 45 | 
 46 |         return $this;
 47 |     }
 48 | 
 49 |     /**
 50 |      * {@inheritdoc}
 51 |      *
 52 |      * @see \Imagine\Image\LayersInterface::remove()
 53 |      */
 54 |     public function remove($offset)
 55 |     {
 56 |         unset($this[$offset]);
 57 | 
 58 |         return $this;
 59 |     }
 60 | 
 61 |     /**
 62 |      * {@inheritdoc}
 63 |      *
 64 |      * @see \Imagine\Image\LayersInterface::get()
 65 |      */
 66 |     public function get($offset)
 67 |     {
 68 |         return $this[$offset];
 69 |     }
 70 | 
 71 |     /**
 72 |      * {@inheritdoc}
 73 |      *
 74 |      * @see \Imagine\Image\LayersInterface::has()
 75 |      */
 76 |     public function has($offset)
 77 |     {
 78 |         return isset($this[$offset]);
 79 |     }
 80 | 
 81 |     /**
 82 |      * {@inheritdoc}
 83 |      *
 84 |      * @see \Imagine\Factory\ClassFactoryAwareInterface::setClassFactory()
 85 |      */
 86 |     public function setClassFactory(ClassFactoryInterface $classFactory)
 87 |     {
 88 |         $this->classFactory = $classFactory;
 89 | 
 90 |         return $this;
 91 |     }
 92 | 
 93 |     /**
 94 |      * {@inheritdoc}
 95 |      *
 96 |      * @see \Imagine\Factory\ClassFactoryAwareInterface::getClassFactory()
 97 |      */
 98 |     public function getClassFactory()
 99 |     {
100 |         if ($this->classFactory === null) {
101 |             $this->classFactory = new ClassFactory();
102 |         }
103 | 
104 |         return $this->classFactory;
105 |     }
106 | }
107 | 


--------------------------------------------------------------------------------
/src/Image/Box.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | 
 16 | /**
 17 |  * A box implementation.
 18 |  */
 19 | final class Box implements BoxInterface
 20 | {
 21 |     /**
 22 |      * @var int
 23 |      */
 24 |     private $width;
 25 | 
 26 |     /**
 27 |      * @var int
 28 |      */
 29 |     private $height;
 30 | 
 31 |     /**
 32 |      * Constructs the Size with given width and height.
 33 |      *
 34 |      * @param int $width
 35 |      * @param int $height
 36 |      *
 37 |      * @throws \Imagine\Exception\InvalidArgumentException
 38 |      */
 39 |     public function __construct($width, $height)
 40 |     {
 41 |         if (!\is_int($width)) {
 42 |             $width = (int) round($width);
 43 |         }
 44 |         if (!\is_int($height)) {
 45 |             $height = (int) round($height);
 46 |         }
 47 |         $this->width = $width;
 48 |         $this->height = $height;
 49 |         if ($this->width < 1 || $this->height < 1) {
 50 |             throw new InvalidArgumentException(sprintf('Length of either side cannot be 0 or negative, current size is %sx%s', $width, $height));
 51 |         }
 52 |     }
 53 | 
 54 |     /**
 55 |      * {@inheritdoc}
 56 |      *
 57 |      * @see \Imagine\Image\BoxInterface::getWidth()
 58 |      */
 59 |     public function getWidth()
 60 |     {
 61 |         return $this->width;
 62 |     }
 63 | 
 64 |     /**
 65 |      * {@inheritdoc}
 66 |      *
 67 |      * @see \Imagine\Image\BoxInterface::getHeight()
 68 |      */
 69 |     public function getHeight()
 70 |     {
 71 |         return $this->height;
 72 |     }
 73 | 
 74 |     /**
 75 |      * {@inheritdoc}
 76 |      *
 77 |      * @see \Imagine\Image\BoxInterface::scale()
 78 |      */
 79 |     public function scale($ratio)
 80 |     {
 81 |         $width = max(1, round($ratio * $this->width));
 82 |         $height = max(1, round($ratio * $this->height));
 83 | 
 84 |         return new self($width, $height);
 85 |     }
 86 | 
 87 |     /**
 88 |      * {@inheritdoc}
 89 |      *
 90 |      * @see \Imagine\Image\BoxInterface::increase()
 91 |      */
 92 |     public function increase($size)
 93 |     {
 94 |         return new self((int) $size + $this->width, (int) $size + $this->height);
 95 |     }
 96 | 
 97 |     /**
 98 |      * {@inheritdoc}
 99 |      *
100 |      * @see \Imagine\Image\BoxInterface::contains()
101 |      */
102 |     public function contains(BoxInterface $box, ?PointInterface $start = null)
103 |     {
104 |         $start = $start ? $start : new Point(0, 0);
105 | 
106 |         return $start->in($this) && $this->width >= $box->getWidth() + $start->getX() && $this->height >= $box->getHeight() + $start->getY();
107 |     }
108 | 
109 |     /**
110 |      * {@inheritdoc}
111 |      *
112 |      * @see \Imagine\Image\BoxInterface::square()
113 |      */
114 |     public function square()
115 |     {
116 |         return $this->width * $this->height;
117 |     }
118 | 
119 |     /**
120 |      * {@inheritdoc}
121 |      *
122 |      * @see \Imagine\Image\BoxInterface::__toString()
123 |      */
124 |     public function __toString()
125 |     {
126 |         return sprintf('%dx%d px', $this->width, $this->height);
127 |     }
128 | 
129 |     /**
130 |      * {@inheritdoc}
131 |      *
132 |      * @see \Imagine\Image\BoxInterface::widen()
133 |      */
134 |     public function widen($width)
135 |     {
136 |         return $this->scale($width / $this->width);
137 |     }
138 | 
139 |     /**
140 |      * {@inheritdoc}
141 |      *
142 |      * @see \Imagine\Image\BoxInterface::heighten()
143 |      */
144 |     public function heighten($height)
145 |     {
146 |         return $this->scale($height / $this->height);
147 |     }
148 | }
149 | 


--------------------------------------------------------------------------------
/src/Image/BoxInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image;
13 | 
14 | /**
15 |  * Interface for a box.
16 |  */
17 | interface BoxInterface
18 | {
19 |     /**
20 |      * Gets box height.
21 |      *
22 |      * @return int
23 |      */
24 |     public function getHeight();
25 | 
26 |     /**
27 |      * Gets box width.
28 |      *
29 |      * @return int
30 |      */
31 |     public function getWidth();
32 | 
33 |     /**
34 |      * Creates new BoxInterface instance with ratios applied to both sides.
35 |      *
36 |      * @param float $ratio
37 |      *
38 |      * @return static
39 |      */
40 |     public function scale($ratio);
41 | 
42 |     /**
43 |      * Creates new BoxInterface, adding given size to both sides.
44 |      *
45 |      * @param int $size
46 |      *
47 |      * @return static
48 |      */
49 |     public function increase($size);
50 | 
51 |     /**
52 |      * Checks whether current box can fit given box at a given start position,
53 |      * start position defaults to top left corner xy(0,0).
54 |      *
55 |      * @param \Imagine\Image\BoxInterface $box
56 |      * @param \Imagine\Image\PointInterface $start
57 |      *
58 |      * @return bool
59 |      */
60 |     public function contains(BoxInterface $box, ?PointInterface $start = null);
61 | 
62 |     /**
63 |      * Gets current box square, useful for getting total number of pixels in a
64 |      * given box.
65 |      *
66 |      * @return int
67 |      */
68 |     public function square();
69 | 
70 |     /**
71 |      * Returns a string representation of the current box.
72 |      *
73 |      * @return string
74 |      */
75 |     public function __toString();
76 | 
77 |     /**
78 |      * Resizes box to given width, constraining proportions and returns the new box.
79 |      *
80 |      * @param int $width
81 |      *
82 |      * @return static
83 |      */
84 |     public function widen($width);
85 | 
86 |     /**
87 |      * Resizes box to given height, constraining proportions and returns the new box.
88 |      *
89 |      * @param int $height
90 |      *
91 |      * @return static
92 |      */
93 |     public function heighten($height);
94 | }
95 | 


--------------------------------------------------------------------------------
/src/Image/Fill/FillInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Fill;
13 | 
14 | use Imagine\Image\PointInterface;
15 | 
16 | /**
17 |  * Interface for the fill.
18 |  */
19 | interface FillInterface
20 | {
21 |     /**
22 |      * Gets color of the fill for the given position.
23 |      *
24 |      * @param \Imagine\Image\PointInterface $position
25 |      *
26 |      * @return \Imagine\Image\Palette\Color\ColorInterface
27 |      */
28 |     public function getColor(PointInterface $position);
29 | }
30 | 


--------------------------------------------------------------------------------
/src/Image/Fill/Gradient/Horizontal.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Fill\Gradient;
13 | 
14 | use Imagine\Image\PointInterface;
15 | 
16 | /**
17 |  * Horizontal gradient fill.
18 |  */
19 | final class Horizontal extends Linear
20 | {
21 |     /**
22 |      * {@inheritdoc}
23 |      *
24 |      * @see \Imagine\Image\Fill\Gradient\Linear::getDistance()
25 |      */
26 |     public function getDistance(PointInterface $position)
27 |     {
28 |         return $position->getX();
29 |     }
30 | }
31 | 


--------------------------------------------------------------------------------
/src/Image/Fill/Gradient/Linear.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Fill\Gradient;
13 | 
14 | use Imagine\Image\Fill\FillInterface;
15 | use Imagine\Image\Palette\Color\ColorInterface;
16 | use Imagine\Image\PointInterface;
17 | 
18 | /**
19 |  * Linear gradient fill.
20 |  */
21 | abstract class Linear implements FillInterface
22 | {
23 |     /**
24 |      * @var int
25 |      */
26 |     private $length;
27 | 
28 |     /**
29 |      * @var \Imagine\Image\Palette\Color\ColorInterface
30 |      */
31 |     private $start;
32 | 
33 |     /**
34 |      * @var \Imagine\Image\Palette\Color\ColorInterface
35 |      */
36 |     private $end;
37 | 
38 |     /**
39 |      * Constructs a linear gradient with overall gradient length, and start and
40 |      * end shades, which default to 0 and 255 accordingly.
41 |      *
42 |      * @param int $length
43 |      * @param \Imagine\Image\Palette\Color\ColorInterface $start
44 |      * @param \Imagine\Image\Palette\Color\ColorInterface $end
45 |      */
46 |     final public function __construct($length, ColorInterface $start, ColorInterface $end)
47 |     {
48 |         $this->length = $length;
49 |         $this->start = $start;
50 |         $this->end = $end;
51 |     }
52 | 
53 |     /**
54 |      * {@inheritdoc}
55 |      *
56 |      * @see \Imagine\Image\Fill\FillInterface::getColor()
57 |      */
58 |     final public function getColor(PointInterface $position)
59 |     {
60 |         $l = $this->getDistance($position);
61 | 
62 |         if ($l >= $this->length) {
63 |             return $this->end;
64 |         }
65 | 
66 |         if ($l < 0) {
67 |             return $this->start;
68 |         }
69 | 
70 |         return $this->start->getPalette()->blend($this->start, $this->end, $l / $this->length);
71 |     }
72 | 
73 |     /**
74 |      * @return \Imagine\Image\Palette\Color\ColorInterface
75 |      */
76 |     final public function getStart()
77 |     {
78 |         return $this->start;
79 |     }
80 | 
81 |     /**
82 |      * @return \Imagine\Image\Palette\Color\ColorInterface
83 |      */
84 |     final public function getEnd()
85 |     {
86 |         return $this->end;
87 |     }
88 | 
89 |     /**
90 |      * Get the distance of the position relative to the beginning of the gradient.
91 |      *
92 |      * @param \Imagine\Image\PointInterface $position
93 |      *
94 |      * @return int
95 |      */
96 |     abstract protected function getDistance(PointInterface $position);
97 | }
98 | 


--------------------------------------------------------------------------------
/src/Image/Fill/Gradient/Vertical.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Fill\Gradient;
13 | 
14 | use Imagine\Image\PointInterface;
15 | 
16 | /**
17 |  * Vertical gradient fill.
18 |  */
19 | final class Vertical extends Linear
20 | {
21 |     /**
22 |      * {@inheritdoc}
23 |      *
24 |      * @see \Imagine\Image\Fill\Gradient\Linear::getDistance()
25 |      */
26 |     public function getDistance(PointInterface $position)
27 |     {
28 |         return $position->getY();
29 |     }
30 | }
31 | 


--------------------------------------------------------------------------------
/src/Image/FontInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image;
13 | 
14 | /**
15 |  * The font interface.
16 |  */
17 | interface FontInterface
18 | {
19 |     /**
20 |      * Gets the fontfile for current font.
21 |      *
22 |      * @return string
23 |      */
24 |     public function getFile();
25 | 
26 |     /**
27 |      * Gets font's integer point size.
28 |      *
29 |      * @return int
30 |      */
31 |     public function getSize();
32 | 
33 |     /**
34 |      * Gets font's color.
35 |      *
36 |      * @return \Imagine\Image\Palette\Color\ColorInterface
37 |      */
38 |     public function getColor();
39 | 
40 |     /**
41 |      * Gets BoxInterface of font size on the image based on string and angle.
42 |      *
43 |      * @param string $string
44 |      * @param int $angle
45 |      *
46 |      * @return \Imagine\Image\BoxInterface
47 |      */
48 |     public function box($string, $angle = 0);
49 | 
50 |     /**
51 |      * Split a string into multiple lines so that it fits a specific width.
52 |      *
53 |      * @param string $string The text to be wrapped
54 |      * @param int $maxWidth The maximum width of the text
55 |      * @param int $angle
56 |      *
57 |      * @return string
58 |      */
59 |     public function wrapText($string, $maxWidth, $angle = 0);
60 | }
61 | 


--------------------------------------------------------------------------------
/src/Image/Format.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | namespace Imagine\Image;
  4 | 
  5 | use ReflectionClass;
  6 | 
  7 | /**
  8 |  * Represent an image format.
  9 |  *
 10 |  * @since 1.3.0
 11 |  */
 12 | class Format
 13 | {
 14 |     const ID_AVIF = 'avif';
 15 | 
 16 |     const ID_BMP = 'bmp';
 17 | 
 18 |     const ID_GIF = 'gif';
 19 | 
 20 |     const ID_HEIC = 'heic';
 21 | 
 22 |     const ID_JPEG = 'jpeg';
 23 | 
 24 |     const ID_JXL = 'jxl';
 25 | 
 26 |     const ID_PNG = 'png';
 27 | 
 28 |     const ID_WBMP = 'wbmp';
 29 | 
 30 |     const ID_WEBP = 'webp';
 31 | 
 32 |     const ID_XBM = 'xbm';
 33 | 
 34 |     /**
 35 |      * @var \Imagine\Image\FormatList|null
 36 |      */
 37 |     private static $all = null;
 38 | 
 39 |     /**
 40 |      * @var string
 41 |      */
 42 |     private $id;
 43 | 
 44 |     /**
 45 |      * @var string
 46 |      */
 47 |     private $mimeType;
 48 | 
 49 |     /**
 50 |      * @var string
 51 |      */
 52 |     private $canonicalFileExtension;
 53 | 
 54 |     /**
 55 |      * @var string[]
 56 |      */
 57 |     private $alternativeIDs;
 58 | 
 59 |     /**
 60 |      * @param string $id
 61 |      * @param string $fileExtension
 62 |      * @param string $mimeType
 63 |      * @param string[] $alternativeIDs
 64 |      * @param mixed $canonicalFileExtension
 65 |      */
 66 |     private function __construct($id, $mimeType, $canonicalFileExtension, $alternativeIDs = array())
 67 |     {
 68 |         $this->id = $id;
 69 |         $this->mimeType = $mimeType;
 70 |         $this->canonicalFileExtension = $canonicalFileExtension;
 71 |         $this->alternativeIDs = $alternativeIDs;
 72 |     }
 73 | 
 74 |     /**
 75 |      * @return string
 76 |      */
 77 |     public function getID()
 78 |     {
 79 |         return $this->id;
 80 |     }
 81 | 
 82 |     /**
 83 |      * @return string
 84 |      */
 85 |     public function getMimeType()
 86 |     {
 87 |         return $this->mimeType;
 88 |     }
 89 | 
 90 |     /**
 91 |      * @return string
 92 |      */
 93 |     public function getCanonicalFileExtension()
 94 |     {
 95 |         return $this->canonicalFileExtension;
 96 |     }
 97 | 
 98 |     /**
 99 |      * @return string[]
100 |      */
101 |     public function getAlternativeIDs()
102 |     {
103 |         return $this->alternativeIDs;
104 |     }
105 | 
106 |     /**
107 |      * Get a format given its ID.
108 |      *
109 |      * @param static|string $format the format (a Format instance of a format ID)
110 |      *
111 |      * @return static|null
112 |      */
113 |     public static function get($format)
114 |     {
115 |         return static::getList()->find($format);
116 |     }
117 | 
118 |     /**
119 |      * @return static[]
120 |      */
121 |     public static function getAll()
122 |     {
123 |         return static::getList()->getAll();
124 |     }
125 | 
126 |     /**
127 |      * @return \Imagine\Image\FormatList
128 |      */
129 |     protected static function getList()
130 |     {
131 |         if (self::$all !== null) {
132 |             return self::$all;
133 |         }
134 |         $class = new ReflectionClass(get_called_class());
135 |         $formats = array();
136 |         foreach ($class->getConstants() as $constantName => $constantValue) {
137 |             if (strpos($constantName, 'ID_') === 0) {
138 |                 $formats[] = static::create($constantValue);
139 |             }
140 |         }
141 |         self::$all = new FormatList($formats);
142 | 
143 |         return self::$all;
144 |     }
145 | 
146 |     /**
147 |      * @param string $formatID
148 |      *
149 |      * @return static
150 |      */
151 |     protected static function create($formatID)
152 |     {
153 |         switch ($formatID) {
154 |             case static::ID_JPEG:
155 |                 return new static($formatID, 'image/jpeg', 'jpg', array('jpg', 'pjpeg', 'jfif'));
156 |             case static::ID_WBMP:
157 |                 return new static($formatID, 'image/vnd.wap.wbmp', $formatID);
158 |             default:
159 |                 return new static($formatID, "image/{$formatID}", $formatID);
160 |         }
161 |     }
162 | }
163 | 


--------------------------------------------------------------------------------
/src/Image/FormatList.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | namespace Imagine\Image;
 4 | 
 5 | /**
 6 |  * Holds a list of image formats.
 7 |  *
 8 |  * @since 1.3.0
 9 |  */
10 | class FormatList
11 | {
12 |     /**
13 |      * @var \Imagine\Image\Format[]
14 |      */
15 |     private $formats;
16 | 
17 |     public function __construct(array $formats)
18 |     {
19 |         $this->formats = $formats;
20 |     }
21 | 
22 |     /**
23 |      * @return \Imagine\Image\Format[]
24 |      */
25 |     public function getAll()
26 |     {
27 |         return $this->formats;
28 |     }
29 | 
30 |     /**
31 |      * @return string[]
32 |      */
33 |     public function getAllIDs()
34 |     {
35 |         $result = array();
36 |         foreach ($this->getAll() as $format) {
37 |             $result[] = $format->getID();
38 |         }
39 | 
40 |         return $result;
41 |     }
42 | 
43 |     /**
44 |      * Get a format given its ID.
45 |      *
46 |      * @param \Imagine\Image\Format|string $format the format (a Format instance of a format ID)
47 |      *
48 |      * @return \Imagine\Image\Format|null
49 |      */
50 |     public function find($format)
51 |     {
52 |         if (is_string($format)) {
53 |             $format = strtolower(trim($format));
54 |             if ($format === '') {
55 |                 return null;
56 |             }
57 |             foreach ($this->getAll() as $f) {
58 |                 if ($f->getID() === $format || in_array($format, $f->getAlternativeIDs(), true)) {
59 |                     return $f;
60 |                 }
61 |             }
62 | 
63 |             return null;
64 |         }
65 | 
66 |         return in_array($format, $this->getAll(), true) ? $format : null;
67 |     }
68 | }
69 | 


--------------------------------------------------------------------------------
/src/Image/Histogram/Bucket.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Histogram;
13 | 
14 | /**
15 |  * Bucket histogram.
16 |  */
17 | final class Bucket implements \Countable
18 | {
19 |     /**
20 |      * @var \Imagine\Image\Histogram\Range
21 |      */
22 |     private $range;
23 | 
24 |     /**
25 |      * @var int
26 |      */
27 |     private $count;
28 | 
29 |     /**
30 |      * @param \Imagine\Image\Histogram\Range $range
31 |      * @param int $count
32 |      */
33 |     public function __construct(Range $range, $count = 0)
34 |     {
35 |         $this->range = $range;
36 |         $this->count = $count;
37 |     }
38 | 
39 |     /**
40 |      * @param int $value
41 |      *
42 |      * @return $this
43 |      */
44 |     public function add($value)
45 |     {
46 |         if ($this->range->contains($value)) {
47 |             $this->count++;
48 |         }
49 | 
50 |         return $this;
51 |     }
52 | 
53 |     /**
54 |      * Get the number of elements in the bucket.
55 |      *
56 |      * @return int
57 |      */
58 |     #[\ReturnTypeWillChange]
59 |     public function count()
60 |     {
61 |         return $this->count;
62 |     }
63 | }
64 | 


--------------------------------------------------------------------------------
/src/Image/Histogram/Range.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Histogram;
13 | 
14 | use Imagine\Exception\OutOfBoundsException;
15 | 
16 | /**
17 |  * Range histogram.
18 |  */
19 | final class Range
20 | {
21 |     /**
22 |      * @var int
23 |      */
24 |     private $start;
25 | 
26 |     /**
27 |      * @var int
28 |      */
29 |     private $end;
30 | 
31 |     /**
32 |      * @param int $start
33 |      * @param int $end
34 |      *
35 |      * @throws \Imagine\Exception\OutOfBoundsException
36 |      */
37 |     public function __construct($start, $end)
38 |     {
39 |         if ($end <= $start) {
40 |             throw new OutOfBoundsException(sprintf('Range end cannot be bigger than start, %d %d given accordingly', $this->start, $this->end));
41 |         }
42 | 
43 |         $this->start = $start;
44 |         $this->end = $end;
45 |     }
46 | 
47 |     /**
48 |      * @param int $value
49 |      *
50 |      * @return bool
51 |      */
52 |     public function contains($value)
53 |     {
54 |         return $value >= $this->start && $value < $this->end;
55 |     }
56 | }
57 | 


--------------------------------------------------------------------------------
/src/Image/ImagineInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | use Imagine\Factory\ClassFactoryAwareInterface;
 15 | use Imagine\Image\Metadata\MetadataReaderInterface;
 16 | use Imagine\Image\Palette\Color\ColorInterface;
 17 | 
 18 | /**
 19 |  * The imagine interface.
 20 |  */
 21 | interface ImagineInterface extends ClassFactoryAwareInterface
 22 | {
 23 |     const VERSION = '1.5.1-dev';
 24 | 
 25 |     /**
 26 |      * Creates a new empty image with an optional background color.
 27 |      *
 28 |      * @param \Imagine\Image\BoxInterface $size
 29 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 30 |      *
 31 |      * @throws \Imagine\Exception\InvalidArgumentException
 32 |      * @throws \Imagine\Exception\RuntimeException
 33 |      *
 34 |      * @return \Imagine\Image\ImageInterface
 35 |      */
 36 |     public function create(BoxInterface $size, ?ColorInterface $color = null);
 37 | 
 38 |     /**
 39 |      * Opens an existing image from $path.
 40 |      *
 41 |      * @param string|\Imagine\File\LoaderInterface|mixed $path the file path, a LoaderInterface instance, or an object whose string representation is the image path
 42 |      *
 43 |      * @throws \Imagine\Exception\RuntimeException
 44 |      *
 45 |      * @return \Imagine\Image\ImageInterface
 46 |      */
 47 |     public function open($path);
 48 | 
 49 |     /**
 50 |      * Loads an image from a binary $string.
 51 |      *
 52 |      * @param string $string
 53 |      *
 54 |      * @throws \Imagine\Exception\RuntimeException
 55 |      *
 56 |      * @return \Imagine\Image\ImageInterface
 57 |      */
 58 |     public function load($string);
 59 | 
 60 |     /**
 61 |      * Loads an image from a resource $resource.
 62 |      *
 63 |      * @param resource $resource
 64 |      *
 65 |      * @throws \Imagine\Exception\RuntimeException
 66 |      *
 67 |      * @return \Imagine\Image\ImageInterface
 68 |      */
 69 |     public function read($resource);
 70 | 
 71 |     /**
 72 |      * Constructs a font with specified $file, $size and $color.
 73 |      *
 74 |      * The font size is to be specified in points (e.g. 10pt means 10)
 75 |      *
 76 |      * @param string $file
 77 |      * @param int $size
 78 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
 79 |      *
 80 |      * @return \Imagine\Image\FontInterface
 81 |      */
 82 |     public function font($file, $size, ColorInterface $color);
 83 | 
 84 |     /**
 85 |      * Set the object to be used to read image metadata.
 86 |      *
 87 |      * @param \Imagine\Image\Metadata\MetadataReaderInterface $metadataReader
 88 |      *
 89 |      * @return $this
 90 |      */
 91 |     public function setMetadataReader(MetadataReaderInterface $metadataReader);
 92 | 
 93 |     /**
 94 |      * Get the object to be used to read image metadata.
 95 |      *
 96 |      * @return \Imagine\Image\Metadata\MetadataReaderInterface
 97 |      */
 98 |     public function getMetadataReader();
 99 | }
100 | 


--------------------------------------------------------------------------------
/src/Image/LayersInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | /**
 15 |  * The layers interface.
 16 |  */
 17 | interface LayersInterface extends \Iterator, \Countable, \ArrayAccess
 18 | {
 19 |     /**
 20 |      * Merge layers into the original objects.
 21 |      *
 22 |      * @throws \Imagine\Exception\RuntimeException
 23 |      */
 24 |     public function merge();
 25 | 
 26 |     /**
 27 |      * Animates layers.
 28 |      *
 29 |      * @param string $format The output output format
 30 |      * @param int $delay The delay in milliseconds between two frames
 31 |      * @param int $loops The number of loops, 0 means infinite
 32 |      *
 33 |      * @throws \Imagine\Exception\InvalidArgumentException In case an invalid argument is provided
 34 |      * @throws \Imagine\Exception\RuntimeException In case the driver fails to animate
 35 |      *
 36 |      * @return $this
 37 |      */
 38 |     public function animate($format, $delay, $loops);
 39 | 
 40 |     /**
 41 |      * Coalesce layers. Each layer in the sequence is the same size as the first and composited with the next layer in
 42 |      * the sequence.
 43 |      *
 44 |      * @throws \Imagine\Exception\NotSupportedException
 45 |      *
 46 |      * @return $this
 47 |      */
 48 |     public function coalesce();
 49 | 
 50 |     /**
 51 |      * Adds an image at the end of the layers stack.
 52 |      *
 53 |      * @param \Imagine\Image\ImageInterface $image
 54 |      *
 55 |      * @throws \Imagine\Exception\RuntimeException
 56 |      *
 57 |      * @return $this
 58 |      */
 59 |     public function add(ImageInterface $image);
 60 | 
 61 |     /**
 62 |      * Set an image at offset.
 63 |      *
 64 |      * @param int $offset
 65 |      * @param \Imagine\Image\ImageInterface $image
 66 |      *
 67 |      * @throws \Imagine\Exception\RuntimeException
 68 |      * @throws \Imagine\Exception\InvalidArgumentException
 69 |      * @throws \Imagine\Exception\OutOfBoundsException
 70 |      *
 71 |      * @return $this
 72 |      */
 73 |     public function set($offset, ImageInterface $image);
 74 | 
 75 |     /**
 76 |      * Removes the image at offset.
 77 |      *
 78 |      * @param int $offset
 79 |      *
 80 |      * @throws \Imagine\Exception\RuntimeException
 81 |      * @throws \Imagine\Exception\InvalidArgumentException
 82 |      *
 83 |      * @return $this
 84 |      */
 85 |     public function remove($offset);
 86 | 
 87 |     /**
 88 |      * Returns the image at offset.
 89 |      *
 90 |      * @param int $offset
 91 |      *
 92 |      * @throws \Imagine\Exception\RuntimeException
 93 |      * @throws \Imagine\Exception\InvalidArgumentException
 94 |      *
 95 |      * @return \Imagine\Image\ImageInterface
 96 |      */
 97 |     public function get($offset);
 98 | 
 99 |     /**
100 |      * Returns true if a layer at offset is preset.
101 |      *
102 |      * @param int $offset
103 |      *
104 |      * @return bool
105 |      */
106 |     public function has($offset);
107 | }
108 | 


--------------------------------------------------------------------------------
/src/Image/Metadata/AbstractMetadataReader.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Metadata;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | use Imagine\File\Loader;
 16 | use Imagine\File\LoaderInterface;
 17 | 
 18 | /**
 19 |  * Base class for the default metadata readers.
 20 |  */
 21 | abstract class AbstractMetadataReader implements MetadataReaderInterface
 22 | {
 23 |     /**
 24 |      * {@inheritdoc}
 25 |      *
 26 |      * @see \Imagine\Image\Metadata\MetadataReaderInterface::readFile()
 27 |      */
 28 |     public function readFile($file)
 29 |     {
 30 |         $loader = $file instanceof LoaderInterface ? $file : new Loader($file);
 31 | 
 32 |         return new MetadataBag(array_merge($this->getStreamMetadata($loader), $this->extractFromFile($loader)));
 33 |     }
 34 | 
 35 |     /**
 36 |      * {@inheritdoc}
 37 |      *
 38 |      * @see \Imagine\Image\Metadata\MetadataReaderInterface::readData()
 39 |      */
 40 |     public function readData($data, $originalResource = null)
 41 |     {
 42 |         if ($originalResource !== null) {
 43 |             return new MetadataBag(array_merge($this->getStreamMetadata($originalResource), $this->extractFromData($data)));
 44 |         }
 45 | 
 46 |         return new MetadataBag($this->extractFromData($data));
 47 |     }
 48 | 
 49 |     /**
 50 |      * {@inheritdoc}
 51 |      *
 52 |      * @see \Imagine\Image\Metadata\MetadataReaderInterface::readStream()
 53 |      */
 54 |     public function readStream($resource)
 55 |     {
 56 |         if (!is_resource($resource)) {
 57 |             throw new InvalidArgumentException('Invalid resource provided.');
 58 |         }
 59 | 
 60 |         return new MetadataBag(array_merge($this->getStreamMetadata($resource), $this->extractFromStream($resource)));
 61 |     }
 62 | 
 63 |     /**
 64 |      * Gets the URI from a stream resource.
 65 |      *
 66 |      * @param resource|\Imagine\File\LoaderInterface $resource
 67 |      *
 68 |      * @return array
 69 |      */
 70 |     private function getStreamMetadata($resource)
 71 |     {
 72 |         $metadata = array();
 73 | 
 74 |         if ($resource instanceof LoaderInterface) {
 75 |             $metadata['uri'] = $resource->getPath();
 76 |             if ($resource->isLocalFile()) {
 77 |                 $metadata['filepath'] = realpath($resource->getPath());
 78 |             }
 79 |         } elseif (false !== $data = @stream_get_meta_data($resource)) {
 80 |             if (isset($data['uri'])) {
 81 |                 $metadata['uri'] = $data['uri'];
 82 |                 if (stream_is_local($resource)) {
 83 |                     $metadata['filepath'] = realpath($data['uri']);
 84 |                 }
 85 |             }
 86 |         }
 87 | 
 88 |         return $metadata;
 89 |     }
 90 | 
 91 |     /**
 92 |      * Extracts metadata from a file.
 93 |      *
 94 |      * @param string|\Imagine\File\LoaderInterface $file
 95 |      *
 96 |      * @return array An associative array of metadata
 97 |      */
 98 |     abstract protected function extractFromFile($file);
 99 | 
100 |     /**
101 |      * Extracts metadata from raw data.
102 |      *
103 |      * @param string $data
104 |      *
105 |      * @return array An associative array of metadata
106 |      */
107 |     abstract protected function extractFromData($data);
108 | 
109 |     /**
110 |      * Extracts metadata from a stream.
111 |      *
112 |      * @param resource $resource
113 |      *
114 |      * @return array An associative array of metadata
115 |      */
116 |     abstract protected function extractFromStream($resource);
117 | }
118 | 


--------------------------------------------------------------------------------
/src/Image/Metadata/DefaultMetadataReader.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Metadata;
13 | 
14 | /**
15 |  * A metadata reader that actually doesn't try to extract metadata.
16 |  */
17 | class DefaultMetadataReader extends AbstractMetadataReader
18 | {
19 |     /**
20 |      * {@inheritdoc}
21 |      *
22 |      * @see \Imagine\Image\Metadata\AbstractMetadataReader::extractFromFile()
23 |      */
24 |     protected function extractFromFile($file)
25 |     {
26 |         return array();
27 |     }
28 | 
29 |     /**
30 |      * {@inheritdoc}
31 |      *
32 |      * @see \Imagine\Image\Metadata\AbstractMetadataReader::extractFromData()
33 |      */
34 |     protected function extractFromData($data)
35 |     {
36 |         return array();
37 |     }
38 | 
39 |     /**
40 |      * {@inheritdoc}
41 |      *
42 |      * @see \Imagine\Image\Metadata\AbstractMetadataReader::extractFromStream()
43 |      */
44 |     protected function extractFromStream($resource)
45 |     {
46 |         return array();
47 |     }
48 | }
49 | 


--------------------------------------------------------------------------------
/src/Image/Metadata/ExifMetadataReader.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Metadata;
 13 | 
 14 | use Imagine\Exception\NotSupportedException;
 15 | use Imagine\File\Loader;
 16 | use Imagine\File\LoaderInterface;
 17 | use Imagine\Utils\ErrorHandling;
 18 | 
 19 | /**
 20 |  * Metadata driven by Exif information.
 21 |  */
 22 | class ExifMetadataReader extends AbstractMetadataReader
 23 | {
 24 |     /**
 25 |      * @throws \Imagine\Exception\NotSupportedException
 26 |      */
 27 |     public function __construct()
 28 |     {
 29 |         $whyNot = static::getUnsupportedReason();
 30 |         if ($whyNot !== '') {
 31 |             throw new NotSupportedException($whyNot);
 32 |         }
 33 |     }
 34 | 
 35 |     /**
 36 |      * Get the reason why this metadata reader is not supported.
 37 |      *
 38 |      * @return string empty string if the reader is available
 39 |      */
 40 |     public static function getUnsupportedReason()
 41 |     {
 42 |         if (!function_exists('exif_read_data')) {
 43 |             return 'The PHP EXIF extension is required to use the ExifMetadataReader';
 44 |         }
 45 | 
 46 |         if (PHP_VERSION_ID < 70200) {
 47 |             if (!in_array('data', stream_get_wrappers(), true)) {
 48 |                 return 'The data:// stream wrapper must be enabled';
 49 |             }
 50 |             if (in_array(ini_get('allow_url_fopen'), array('', '0', 0), true)) {
 51 |                 return 'The allow_url_fopen php.ini configuration key must be set to 1';
 52 |             }
 53 |         }
 54 | 
 55 |         return '';
 56 |     }
 57 | 
 58 |     /**
 59 |      * Is this metadata reader supported?
 60 |      *
 61 |      * @return bool
 62 |      */
 63 |     public static function isSupported()
 64 |     {
 65 |         return static::getUnsupportedReason() === '';
 66 |     }
 67 | 
 68 |     /**
 69 |      * {@inheritdoc}
 70 |      *
 71 |      * @see \Imagine\Image\Metadata\AbstractMetadataReader::extractFromFile()
 72 |      */
 73 |     protected function extractFromFile($file)
 74 |     {
 75 |         $loader = $file instanceof LoaderInterface ? $file : new Loader($file);
 76 | 
 77 |         if ($loader->isLocalFile()) {
 78 |             return $this->extract($loader->getPath());
 79 |         }
 80 | 
 81 |         return $this->doReadData($loader->getData());
 82 |     }
 83 | 
 84 |     /**
 85 |      * {@inheritdoc}
 86 |      *
 87 |      * @see \Imagine\Image\Metadata\AbstractMetadataReader::extractFromData()
 88 |      */
 89 |     protected function extractFromData($data)
 90 |     {
 91 |         return $this->doReadData($data);
 92 |     }
 93 | 
 94 |     /**
 95 |      * {@inheritdoc}
 96 |      *
 97 |      * @see \Imagine\Image\Metadata\AbstractMetadataReader::extractFromStream()
 98 |      */
 99 |     protected function extractFromStream($resource)
100 |     {
101 |         return PHP_VERSION_ID < 70200 ? $this->doReadData(stream_get_contents($resource)) : $this->extract($resource);
102 |     }
103 | 
104 |     /**
105 |      * Extracts metadata from raw data, merges with existing metadata.
106 |      *
107 |      * @param string $data
108 |      *
109 |      * @return array
110 |      */
111 |     private function doReadData($data)
112 |     {
113 |         if (PHP_VERSION_ID >= 70200) {
114 |             $stream = fopen('php://memory', 'r+');
115 |             fwrite($stream, $data);
116 |             rewind($stream);
117 | 
118 |             return $this->extract($stream);
119 |         }
120 | 
121 |         if (substr($data, 0, 2) === 'II') {
122 |             $mime = 'image/tiff';
123 |         } else {
124 |             $mime = 'image/jpeg';
125 |         }
126 | 
127 |         return $this->extract('data://' . $mime . ';base64,' . base64_encode($data));
128 |     }
129 | 
130 |     /**
131 |      * Performs the exif data extraction given a path, data-URI representation or stream.
132 |      *
133 |      * @param string|resource $path the path to the file, the data-URI representation or a stream
134 |      *
135 |      * @return array
136 |      */
137 |     private function extract($path)
138 |     {
139 |         try {
140 |             $exifData = ErrorHandling::ignoring(-1, function () use ($path) {
141 |                 return @exif_read_data($path, null, true, false);
142 |             });
143 |         } catch (\Exception $e) {
144 |             $exifData = false;
145 |         } catch (\Throwable $e) {
146 |             $exifData = false;
147 |         }
148 |         if (!is_array($exifData)) {
149 |             return array();
150 |         }
151 | 
152 |         $metadata = array();
153 |         foreach ($exifData as $prefix => $values) {
154 |             if (is_array($values)) {
155 |                 $prefix = strtolower($prefix);
156 |                 foreach ($values as $prop => $value) {
157 |                     $metadata[$prefix . '.' . $prop] = $value;
158 |                 }
159 |             }
160 |         }
161 | 
162 |         return $metadata;
163 |     }
164 | }
165 | 


--------------------------------------------------------------------------------
/src/Image/Metadata/MetadataBag.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Metadata;
 13 | 
 14 | /**
 15 |  * The container of the data extracted from metadata.
 16 |  */
 17 | class MetadataBag implements \ArrayAccess, \IteratorAggregate, \Countable
 18 | {
 19 |     /**
 20 |      * @var array
 21 |      */
 22 |     private $data;
 23 | 
 24 |     /**
 25 |      * @param array $data
 26 |      */
 27 |     public function __construct(array $data = array())
 28 |     {
 29 |         $this->data = $data;
 30 |     }
 31 | 
 32 |     /**
 33 |      * Returns the metadata key, default value if it does not exist.
 34 |      *
 35 |      * @param string $key
 36 |      * @param mixed|null $default
 37 |      *
 38 |      * @return mixed
 39 |      */
 40 |     public function get($key, $default = null)
 41 |     {
 42 |         return array_key_exists($key, $this->data) ? $this->data[$key] : $default;
 43 |     }
 44 | 
 45 |     /**
 46 |      * {@inheritdoc}
 47 |      *
 48 |      * @see \Countable::count()
 49 |      *
 50 |      * @return int
 51 |      */
 52 |     #[\ReturnTypeWillChange]
 53 |     public function count()
 54 |     {
 55 |         return count($this->data);
 56 |     }
 57 | 
 58 |     /**
 59 |      * {@inheritdoc}
 60 |      *
 61 |      * @see \IteratorAggregate::getIterator()
 62 |      *
 63 |      * @return \ArrayIterator
 64 |      */
 65 |     #[\ReturnTypeWillChange]
 66 |     public function getIterator()
 67 |     {
 68 |         return new \ArrayIterator($this->data);
 69 |     }
 70 | 
 71 |     /**
 72 |      * {@inheritdoc}
 73 |      *
 74 |      * @see \ArrayAccess::offsetExists()
 75 |      *
 76 |      * @return bool
 77 |      */
 78 |     #[\ReturnTypeWillChange]
 79 |     public function offsetExists($offset)
 80 |     {
 81 |         return array_key_exists($offset, $this->data);
 82 |     }
 83 | 
 84 |     /**
 85 |      * {@inheritdoc}
 86 |      *
 87 |      * @see \ArrayAccess::offsetSet()
 88 |      *
 89 |      * @return void
 90 |      */
 91 |     #[\ReturnTypeWillChange]
 92 |     public function offsetSet($offset, $value)
 93 |     {
 94 |         $this->data[$offset] = $value;
 95 |     }
 96 | 
 97 |     /**
 98 |      * {@inheritdoc}
 99 |      *
100 |      * @see \ArrayAccess::offsetUnset()
101 |      *
102 |      * @return void
103 |      */
104 |     #[\ReturnTypeWillChange]
105 |     public function offsetUnset($offset)
106 |     {
107 |         unset($this->data[$offset]);
108 |     }
109 | 
110 |     /**
111 |      * {@inheritdoc}
112 |      *
113 |      * @see \ArrayAccess::offsetGet()
114 |      *
115 |      * @return mixed
116 |      */
117 |     #[\ReturnTypeWillChange]
118 |     public function offsetGet($offset)
119 |     {
120 |         return $this->get($offset);
121 |     }
122 | 
123 |     /**
124 |      * Returns metadata as an associative array.
125 |      *
126 |      * @return array
127 |      */
128 |     public function toArray()
129 |     {
130 |         return $this->data;
131 |     }
132 | }
133 | 


--------------------------------------------------------------------------------
/src/Image/Metadata/MetadataReaderInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Metadata;
13 | 
14 | /**
15 |  * Interface that metadata readers must implement.
16 |  */
17 | interface MetadataReaderInterface
18 | {
19 |     /**
20 |      * Reads metadata from a file.
21 |      *
22 |      * @param string|\Imagine\File\LoaderInterface $file the path to the file where to read metadata
23 |      *
24 |      * @throws \Imagine\Exception\InvalidArgumentException in case the file does not exist
25 |      *
26 |      * @return \Imagine\Image\Metadata\MetadataBag
27 |      */
28 |     public function readFile($file);
29 | 
30 |     /**
31 |      * Reads metadata from a binary string.
32 |      *
33 |      * @param string $data the binary string to read
34 |      * @param resource|null $originalResource an optional resource to gather stream metadata
35 |      *
36 |      * @return \Imagine\Image\Metadata\MetadataBag
37 |      */
38 |     public function readData($data, $originalResource = null);
39 | 
40 |     /**
41 |      * Reads metadata from a stream.
42 |      *
43 |      * @param resource $resource the stream to read
44 |      *
45 |      * @throws \Imagine\Exception\InvalidArgumentException in case the resource is not valid
46 |      *
47 |      * @return \Imagine\Image\Metadata\MetadataBag
48 |      */
49 |     public function readStream($resource);
50 | }
51 | 


--------------------------------------------------------------------------------
/src/Image/Palette/CMYK.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | use Imagine\Exception\RuntimeException;
 16 | use Imagine\Image\Palette\Color\CMYK as CMYKColor;
 17 | use Imagine\Image\Palette\Color\ColorInterface;
 18 | use Imagine\Image\Profile;
 19 | use Imagine\Image\ProfileInterface;
 20 | 
 21 | /**
 22 |  * The CMYK palette.
 23 |  */
 24 | class CMYK implements PaletteInterface
 25 | {
 26 |     /**
 27 |      * @var \Imagine\Image\Palette\ColorParser
 28 |      */
 29 |     private $parser;
 30 | 
 31 |     /**
 32 |      * @var \Imagine\Image\ProfileInterface|null
 33 |      */
 34 |     private $profile;
 35 | 
 36 |     /**
 37 |      * @var \Imagine\Image\Palette\Color\CMYK[]
 38 |      */
 39 |     private static $colors = array();
 40 | 
 41 |     public function __construct()
 42 |     {
 43 |         $this->parser = new ColorParser();
 44 |     }
 45 | 
 46 |     /**
 47 |      * {@inheritdoc}
 48 |      *
 49 |      * @see \Imagine\Image\Palette\PaletteInterface::name()
 50 |      */
 51 |     public function name()
 52 |     {
 53 |         return PaletteInterface::PALETTE_CMYK;
 54 |     }
 55 | 
 56 |     /**
 57 |      * {@inheritdoc}
 58 |      *
 59 |      * @see \Imagine\Image\Palette\PaletteInterface::pixelDefinition()
 60 |      */
 61 |     public function pixelDefinition()
 62 |     {
 63 |         return array(
 64 |             ColorInterface::COLOR_CYAN,
 65 |             ColorInterface::COLOR_MAGENTA,
 66 |             ColorInterface::COLOR_YELLOW,
 67 |             ColorInterface::COLOR_KEYLINE,
 68 |         );
 69 |     }
 70 | 
 71 |     /**
 72 |      * {@inheritdoc}
 73 |      *
 74 |      * @see \Imagine\Image\Palette\PaletteInterface::supportsAlpha()
 75 |      */
 76 |     public function supportsAlpha()
 77 |     {
 78 |         return false;
 79 |     }
 80 | 
 81 |     /**
 82 |      * {@inheritdoc}
 83 |      *
 84 |      * @see \Imagine\Image\Palette\PaletteInterface::getChannelsMaxValue()
 85 |      */
 86 |     public function getChannelsMaxValue()
 87 |     {
 88 |         return 100;
 89 |     }
 90 | 
 91 |     /**
 92 |      * {@inheritdoc}
 93 |      *
 94 |      * @see \Imagine\Image\Palette\PaletteInterface::color()
 95 |      */
 96 |     public function color($color, $alpha = null)
 97 |     {
 98 |         if ($alpha !== null && $alpha !== 100) {
 99 |             throw new InvalidArgumentException('CMYK palette does not support alpha');
100 |         }
101 | 
102 |         $color = $this->parser->parseToCMYK($color);
103 |         $index = sprintf('cmyk(%d, %d, %d, %d)', $color[0], $color[1], $color[2], $color[3]);
104 | 
105 |         if (array_key_exists($index, self::$colors) === false) {
106 |             self::$colors[$index] = new CMYKColor($this, $color);
107 |         }
108 | 
109 |         return self::$colors[$index];
110 |     }
111 | 
112 |     /**
113 |      * {@inheritdoc}
114 |      *
115 |      * @see \Imagine\Image\Palette\PaletteInterface::blend()
116 |      */
117 |     public function blend(ColorInterface $color1, ColorInterface $color2, $amount)
118 |     {
119 |         if (!$color1 instanceof CMYKColor || !$color2 instanceof CMYKColor) {
120 |             throw new RuntimeException('CMYK palette can only blend CMYK colors');
121 |         }
122 |         $max = $this->getChannelsMaxValue();
123 | 
124 |         return $this->color(array(
125 |             min($max, $color1->getCyan() + $color2->getCyan() * $amount),
126 |             min($max, $color1->getMagenta() + $color2->getMagenta() * $amount),
127 |             min($max, $color1->getYellow() + $color2->getYellow() * $amount),
128 |             min($max, $color1->getKeyline() + $color2->getKeyline() * $amount),
129 |         ));
130 |     }
131 | 
132 |     /**
133 |      * {@inheritdoc}
134 |      *
135 |      * @see \Imagine\Image\Palette\PaletteInterface::useProfile()
136 |      */
137 |     public function useProfile(ProfileInterface $profile)
138 |     {
139 |         $this->profile = $profile;
140 | 
141 |         return $this;
142 |     }
143 | 
144 |     /**
145 |      * {@inheritdoc}
146 |      *
147 |      * @see \Imagine\Image\Palette\PaletteInterface::profile()
148 |      */
149 |     public function profile()
150 |     {
151 |         if (!$this->profile) {
152 |             $this->profile = Profile::fromPath(__DIR__ . '/../../resources/Adobe/CMYK/USWebUncoated.icc');
153 |         }
154 | 
155 |         return $this->profile;
156 |     }
157 | }
158 | 


--------------------------------------------------------------------------------
/src/Image/Palette/Color/ColorInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette\Color;
 13 | 
 14 | interface ColorInterface
 15 | {
 16 |     /**
 17 |      * Channel name: red.
 18 |      *
 19 |      * @var string
 20 |      */
 21 |     const COLOR_RED = 'red';
 22 | 
 23 |     /**
 24 |      * Channel name: green.
 25 |      *
 26 |      * @var string
 27 |      */
 28 |     const COLOR_GREEN = 'green';
 29 | 
 30 |     /**
 31 |      * Channel name: blue.
 32 |      *
 33 |      * @var string
 34 |      */
 35 |     const COLOR_BLUE = 'blue';
 36 | 
 37 |     /**
 38 |      * Channel name: cyan.
 39 |      *
 40 |      * @var string
 41 |      */
 42 |     const COLOR_CYAN = 'cyan';
 43 | 
 44 |     /**
 45 |      * Channel name: magenta.
 46 |      *
 47 |      * @var string
 48 |      */
 49 |     const COLOR_MAGENTA = 'magenta';
 50 | 
 51 |     /**
 52 |      * Channel name: yellow.
 53 |      *
 54 |      * @var string
 55 |      */
 56 |     const COLOR_YELLOW = 'yellow';
 57 | 
 58 |     /**
 59 |      * Channel name: key (black).
 60 |      *
 61 |      * @var string
 62 |      */
 63 |     const COLOR_KEYLINE = 'keyline';
 64 | 
 65 |     /**
 66 |      * Channel name: gray.
 67 |      *
 68 |      * @var string
 69 |      */
 70 |     const COLOR_GRAY = 'gray';
 71 | 
 72 |     /**
 73 |      * Return the value of one of the component.
 74 |      *
 75 |      * @param string $component One of the ColorInterface::COLOR_* component
 76 |      *
 77 |      * @throws \Imagine\Exception\InvalidArgumentException if $component is not valid
 78 |      *
 79 |      * @return int|null
 80 |      */
 81 |     public function getValue($component);
 82 | 
 83 |     /**
 84 |      * Returns percentage of transparency of the color (from 0 - fully transparent, to 100 - fully opaque).
 85 |      *
 86 |      * @return int|null return NULL if the color type does not support transparency
 87 |      */
 88 |     public function getAlpha();
 89 | 
 90 |     /**
 91 |      * Returns the palette attached to the current color.
 92 |      *
 93 |      * @return \Imagine\Image\Palette\PaletteInterface
 94 |      */
 95 |     public function getPalette();
 96 | 
 97 |     /**
 98 |      * Returns a copy of current color, incrementing the alpha channel by the given amount.
 99 |      *
100 |      * @param int $alpha
101 |      *
102 |      * @throws \Imagine\Exception\RuntimeException if the color type does not support transparency
103 |      *
104 |      * @return static
105 |      */
106 |     public function dissolve($alpha);
107 | 
108 |     /**
109 |      * Returns a copy of the current color, lightened by the specified number of shades.
110 |      *
111 |      * @param int $shade
112 |      *
113 |      * @return static
114 |      */
115 |     public function lighten($shade);
116 | 
117 |     /**
118 |      * Returns a copy of the current color, darkened by the specified number of shades.
119 |      *
120 |      * @param int $shade
121 |      *
122 |      * @return static
123 |      */
124 |     public function darken($shade);
125 | 
126 |     /**
127 |      * Returns a gray related to the current color.
128 |      *
129 |      * @return static
130 |      */
131 |     public function grayscale();
132 | 
133 |     /**
134 |      * Checks if the current color is opaque.
135 |      *
136 |      * @return bool
137 |      */
138 |     public function isOpaque();
139 | 
140 |     /**
141 |      * Returns hex representation of the color.
142 |      *
143 |      * @return string
144 |      */
145 |     public function __toString();
146 | }
147 | 


--------------------------------------------------------------------------------
/src/Image/Palette/Color/Gray.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette\Color;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | use Imagine\Image\Palette\Grayscale;
 16 | 
 17 | final class Gray implements ColorInterface
 18 | {
 19 |     /**
 20 |      * @var int
 21 |      */
 22 |     private $gray;
 23 | 
 24 |     /**
 25 |      * @var int
 26 |      */
 27 |     private $alpha;
 28 | 
 29 |     /**
 30 |      * @var \Imagine\Image\Palette\Grayscale
 31 |      */
 32 |     private $palette;
 33 | 
 34 |     /**
 35 |      * @param \Imagine\Image\Palette\Grayscale $palette
 36 |      * @param int[] $color
 37 |      * @param int $alpha
 38 |      */
 39 |     public function __construct(Grayscale $palette, array $color, $alpha)
 40 |     {
 41 |         $this->palette = $palette;
 42 |         $this->setColor($color);
 43 |         $this->setAlpha($alpha);
 44 |     }
 45 | 
 46 |     /**
 47 |      * {@inheritdoc}
 48 |      *
 49 |      * @see \Imagine\Image\Palette\Color\ColorInterface::getValue()
 50 |      */
 51 |     public function getValue($component)
 52 |     {
 53 |         switch ($component) {
 54 |             case ColorInterface::COLOR_GRAY:
 55 |                 return $this->getGray();
 56 |             default:
 57 |                 throw new InvalidArgumentException(sprintf('Color component %s is not valid', $component));
 58 |         }
 59 |     }
 60 | 
 61 |     /**
 62 |      * Returns Gray value of the color (from 0 to 255).
 63 |      *
 64 |      * @return int
 65 |      */
 66 |     public function getGray()
 67 |     {
 68 |         return $this->gray;
 69 |     }
 70 | 
 71 |     /**
 72 |      * {@inheritdoc}
 73 |      *
 74 |      * @see \Imagine\Image\Palette\Color\ColorInterface::getPalette()
 75 |      */
 76 |     public function getPalette()
 77 |     {
 78 |         return $this->palette;
 79 |     }
 80 | 
 81 |     /**
 82 |      * {@inheritdoc}
 83 |      *
 84 |      * @see \Imagine\Image\Palette\Color\ColorInterface::getAlpha()
 85 |      */
 86 |     public function getAlpha()
 87 |     {
 88 |         return $this->alpha;
 89 |     }
 90 | 
 91 |     /**
 92 |      * {@inheritdoc}
 93 |      *
 94 |      * @see \Imagine\Image\Palette\Color\ColorInterface::dissolve()
 95 |      */
 96 |     public function dissolve($alpha)
 97 |     {
 98 |         return $this->palette->color(
 99 |             array($this->gray),
100 |             min(max((int) round($this->alpha + $alpha), 0), 100)
101 |         );
102 |     }
103 | 
104 |     /**
105 |      * {@inheritdoc}
106 |      *
107 |      * @see \Imagine\Image\Palette\Color\ColorInterface::lighten()
108 |      */
109 |     public function lighten($shade)
110 |     {
111 |         return $this->palette->color(array(min(255, $this->gray + $shade)), $this->alpha);
112 |     }
113 | 
114 |     /**
115 |      * {@inheritdoc}
116 |      *
117 |      * @see \Imagine\Image\Palette\Color\ColorInterface::darken()
118 |      */
119 |     public function darken($shade)
120 |     {
121 |         return $this->palette->color(array(max(0, $this->gray - $shade)), $this->alpha);
122 |     }
123 | 
124 |     /**
125 |      * {@inheritdoc}
126 |      *
127 |      * @see \Imagine\Image\Palette\Color\ColorInterface::grayscale()
128 |      */
129 |     public function grayscale()
130 |     {
131 |         return $this;
132 |     }
133 | 
134 |     /**
135 |      * {@inheritdoc}
136 |      *
137 |      * @see \Imagine\Image\Palette\Color\ColorInterface::isOpaque()
138 |      */
139 |     public function isOpaque()
140 |     {
141 |         return $this->alpha === 100;
142 |     }
143 | 
144 |     /**
145 |      * {@inheritdoc}
146 |      *
147 |      * @see \Imagine\Image\Palette\Color\ColorInterface::__toString()
148 |      */
149 |     public function __toString()
150 |     {
151 |         return sprintf('#%02x%02x%02x', $this->gray, $this->gray, $this->gray);
152 |     }
153 | 
154 |     /**
155 |      * Performs checks for validity of given alpha value and sets it.
156 |      *
157 |      * @param int $alpha
158 |      *
159 |      * @throws \Imagine\Exception\InvalidArgumentException
160 |      */
161 |     private function setAlpha($alpha)
162 |     {
163 |         if (!is_int($alpha) || $alpha < 0 || $alpha > 100) {
164 |             throw new InvalidArgumentException(sprintf('Alpha must be an integer between 0 and 100, %s given', $alpha));
165 |         }
166 | 
167 |         $this->alpha = $alpha;
168 |     }
169 | 
170 |     /**
171 |      * Performs checks for color validity (array of array(gray)).
172 |      *
173 |      * @param int[] $color
174 |      *
175 |      * @throws \Imagine\Exception\InvalidArgumentException
176 |      */
177 |     private function setColor(array $color)
178 |     {
179 |         if (count($color) !== 1) {
180 |             throw new InvalidArgumentException('Color argument must look like array(gray), where gray is the integer value between 0 and 255 for the grayscale');
181 |         }
182 | 
183 |         $color = array_values($color);
184 |         $color[0] = max(0, min(255, $color[0]));
185 | 
186 |         list($this->gray) = $color;
187 |     }
188 | }
189 | 


--------------------------------------------------------------------------------
/src/Image/Palette/ColorParser.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | 
 16 | class ColorParser
 17 | {
 18 |     /**
 19 |      * Parses a color to a RGB tuple.
 20 |      *
 21 |      * @param string|array|int $color
 22 |      *
 23 |      * @throws \Imagine\Exception\InvalidArgumentException
 24 |      *
 25 |      * @return array
 26 |      */
 27 |     public function parseToRGB($color)
 28 |     {
 29 |         $color = $this->parse($color);
 30 | 
 31 |         if (count($color) === 4) {
 32 |             $color = array(
 33 |                 255 * (1 - $color[0] / 100) * (1 - $color[3] / 100),
 34 |                 255 * (1 - $color[1] / 100) * (1 - $color[3] / 100),
 35 |                 255 * (1 - $color[2] / 100) * (1 - $color[3] / 100),
 36 |             );
 37 |         }
 38 | 
 39 |         return $color;
 40 |     }
 41 | 
 42 |     /**
 43 |      * Parses a color to a CMYK tuple.
 44 |      *
 45 |      * @param string|array|int $color
 46 |      *
 47 |      * @throws \Imagine\Exception\InvalidArgumentException
 48 |      *
 49 |      * @return array
 50 |      */
 51 |     public function parseToCMYK($color)
 52 |     {
 53 |         $color = $this->parse($color);
 54 | 
 55 |         if (count($color) === 3) {
 56 |             $r = $color[0] / 255;
 57 |             $g = $color[1] / 255;
 58 |             $b = $color[2] / 255;
 59 | 
 60 |             $k = 1 - max($r, $g, $b);
 61 | 
 62 |             $color = array(
 63 |                 $k === 1 ? 0 : round((1 - $r - $k) / (1 - $k) * 100),
 64 |                 $k === 1 ? 0 : round((1 - $g - $k) / (1 - $k) * 100),
 65 |                 $k === 1 ? 0 : round((1 - $b - $k) / (1 - $k) * 100),
 66 |                 round($k * 100),
 67 |             );
 68 |         }
 69 | 
 70 |         return $color;
 71 |     }
 72 | 
 73 |     /**
 74 |      * Parses a color to a grayscale value.
 75 |      *
 76 |      * @param string|array|int $color
 77 |      *
 78 |      * @throws \Imagine\Exception\InvalidArgumentException
 79 |      *
 80 |      * @return int[]
 81 |      */
 82 |     public function parseToGrayscale($color)
 83 |     {
 84 |         if (is_array($color) && count($color) === 1) {
 85 |             return array((int) round(array_pop($color)));
 86 |         }
 87 | 
 88 |         $color = array_unique($this->parse($color));
 89 | 
 90 |         if (count($color) !== 1) {
 91 |             throw new InvalidArgumentException('The provided color has different values of red, green and blue components. Grayscale colors must have the same values for these.');
 92 |         }
 93 | 
 94 |         return $color;
 95 |     }
 96 | 
 97 |     /**
 98 |      * Parses a color.
 99 |      *
100 |      * @param string|array|int $color
101 |      *
102 |      * @throws \Imagine\Exception\InvalidArgumentException
103 |      *
104 |      * @return int[]
105 |      */
106 |     private function parse($color)
107 |     {
108 |         if (!is_string($color) && !is_array($color) && !is_int($color)) {
109 |             throw new InvalidArgumentException(sprintf('Color must be specified as a hexadecimal string, array or integer, %s given', gettype($color)));
110 |         }
111 | 
112 |         if (is_array($color)) {
113 |             if (count($color) === 3 || count($color) === 4) {
114 |                 return array_map(
115 |                     function ($component) {
116 |                         return (int) round($component);
117 |                     },
118 |                     array_values($color)
119 |                 );
120 |             }
121 |             throw new InvalidArgumentException('Color argument if array, must look like array(R, G, B), or array(C, M, Y, K) where R, G, B are the integer values between 0 and 255 for red, green and blue or cyan, magenta, yellow and black color indexes accordingly');
122 |         }
123 |         if (is_string($color)) {
124 |             if (strpos($color, 'cmyk(') === 0) {
125 |                 $substrColor = substr($color, 5, strlen($color) - 6);
126 | 
127 |                 $components = array_map(function ($component) {
128 |                     return (int) round(trim($component, ' %'));
129 |                 }, explode(',', $substrColor));
130 | 
131 |                 if (count($components) !== 4) {
132 |                     throw new InvalidArgumentException(sprintf('Unable to parse color %s', $color));
133 |                 }
134 | 
135 |                 return $components;
136 |             } else {
137 |                 $color = ltrim($color, '#');
138 | 
139 |                 if (strlen($color) !== 3 && strlen($color) !== 6) {
140 |                     throw new InvalidArgumentException(sprintf('Color must be a hex value in regular (6 characters) or short (3 characters) notation, "%s" given', $color));
141 |                 }
142 | 
143 |                 if (strlen($color) === 3) {
144 |                     $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
145 |                 }
146 | 
147 |                 $color = array_map('hexdec', str_split($color, 2));
148 |             }
149 |         }
150 | 
151 |         if (is_int($color)) {
152 |             $color = array(255 & ($color >> 16), 255 & ($color >> 8), 255 & $color);
153 |         }
154 | 
155 |         return $color;
156 |     }
157 | }
158 | 


--------------------------------------------------------------------------------
/src/Image/Palette/Grayscale.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette;
 13 | 
 14 | use Imagine\Exception\RuntimeException;
 15 | use Imagine\Image\Palette\Color\ColorInterface;
 16 | use Imagine\Image\Palette\Color\Gray as GrayColor;
 17 | use Imagine\Image\Profile;
 18 | use Imagine\Image\ProfileInterface;
 19 | 
 20 | /**
 21 |  * The grayscale palette.
 22 |  */
 23 | class Grayscale implements PaletteInterface
 24 | {
 25 |     /**
 26 |      * @var \Imagine\Image\Palette\ColorParser
 27 |      */
 28 |     private $parser;
 29 | 
 30 |     /**
 31 |      * @var \Imagine\Image\ProfileInterface|null
 32 |      */
 33 |     private $profile;
 34 | 
 35 |     /**
 36 |      * @var \Imagine\Image\Palette\Color\Gray[]
 37 |      */
 38 |     protected static $colors = array();
 39 | 
 40 |     public function __construct()
 41 |     {
 42 |         $this->parser = new ColorParser();
 43 |     }
 44 | 
 45 |     /**
 46 |      * {@inheritdoc}
 47 |      *
 48 |      * @see \Imagine\Image\Palette\PaletteInterface::name()
 49 |      */
 50 |     public function name()
 51 |     {
 52 |         return PaletteInterface::PALETTE_GRAYSCALE;
 53 |     }
 54 | 
 55 |     /**
 56 |      * {@inheritdoc}
 57 |      *
 58 |      * @see \Imagine\Image\Palette\PaletteInterface::pixelDefinition()
 59 |      */
 60 |     public function pixelDefinition()
 61 |     {
 62 |         return array(ColorInterface::COLOR_GRAY);
 63 |     }
 64 | 
 65 |     /**
 66 |      * {@inheritdoc}
 67 |      *
 68 |      * @see \Imagine\Image\Palette\PaletteInterface::supportsAlpha()
 69 |      */
 70 |     public function supportsAlpha()
 71 |     {
 72 |         return true;
 73 |     }
 74 | 
 75 |     /**
 76 |      * {@inheritdoc}
 77 |      *
 78 |      * @see \Imagine\Image\Palette\PaletteInterface::getChannelsMaxValue()
 79 |      */
 80 |     public function getChannelsMaxValue()
 81 |     {
 82 |         return 255;
 83 |     }
 84 | 
 85 |     /**
 86 |      * {@inheritdoc}
 87 |      *
 88 |      * @see \Imagine\Image\Palette\PaletteInterface::useProfile()
 89 |      */
 90 |     public function useProfile(ProfileInterface $profile)
 91 |     {
 92 |         $this->profile = $profile;
 93 | 
 94 |         return $this;
 95 |     }
 96 | 
 97 |     /**
 98 |      * {@inheritdoc}
 99 |      *
100 |      * @see \Imagine\Image\Palette\PaletteInterface::profile()
101 |      */
102 |     public function profile()
103 |     {
104 |         if (!$this->profile) {
105 |             $this->profile = Profile::fromPath(__DIR__ . '/../../resources/colormanagement.org/ISOcoated_v2_grey1c_bas.ICC');
106 |         }
107 | 
108 |         return $this->profile;
109 |     }
110 | 
111 |     /**
112 |      * {@inheritdoc}
113 |      *
114 |      * @see \Imagine\Image\Palette\PaletteInterface::color()
115 |      */
116 |     public function color($color, $alpha = null)
117 |     {
118 |         if ($alpha === null) {
119 |             $alpha = 0;
120 |         }
121 | 
122 |         $color = $this->parser->parseToGrayscale($color);
123 |         $index = sprintf('#%02x%02x%02x-%d', $color[0], $color[0], $color[0], $alpha);
124 | 
125 |         if (array_key_exists($index, static::$colors) === false) {
126 |             static::$colors[$index] = new GrayColor($this, $color, $alpha);
127 |         }
128 | 
129 |         return static::$colors[$index];
130 |     }
131 | 
132 |     /**
133 |      * {@inheritdoc}
134 |      *
135 |      * @see \Imagine\Image\Palette\PaletteInterface::blend()
136 |      */
137 |     public function blend(ColorInterface $color1, ColorInterface $color2, $amount)
138 |     {
139 |         if (!$color1 instanceof GrayColor || !$color2 instanceof GrayColor) {
140 |             throw new RuntimeException('Grayscale palette can only blend Grayscale colors');
141 |         }
142 |         $max = $this->getChannelsMaxValue();
143 | 
144 |         return $this->color(
145 |             array(
146 |                 (int) min($max, min($color1->getGray(), $color2->getGray()) + round(abs($color2->getGray() - $color1->getGray()) * $amount)),
147 |             ),
148 |             (int) min(100, min($color1->getAlpha(), $color2->getAlpha()) + round(abs($color2->getAlpha() - $color1->getAlpha()) * $amount))
149 |         );
150 |     }
151 | }
152 | 


--------------------------------------------------------------------------------
/src/Image/Palette/PaletteInterface.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette;
 13 | 
 14 | use Imagine\Image\Palette\Color\ColorInterface;
 15 | use Imagine\Image\ProfileInterface;
 16 | 
 17 | /**
 18 |  * Interface that any palette must implement.
 19 |  */
 20 | interface PaletteInterface
 21 | {
 22 |     /**
 23 |      * Palette name: grayscale.
 24 |      *
 25 |      * @var string
 26 |      */
 27 |     const PALETTE_GRAYSCALE = 'gray';
 28 | 
 29 |     /**
 30 |      * Palette name: RGB.
 31 |      *
 32 |      * @var string
 33 |      */
 34 |     const PALETTE_RGB = 'rgb';
 35 | 
 36 |     /**
 37 |      * Palette name: CMYK.
 38 |      *
 39 |      * @var string
 40 |      */
 41 |     const PALETTE_CMYK = 'cmyk';
 42 | 
 43 |     /**
 44 |      * Returns a color given some values.
 45 |      *
 46 |      * @param string|int[]|int $color A color
 47 |      * @param int|null $alpha Set alpha to null to disable it
 48 |      *
 49 |      * @throws \Imagine\Exception\InvalidArgumentException In case you pass an alpha value to a Palette that does not support alpha
 50 |      *
 51 |      * @return \Imagine\Image\Palette\Color\ColorInterface
 52 |      */
 53 |     public function color($color, $alpha = null);
 54 | 
 55 |     /**
 56 |      * Blend two colors given an amount.
 57 |      *
 58 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color1
 59 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color2
 60 |      * @param float $amount The amount of color2 in color1
 61 |      *
 62 |      * @return \Imagine\Image\Palette\Color\ColorInterface
 63 |      */
 64 |     public function blend(ColorInterface $color1, ColorInterface $color2, $amount);
 65 | 
 66 |     /**
 67 |      * Attachs an ICC profile to this Palette.
 68 |      *
 69 |      * (A default profile is provided by default)
 70 |      *
 71 |      * @param \Imagine\Image\ProfileInterface $profile
 72 |      *
 73 |      * @return $this
 74 |      */
 75 |     public function useProfile(ProfileInterface $profile);
 76 | 
 77 |     /**
 78 |      * Returns the ICC profile attached to this Palette.
 79 |      *
 80 |      * @return \Imagine\Image\ProfileInterface
 81 |      */
 82 |     public function profile();
 83 | 
 84 |     /**
 85 |      * Returns the name of this Palette, one of PaletteInterface::PALETTE_ constants.
 86 |      *
 87 |      * @return string
 88 |      */
 89 |     public function name();
 90 | 
 91 |     /**
 92 |      * Returns an array containing ColorInterface::COLOR_* constants that
 93 |      * define the structure of colors for a pixel.
 94 |      *
 95 |      * @return string[]
 96 |      */
 97 |     public function pixelDefinition();
 98 | 
 99 |     /**
100 |      * Tells if alpha channel is supported in this palette.
101 |      *
102 |      * @return bool
103 |      */
104 |     public function supportsAlpha();
105 | 
106 |     /**
107 |      * Get the max value of palette components (255 for RGB and Grayscale, 100 for CMYK).
108 |      *
109 |      * @return int
110 |      */
111 |     public function getChannelsMaxValue();
112 | }
113 | 


--------------------------------------------------------------------------------
/src/Image/Palette/RGB.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image\Palette;
 13 | 
 14 | use Imagine\Exception\RuntimeException;
 15 | use Imagine\Image\Palette\Color\ColorInterface;
 16 | use Imagine\Image\Palette\Color\RGB as RGBColor;
 17 | use Imagine\Image\Profile;
 18 | use Imagine\Image\ProfileInterface;
 19 | 
 20 | /**
 21 |  * The RGB palette.
 22 |  */
 23 | class RGB implements PaletteInterface
 24 | {
 25 |     /**
 26 |      * @var \Imagine\Image\Palette\ColorParser
 27 |      */
 28 |     private $parser;
 29 | 
 30 |     /**
 31 |      * @var \Imagine\Image\ProfileInterface|null
 32 |      */
 33 |     private $profile;
 34 | 
 35 |     /**
 36 |      * @var \Imagine\Image\Palette\Color\RGB[]
 37 |      */
 38 |     protected static $colors = array();
 39 | 
 40 |     public function __construct()
 41 |     {
 42 |         $this->parser = new ColorParser();
 43 |     }
 44 | 
 45 |     /**
 46 |      * {@inheritdoc}
 47 |      *
 48 |      * @see \Imagine\Image\Palette\PaletteInterface::name()
 49 |      */
 50 |     public function name()
 51 |     {
 52 |         return PaletteInterface::PALETTE_RGB;
 53 |     }
 54 | 
 55 |     /**
 56 |      * {@inheritdoc}
 57 |      *
 58 |      * @see \Imagine\Image\Palette\PaletteInterface::pixelDefinition()
 59 |      */
 60 |     public function pixelDefinition()
 61 |     {
 62 |         return array(
 63 |             ColorInterface::COLOR_RED,
 64 |             ColorInterface::COLOR_GREEN,
 65 |             ColorInterface::COLOR_BLUE,
 66 |         );
 67 |     }
 68 | 
 69 |     /**
 70 |      * {@inheritdoc}
 71 |      *
 72 |      * @see \Imagine\Image\Palette\PaletteInterface::supportsAlpha()
 73 |      */
 74 |     public function supportsAlpha()
 75 |     {
 76 |         return true;
 77 |     }
 78 | 
 79 |     /**
 80 |      * {@inheritdoc}
 81 |      *
 82 |      * @see \Imagine\Image\Palette\PaletteInterface::getChannelsMaxValue()
 83 |      */
 84 |     public function getChannelsMaxValue()
 85 |     {
 86 |         return 255;
 87 |     }
 88 | 
 89 |     /**
 90 |      * {@inheritdoc}
 91 |      *
 92 |      * @see \Imagine\Image\Palette\PaletteInterface::useProfile()
 93 |      */
 94 |     public function useProfile(ProfileInterface $profile)
 95 |     {
 96 |         $this->profile = $profile;
 97 | 
 98 |         return $this;
 99 |     }
100 | 
101 |     /**
102 |      * {@inheritdoc}
103 |      *
104 |      * @see \Imagine\Image\Palette\PaletteInterface::profile()
105 |      */
106 |     public function profile()
107 |     {
108 |         if (!$this->profile) {
109 |             $this->profile = Profile::fromPath(__DIR__ . '/../../resources/color.org/sRGB_IEC61966-2-1_black_scaled.icc');
110 |         }
111 | 
112 |         return $this->profile;
113 |     }
114 | 
115 |     /**
116 |      * {@inheritdoc}
117 |      *
118 |      * @see \Imagine\Image\Palette\PaletteInterface::color()
119 |      */
120 |     public function color($color, $alpha = null)
121 |     {
122 |         if ($alpha === null) {
123 |             $alpha = 100;
124 |         }
125 | 
126 |         $color = $this->parser->parseToRGB($color);
127 |         $index = sprintf('#%02x%02x%02x-%d', $color[0], $color[1], $color[2], $alpha);
128 | 
129 |         if (array_key_exists($index, static::$colors) === false) {
130 |             static::$colors[$index] = new RGBColor($this, $color, $alpha);
131 |         }
132 | 
133 |         return static::$colors[$index];
134 |     }
135 | 
136 |     /**
137 |      * {@inheritdoc}
138 |      *
139 |      * @see \Imagine\Image\Palette\PaletteInterface::blend()
140 |      */
141 |     public function blend(ColorInterface $color1, ColorInterface $color2, $amount)
142 |     {
143 |         if (!$color1 instanceof RGBColor || !$color2 instanceof RGBColor) {
144 |             throw new RuntimeException('RGB palette can only blend RGB colors');
145 |         }
146 |         $amount = (float) $amount;
147 |         $amountComplement = 1 - $amount;
148 |         $max = $this->getChannelsMaxValue();
149 | 
150 |         return $this->color(
151 |             array(
152 |                 min(max((int) round($color2->getRed() * $amount + $color1->getRed() * $amountComplement), 0), $max),
153 |                 min(max((int) round($color2->getGreen() * $amount + $color1->getGreen() * $amountComplement), 0), $max),
154 |                 min(max((int) round($color2->getBlue() * $amount + $color1->getBlue() * $amountComplement), 0), $max),
155 |             ),
156 |             min(max((int) round($color2->getAlpha() * $amount + $color1->getAlpha() * $amountComplement), 0), 100)
157 |         );
158 |     }
159 | }
160 | 


--------------------------------------------------------------------------------
/src/Image/Point.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Image;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | 
 16 | /**
 17 |  * The point class.
 18 |  */
 19 | final class Point implements PointInterface
 20 | {
 21 |     /**
 22 |      * @var int
 23 |      */
 24 |     private $x;
 25 | 
 26 |     /**
 27 |      * @var int
 28 |      */
 29 |     private $y;
 30 | 
 31 |     /**
 32 |      * Constructs a point of coordinates.
 33 |      *
 34 |      * @param int $x
 35 |      * @param int $y
 36 |      *
 37 |      * @throws \Imagine\Exception\InvalidArgumentException
 38 |      */
 39 |     public function __construct($x, $y)
 40 |     {
 41 |         if (!is_numeric($x) || !is_numeric($y)) {
 42 |             throw new InvalidArgumentException('x or y must be numeric');
 43 |         }
 44 | 
 45 |         $x = (int) round((float) $x);
 46 |         $y = (int) round((float) $y);
 47 | 
 48 |         if ($x < 0 || $y < 0) {
 49 |             throw new InvalidArgumentException(sprintf('A coordinate cannot be positioned outside of a bounding box (x: %s, y: %s given)', $x, $y));
 50 |         }
 51 | 
 52 |         $this->x = $x;
 53 |         $this->y = $y;
 54 |     }
 55 | 
 56 |     /**
 57 |      * {@inheritdoc}
 58 |      *
 59 |      * @see \Imagine\Image\PointInterface::getX()
 60 |      */
 61 |     public function getX()
 62 |     {
 63 |         return $this->x;
 64 |     }
 65 | 
 66 |     /**
 67 |      * {@inheritdoc}
 68 |      *
 69 |      * @see \Imagine\Image\PointInterface::getY()
 70 |      */
 71 |     public function getY()
 72 |     {
 73 |         return $this->y;
 74 |     }
 75 | 
 76 |     /**
 77 |      * {@inheritdoc}
 78 |      *
 79 |      * @see \Imagine\Image\PointInterface::in()
 80 |      */
 81 |     public function in(BoxInterface $box)
 82 |     {
 83 |         return $this->x < $box->getWidth() && $this->y < $box->getHeight();
 84 |     }
 85 | 
 86 |     /**
 87 |      * {@inheritdoc}
 88 |      *
 89 |      * @see \Imagine\Image\PointInterface::move()
 90 |      */
 91 |     public function move($amount)
 92 |     {
 93 |         return new self($this->x + $amount, $this->y + $amount);
 94 |     }
 95 | 
 96 |     /**
 97 |      * {@inheritdoc}
 98 |      *
 99 |      * @see \Imagine\Image\PointInterface::__toString()
100 |      */
101 |     public function __toString()
102 |     {
103 |         return sprintf('(%d, %d)', $this->x, $this->y);
104 |     }
105 | }
106 | 


--------------------------------------------------------------------------------
/src/Image/Point/Center.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image\Point;
13 | 
14 | use Imagine\Image\BoxInterface;
15 | use Imagine\Image\Point as OriginalPoint;
16 | use Imagine\Image\PointInterface;
17 | 
18 | /**
19 |  * Center point of a box.
20 |  */
21 | final class Center implements PointInterface
22 | {
23 |     /**
24 |      * @var \Imagine\Image\BoxInterface
25 |      */
26 |     private $box;
27 | 
28 |     /**
29 |      * Constructs coordinate with size instance, it needs to be relative to.
30 |      *
31 |      * @param \Imagine\Image\BoxInterface $box
32 |      */
33 |     public function __construct(BoxInterface $box)
34 |     {
35 |         $this->box = $box;
36 |     }
37 | 
38 |     /**
39 |      * {@inheritdoc}
40 |      *
41 |      * @see \Imagine\Image\PointInterface::getX()
42 |      */
43 |     public function getX()
44 |     {
45 |         return ceil($this->box->getWidth() / 2);
46 |     }
47 | 
48 |     /**
49 |      * {@inheritdoc}
50 |      *
51 |      * @see \Imagine\Image\PointInterface::getY()
52 |      */
53 |     public function getY()
54 |     {
55 |         return ceil($this->box->getHeight() / 2);
56 |     }
57 | 
58 |     /**
59 |      * {@inheritdoc}
60 |      *
61 |      * @see \Imagine\Image\PointInterface::in()
62 |      */
63 |     public function in(BoxInterface $box)
64 |     {
65 |         return $this->getX() < $box->getWidth() && $this->getY() < $box->getHeight();
66 |     }
67 | 
68 |     /**
69 |      * {@inheritdoc}
70 |      *
71 |      * @see \Imagine\Image\PointInterface::move()
72 |      */
73 |     public function move($amount)
74 |     {
75 |         return new OriginalPoint($this->getX() + $amount, $this->getY() + $amount);
76 |     }
77 | 
78 |     /**
79 |      * {@inheritdoc}
80 |      *
81 |      * @see \Imagine\Image\PointInterface::__toString()
82 |      */
83 |     public function __toString()
84 |     {
85 |         return sprintf('(%d, %d)', $this->getX(), $this->getY());
86 |     }
87 | }
88 | 


--------------------------------------------------------------------------------
/src/Image/PointInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image;
13 | 
14 | /**
15 |  * The point interface.
16 |  */
17 | interface PointInterface
18 | {
19 |     /**
20 |      * Gets points x coordinate.
21 |      *
22 |      * @return int
23 |      */
24 |     public function getX();
25 | 
26 |     /**
27 |      * Gets points y coordinate.
28 |      *
29 |      * @return int
30 |      */
31 |     public function getY();
32 | 
33 |     /**
34 |      * Checks if current coordinate is inside a given box.
35 |      *
36 |      * @param \Imagine\Image\BoxInterface $box
37 |      *
38 |      * @return bool
39 |      */
40 |     public function in(BoxInterface $box);
41 | 
42 |     /**
43 |      * Returns another point, moved by a given amount from current coordinates.
44 |      *
45 |      * @param int $amount
46 |      *
47 |      * @return \Imagine\Image\PointInterface
48 |      */
49 |     public function move($amount);
50 | 
51 |     /**
52 |      * Gets a string representation for the current point.
53 |      *
54 |      * @return string
55 |      */
56 |     public function __toString();
57 | }
58 | 


--------------------------------------------------------------------------------
/src/Image/PointSigned.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image;
13 | 
14 | /**
15 |  * A point class that allows negative values of coordinates.
16 |  */
17 | final class PointSigned implements PointInterface
18 | {
19 |     /**
20 |      * @var int
21 |      */
22 |     private $x;
23 | 
24 |     /**
25 |      * @var int
26 |      */
27 |     private $y;
28 | 
29 |     /**
30 |      * Constructs a point of coordinates.
31 |      *
32 |      * @param int $x
33 |      * @param int $y
34 |      *
35 |      * @throws \Imagine\Exception\InvalidArgumentException
36 |      */
37 |     public function __construct($x, $y)
38 |     {
39 |         $this->x = $x;
40 |         $this->y = $y;
41 |     }
42 | 
43 |     /**
44 |      * {@inheritdoc}
45 |      *
46 |      * @see \Imagine\Image\PointInterface::getX()
47 |      */
48 |     public function getX()
49 |     {
50 |         return $this->x;
51 |     }
52 | 
53 |     /**
54 |      * {@inheritdoc}
55 |      *
56 |      * @see \Imagine\Image\PointInterface::getY()
57 |      */
58 |     public function getY()
59 |     {
60 |         return $this->y;
61 |     }
62 | 
63 |     /**
64 |      * {@inheritdoc}
65 |      *
66 |      * @see \Imagine\Image\PointInterface::in()
67 |      */
68 |     public function in(BoxInterface $box)
69 |     {
70 |         return $this->x >= 0 && $this->x < $box->getWidth() && $this->y >= 0 && $this->y < $box->getHeight();
71 |     }
72 | 
73 |     /**
74 |      * {@inheritdoc}
75 |      *
76 |      * @see \Imagine\Image\PointInterface::move()
77 |      */
78 |     public function move($amount)
79 |     {
80 |         return new self($this->x + $amount, $this->y + $amount);
81 |     }
82 | 
83 |     /**
84 |      * {@inheritdoc}
85 |      *
86 |      * @see \Imagine\Image\PointInterface::__toString()
87 |      */
88 |     public function __toString()
89 |     {
90 |         return sprintf('(%d, %d)', $this->x, $this->y);
91 |     }
92 | }
93 | 


--------------------------------------------------------------------------------
/src/Image/Profile.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image;
13 | 
14 | use Imagine\Exception\InvalidArgumentException;
15 | 
16 | /**
17 |  * The default implementation of ProfileInterface.
18 |  */
19 | class Profile implements ProfileInterface
20 | {
21 |     /**
22 |      * @var string
23 |      */
24 |     private $data;
25 | 
26 |     /**
27 |      * @var string
28 |      */
29 |     private $name;
30 | 
31 |     /**
32 |      * @param string $name
33 |      * @param string $data
34 |      */
35 |     public function __construct($name, $data)
36 |     {
37 |         $this->name = $name;
38 |         $this->data = $data;
39 |     }
40 | 
41 |     /**
42 |      * {@inheritdoc}
43 |      *
44 |      * @see \Imagine\Image\ProfileInterface::name()
45 |      */
46 |     public function name()
47 |     {
48 |         return $this->name;
49 |     }
50 | 
51 |     /**
52 |      * {@inheritdoc}
53 |      *
54 |      * @see \Imagine\Image\ProfileInterface::data()
55 |      */
56 |     public function data()
57 |     {
58 |         return $this->data;
59 |     }
60 | 
61 |     /**
62 |      * Creates a profile from a path to a file.
63 |      *
64 |      * @param string $path
65 |      *
66 |      * @throws \Imagine\Exception\InvalidArgumentException In case the provided path is not valid
67 |      *
68 |      * @return static
69 |      */
70 |     public static function fromPath($path)
71 |     {
72 |         if (!file_exists($path) || !is_file($path) || !is_readable($path)) {
73 |             throw new InvalidArgumentException(sprintf('Path %s is an invalid profile file or is not readable', $path));
74 |         }
75 | 
76 |         return new static(basename($path), file_get_contents($path));
77 |     }
78 | }
79 | 


--------------------------------------------------------------------------------
/src/Image/ProfileInterface.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Image;
13 | 
14 | interface ProfileInterface
15 | {
16 |     /**
17 |      * Returns the name of the profile.
18 |      *
19 |      * @return string
20 |      */
21 |     public function name();
22 | 
23 |     /**
24 |      * Returns the profile data.
25 |      *
26 |      * @return string
27 |      */
28 |     public function data();
29 | }
30 | 


--------------------------------------------------------------------------------
/src/Imagick/Font.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Imagick;
13 | 
14 | use Imagine\Driver\InfoProvider;
15 | use Imagine\Image\AbstractFont;
16 | use Imagine\Image\Palette\Color\ColorInterface;
17 | 
18 | /**
19 |  * Font implementation using the Imagick PHP extension.
20 |  */
21 | final class Font extends AbstractFont implements InfoProvider
22 | {
23 |     /**
24 |      * @var \Imagick
25 |      */
26 |     private $imagick;
27 | 
28 |     /**
29 |      * @param \Imagick $imagick
30 |      * @param string $file
31 |      * @param int $size
32 |      * @param \Imagine\Image\Palette\Color\ColorInterface $color
33 |      */
34 |     public function __construct(\Imagick $imagick, $file, $size, ColorInterface $color)
35 |     {
36 |         $this->imagick = $imagick;
37 | 
38 |         parent::__construct($file, $size, $color);
39 |     }
40 | 
41 |     /**
42 |      * {@inheritdoc}
43 |      *
44 |      * @see \Imagine\Driver\InfoProvider::getDriverInfo()
45 |      * @since 1.3.0
46 |      */
47 |     public static function getDriverInfo($required = true)
48 |     {
49 |         return DriverInfo::get($required);
50 |     }
51 | 
52 |     /**
53 |      * {@inheritdoc}
54 |      *
55 |      * @see \Imagine\Image\FontInterface::box()
56 |      */
57 |     public function box($string, $angle = 0)
58 |     {
59 |         $text = new \ImagickDraw();
60 | 
61 |         $text->setFont($this->file);
62 | 
63 |         // ensure font resolution is the same as GD's hard-coded 96
64 |         if (static::getDriverInfo()->hasFeature(DriverInfo::FEATURE_CUSTOMRESOLUTION)) {
65 |             $text->setResolution(96, 96);
66 |             $text->setFontSize($this->size);
67 |         } else {
68 |             $text->setFontSize((int) ($this->size * (96 / 72)));
69 |         }
70 | 
71 |         $info = $this->imagick->queryFontMetrics($text, $string);
72 | 
73 |         $box = $this->getClassFactory()->createBox($info['textWidth'], $info['textHeight']);
74 | 
75 |         return $box;
76 |     }
77 | }
78 | 


--------------------------------------------------------------------------------
/src/Utils/ErrorHandling.php:
--------------------------------------------------------------------------------
 1 | <?php
 2 | 
 3 | /*
 4 |  * This file is part of the Imagine package.
 5 |  *
 6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
 7 |  *
 8 |  * For the full copyright and license information, please view the LICENSE
 9 |  * file that was distributed with this source code.
10 |  */
11 | 
12 | namespace Imagine\Utils;
13 | 
14 | use ErrorException;
15 | use Exception;
16 | use Imagine\Exception\RuntimeException;
17 | use Throwable;
18 | 
19 | class ErrorHandling
20 | {
21 |     /**
22 |      * Call a callback ignoring $flags warnings.
23 |      *
24 |      * @param int $flags The flags to be ignored (eg E_WARNING | E_NOTICE)
25 |      * @param callable $callback The callable to be called
26 |      *
27 |      * @throws \Exception Throws an Exception if $callback throws an Exception
28 |      * @throws \Throwable Throws an Throwable if $callback throws an Throwable
29 |      *
30 |      * @return mixed Returns the result of $callback
31 |      */
32 |     public static function ignoring($flags, $callback)
33 |     {
34 |         set_error_handler(
35 |             function () {
36 |             },
37 |             $flags
38 |         );
39 |         try {
40 |             $result = $callback();
41 |             $exception = null;
42 |         } catch (Exception $x) {
43 |             $exception = $x;
44 |         } catch (Throwable $x) {
45 |             $exception = $x;
46 |         }
47 |         restore_error_handler();
48 |         if ($exception !== null) {
49 |             throw $exception;
50 |         }
51 | 
52 |         return $result;
53 |     }
54 | 
55 |     /**
56 |      * Call a callback and throws a RuntimeException if a $flags warning is thrown.
57 |      *
58 |      * @param int $flags The flags to be intercepted (eg E_WARNING | E_NOTICE)
59 |      * @param callable $callback The callable to be called
60 |      *
61 |      * @throws RuntimeException
62 |      * @throws \Imagine\Exception\RuntimeException
63 |      * @throws \Exception
64 |      * @throws \Throwable
65 |      *
66 |      * @return mixed Returns the result of $callback
67 |      */
68 |     public static function throwingRuntimeException($flags, $callback)
69 |     {
70 |         set_error_handler(
71 |             function ($errno, $errstr, $errfile, $errline) {
72 |                 if (error_reporting() !== 0) {
73 |                     throw new RuntimeException($errstr, $errno, new ErrorException($errstr, 0, $errno, $errfile, $errline));
74 |                 }
75 |             },
76 |             $flags
77 |         );
78 |         try {
79 |             $result = $callback();
80 |             $exception = null;
81 |         } catch (Exception $x) {
82 |             $exception = $x;
83 |         } catch (Throwable $x) {
84 |             $exception = $x;
85 |         }
86 |         restore_error_handler();
87 |         if ($exception !== null) {
88 |             throw $exception;
89 |         }
90 | 
91 |         return $result;
92 |     }
93 | }
94 | 


--------------------------------------------------------------------------------
/src/Utils/Matrix.php:
--------------------------------------------------------------------------------
  1 | <?php
  2 | 
  3 | /*
  4 |  * This file is part of the Imagine package.
  5 |  *
  6 |  * (c) Bulat Shakirzyanov <mallluhuct@gmail.com>
  7 |  *
  8 |  * For the full copyright and license information, please view the LICENSE
  9 |  * file that was distributed with this source code.
 10 |  */
 11 | 
 12 | namespace Imagine\Utils;
 13 | 
 14 | use Imagine\Exception\InvalidArgumentException;
 15 | use Imagine\Exception\OutOfBoundsException;
 16 | 
 17 | class Matrix
 18 | {
 19 |     /**
 20 |      * The array of elements.
 21 |      *
 22 |      * @var int[]|float[]
 23 |      */
 24 |     protected $elements = array();
 25 | 
 26 |     /**
 27 |      * The matrix width.
 28 |      *
 29 |      * @var int
 30 |      */
 31 |     protected $width;
 32 | 
 33 |     /**
 34 |      * The matrix height.
 35 |      *
 36 |      * @var int
 37 |      */
 38 |     protected $height;
 39 | 
 40 |     /**
 41 |      * The given $elements get arranged as follows: The elements will be set from left to right in a row until the
 42 |      * row is full. Then, the next line begins alike and so on.
 43 |      *
 44 |      * @param int $width the matrix width
 45 |      * @param int $height he matrix height
 46 |      * @param int[]|float[] $elements the matrix elements
 47 |      *
 48 |      * @throws \Imagine\Exception\InvalidArgumentException
 49 |      */
 50 |     public function __construct($width, $height, $elements = array())
 51 |     {
 52 |         $this->width = (int) round($width);
 53 |         if ($this->width < 1) {
 54 |             throw new InvalidArgumentException('width has to be > 0');
 55 |         }
 56 |         $this->height = (int) round($height);
 57 |         if ($this->height < 1) {
 58 |             throw new InvalidArgumentException('height has to be > 0');
 59 |         }
 60 |         $expectedElements = $width * $height;
 61 |         $providedElements = count($elements);
 62 |         if ($providedElements > $expectedElements) {
 63 |             throw new InvalidArgumentException('there are more provided elements than space in the matrix');
 64 |         }
 65 |         $this->elements = array_values($elements);
 66 |         if ($providedElements < $expectedElements) {
 67 |             $this->elements = array_merge(
 68 |                 $this->elements,
 69 |                 array_fill($providedElements, $expectedElements - $providedElements, 0)
 70 |             );
 71 |         }
 72 |     }
 73 | 
 74 |     /**
 75 |      * Get the matrix width.
 76 |      *
 77 |      * @return int
 78 |      */
 79 |     public function getWidth()
 80 |     {
 81 |         return $this->width;
 82 |     }
 83 | 
 84 |     /**
 85 |      * Get the matrix height.
 86 |      *
 87 |      * @return int
 88 |      */
 89 |     public function getHeight()
 90 |     {
 91 |         return $this->height;
 92 |     }
 93 | 
 94 |     /**
 95 |      * Set the value of a cell.
 96 |      *
 97 |      * @param int $x
 98 |      * @param int $y
 99 |      * @param int|float $value
100 |      */
101 |     public function setElementAt($x, $y, $value)
102 |     {
103 |         $this->elements[$this->calculatePosition($x, $y)] = $value;
104 |     }
105 | 
106 |     /**
107 |      * Get the value of a cell.
108 |      *
109 |      * @param int $x
110 |      * @param int $y
111 |      *
112 |      * @return int|float
113 |      */
114 |     public function getElementAt($x, $y)
115 |     {
116 |         return $this->elements[$this->calculatePosition($x, $y)];
117 |     }
118 | 
119 |     /**
120 |      * Return all the matrix values, as a monodimensional array.
121 |      *
122 |      * @return int[]|float[]
123 |      */
124 |     public function getValueList()
125 |     {
126 |         return $this->elements;
127 |     }
128 | 
129 |     /**
130 |      * Return all the matrix values, as a bidimensional array (every array item contains the values of a row).
131 |      *
132 |      * @return int[]|float[]
133 |      */
134 |     public function getMatrix()
135 |     {
136 |         return array_chunk($this->elements, $this->getWidth());
137 |     }
138 | 
139 |     /**
140 |      * Returns a new Matrix instance, representing the normalized value of this matrix.
141 |      *
142 |      * @return static
143 |      */
144 |     public function normalize()
145 |     {
146 |         $values = $this->getValueList();
147 |         $divisor = array_sum($values);
148 |         if ($divisor == 0 || $divisor == 1) {
149 |             return clone $this;
150 |         }
151 |         $normalizedElements = array();
152 |         foreach ($values as $value) {
153 |             $normalizedElements[] = $value / $divisor;
154 |         }
155 | 
156 |         return new static($this->getWidth(), $this->getHeight(), $normalizedElements);
157 |     }
158 | 
159 |     /**
160 |      * Calculate the offset position of a cell.
161 |      *
162 |      * @param int $x
163 |      * @param int $y
164 |      *
165 |      * @throws \Imagine\Exception\OutOfBoundsException
166 |      *
167 |      * @return int
168 |      */
169 |     protected function calculatePosition($x, $y)
170 |     {
171 |         if ($x < 0 || $y < 0 || $this->width <= $x || $this->height <= $y) {
172 |             throw new OutOfBoundsException(sprintf('There is no position (%s, %s) in this matrix', $x, $y));
173 |         }
174 | 
175 |         return $y * $this->height + $x;
176 |     }
177 | }
178 | 


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/CoatedFOGRA27.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/CoatedFOGRA27.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/CoatedFOGRA39.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/CoatedFOGRA39.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/CoatedGRACoL2006.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/CoatedGRACoL2006.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/JapanColor2001Coated.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/JapanColor2001Coated.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/JapanColor2001Uncoated.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/JapanColor2001Uncoated.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/JapanColor2002Newspaper.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/JapanColor2002Newspaper.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/JapanColor2003WebCoated.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/JapanColor2003WebCoated.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/JapanWebCoated.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/JapanWebCoated.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/USWebCoatedSWOP.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/USWebCoatedSWOP.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/USWebUncoated.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/USWebUncoated.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/UncoatedFOGRA29.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/UncoatedFOGRA29.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/WebCoatedFOGRA28.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/WebCoatedFOGRA28.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/WebCoatedSWOP2006Grade3.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/WebCoatedSWOP2006Grade3.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/CMYK/WebCoatedSWOP2006Grade5.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/CMYK/WebCoatedSWOP2006Grade5.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/AdobeRGB1998.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/AdobeRGB1998.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/AppleRGB.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/AppleRGB.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/ColorMatchRGB.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/ColorMatchRGB.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/PAL_SECAM.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/PAL_SECAM.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/SMPTE-C.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/SMPTE-C.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/VideoHD.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/VideoHD.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/VideoNTSC.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/VideoNTSC.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/RGB/VideoPAL.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/Adobe/RGB/VideoPAL.icc


--------------------------------------------------------------------------------
/src/resources/Adobe/Trademark Information.md:
--------------------------------------------------------------------------------
 1 | *5/10/05*
 2 | 
 3 | # Trademark Information
 4 | 
 5 | Adobe is either a registered trademark or trademark of Adobe Systems Incorporated in the United States and/or other countries. All instances of the name “Adobe RGB” are references to the Adobe RGB (1998) color space and color encodings as defined by Adobe, unless otherwise stated. The name “Adobe RGB (1998)” also is used as a software product trademark for Adobe’s implementation of the Adobe RGB (1998) ICC profile. Adobe does not permit the use of the Adobe RGB trademark for software, hardware, or other related products from companies other than Adobe, unless the company has obtained a prior written license from Adobe to do so.
 6 | 
 7 | ## Distributing the Adobe RGB (1998) ICC profile
 8 | 
 9 | You may distribute the Adobe RGB (1998) ICC profile as embedded within digital image files and on a standalone basis so long as you accept the terms and conditions of the Color Profile License Agreement on this page and the Adobe end-user license agreement.
10 | 
11 | Keep in mind that you must sign a supplementary license agreement with Adobe if you are interested in distributing the Adobe RGB (1998) ICC profile software embedded or as a bundle with a camera, display or other hardware device or software application. If you have not already signed an agreement, please contact your Adobe representative.
12 | 


--------------------------------------------------------------------------------
/src/resources/color.org/sRGB_IEC61966-2-1_black_scaled.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/color.org/sRGB_IEC61966-2-1_black_scaled.icc


--------------------------------------------------------------------------------
/src/resources/color.org/sRGB_IEC61966-2-1_no_black_scaling.icc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/color.org/sRGB_IEC61966-2-1_no_black_scaling.icc


--------------------------------------------------------------------------------
/src/resources/colormanagement.org/ISOcoated_v2_grey1c_bas.ICC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-imagine/Imagine/43856ce80debe1c7b0d7a5fc8497ac64bb6870c3/src/resources/colormanagement.org/ISOcoated_v2_grey1c_bas.ICC


--------------------------------------------------------------------------------