downgrade to kirby v3
This commit is contained in:
5
vendor/league/color-extractor/.gitignore
vendored
Normal file
5
vendor/league/color-extractor/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
vendor
|
||||
composer.lock
|
||||
.DS_Store
|
||||
.idea
|
||||
.php_cs.cache
|
||||
13
vendor/league/color-extractor/.php_cs
vendored
Normal file
13
vendor/league/color-extractor/.php_cs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$finder = Symfony\Component\Finder\Finder::create()
|
||||
->files()
|
||||
->name('*.php')
|
||||
->in(array('src', 'tests'));
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setFinder($finder)
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
]);
|
||||
16
vendor/league/color-extractor/.travis.yml
vendored
Normal file
16
vendor/league/color-extractor/.travis.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- travis_retry composer self-update
|
||||
- travis_retry composer install --no-interaction --prefer-source --dev
|
||||
|
||||
script:
|
||||
- phpunit --coverage-text
|
||||
- ./vendor/bin/phpcs src --standard=psr2
|
||||
32
vendor/league/color-extractor/CONTRIBUTING.md
vendored
Normal file
32
vendor/league/color-extractor/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# Contributing
|
||||
|
||||
Contributions are **welcome** and will be fully **credited**.
|
||||
|
||||
We accept contributions via Pull Requests on [Github](https://github.com/php-loep/statsd).
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
|
||||
|
||||
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
|
||||
|
||||
- **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date.
|
||||
|
||||
- **Consider our release cycle** - We try to follow semver. Randomly breaking public APIs is not an option.
|
||||
|
||||
- **Create topic branches** - Don't ask us to pull from your master branch.
|
||||
|
||||
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
|
||||
|
||||
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
|
||||
|
||||
|
||||
## Running Tests
|
||||
|
||||
``` bash
|
||||
$ phpunit
|
||||
```
|
||||
|
||||
|
||||
**Happy coding**!
|
||||
21
vendor/league/color-extractor/LICENSE
vendored
Normal file
21
vendor/league/color-extractor/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Mathieu Lechat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
79
vendor/league/color-extractor/README.md
vendored
Normal file
79
vendor/league/color-extractor/README.md
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
ColorExtractor
|
||||
==============
|
||||
|
||||
[](https://travis-ci.org/thephpleague/color-extractor)
|
||||
[](https://packagist.org/packages/league/color-extractor)
|
||||
[](https://packagist.org/packages/league/color-extractor)
|
||||
|
||||
Extract colors from an image like a human would do.
|
||||
|
||||
## Install
|
||||
|
||||
Via Composer
|
||||
|
||||
``` bash
|
||||
$ composer require league/color-extractor:0.3.*
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use League\ColorExtractor\Color;
|
||||
use League\ColorExtractor\ColorExtractor;
|
||||
use League\ColorExtractor\Palette;
|
||||
|
||||
$palette = Palette::fromFilename('./some/image.png');
|
||||
|
||||
// $palette is an iterator on colors sorted by pixel count
|
||||
foreach($palette as $color => $count) {
|
||||
// colors are represented by integers
|
||||
echo Color::fromIntToHex($color), ': ', $count, "\n";
|
||||
}
|
||||
|
||||
// it offers some helpers too
|
||||
$topFive = $palette->getMostUsedColors(5);
|
||||
|
||||
$colorCount = count($palette);
|
||||
|
||||
$blackCount = $palette->getColorCount(Color::fromHexToInt('#000000'));
|
||||
|
||||
|
||||
// an extractor is built from a palette
|
||||
$extractor = new ColorExtractor($palette);
|
||||
|
||||
// it defines an extract method which return the most “representative” colors
|
||||
$colors = $extractor->extract(5);
|
||||
|
||||
```
|
||||
|
||||
## Handling transparency
|
||||
|
||||
By default **any pixel with alpha value greater than zero will be discarded**. This is because transparent colors are not perceived
|
||||
as is. For exemple fully transparent black would be seen white on a white background. So if you want to take transparency into account
|
||||
when building a palette you have to specify this background color. You can do this with the second argument of `Palette` constructors.
|
||||
Its default value is `null`, meaning a color won't be added to the palette if its alpha component exists and is greater than zero.
|
||||
|
||||
You can set it as an integer representing the color, then transparent colors will be blended before addition to the palette.
|
||||
|
||||
```php
|
||||
// we set a white background so fully transparent colors will be added as white in the palette
|
||||
// pure red #FF0000 at 50% opacity will be stored as #FF8080 as it would be perceived
|
||||
$palette = Palette::fromFilename('./some/image.png', Color::fromHexToInt('#FFFFFF'));
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/thephpleague/color-extractor/blob/master/CONTRIBUTING.md) for details.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
- [Mathieu Lechat](https://github.com/MatTheCat)
|
||||
- [All Contributors](https://github.com/thephpleague/color-extractor/contributors)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](https://github.com/thephpleague/color-extractor/blob/master/LICENSE) for more information.
|
||||
32
vendor/league/color-extractor/composer.json
vendored
Normal file
32
vendor/league/color-extractor/composer.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "league/color-extractor",
|
||||
"type": "library",
|
||||
"description": "Extract colors from an image as a human would do.",
|
||||
"keywords": ["image", "color", "extract", "palette", "human"],
|
||||
"homepage": "https://github.com/thephpleague/color-extractor",
|
||||
"license": "MIT",
|
||||
"replace": {
|
||||
"matthecat/colorextractor": "*"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mathieu Lechat",
|
||||
"email": "math.lechat@gmail.com",
|
||||
"homepage": "http://matthecat.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"ext-gd": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "~2",
|
||||
"phpunit/phpunit": "~5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "src"
|
||||
}
|
||||
}
|
||||
}
|
||||
13
vendor/league/color-extractor/phpunit.xml.dist
vendored
Normal file
13
vendor/league/color-extractor/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit colors="true" bootstrap="tests/bootstrap.php">
|
||||
<testsuites>
|
||||
<testsuite name="ColorExtractor Test Suite">
|
||||
<directory>tests/League/ColorExtractor</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src/League/ColorExtractor</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
51
vendor/league/color-extractor/src/League/ColorExtractor/Color.php
vendored
Normal file
51
vendor/league/color-extractor/src/League/ColorExtractor/Color.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace League\ColorExtractor;
|
||||
|
||||
class Color
|
||||
{
|
||||
/**
|
||||
* @param int $color
|
||||
* @param bool $prependHash = true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function fromIntToHex($color, $prependHash = true)
|
||||
{
|
||||
return ($prependHash ? '#' : '').sprintf('%06X', $color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $color
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function fromHexToInt($color)
|
||||
{
|
||||
return hexdec(ltrim($color, '#'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $color
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function fromIntToRgb($color)
|
||||
{
|
||||
return [
|
||||
'r' => $color >> 16 & 0xFF,
|
||||
'g' => $color >> 8 & 0xFF,
|
||||
'b' => $color & 0xFF,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $components
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function fromRgbToInt(array $components)
|
||||
{
|
||||
return ($components['r'] * 65536) + ($components['g'] * 256) + ($components['b']);
|
||||
}
|
||||
}
|
||||
275
vendor/league/color-extractor/src/League/ColorExtractor/ColorExtractor.php
vendored
Normal file
275
vendor/league/color-extractor/src/League/ColorExtractor/ColorExtractor.php
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
namespace League\ColorExtractor;
|
||||
|
||||
class ColorExtractor
|
||||
{
|
||||
/** @var \League\ColorExtractor\Palette */
|
||||
protected $palette;
|
||||
|
||||
/** @var \SplFixedArray */
|
||||
protected $sortedColors;
|
||||
|
||||
/**
|
||||
* @param \League\ColorExtractor\Palette $palette
|
||||
*/
|
||||
public function __construct(Palette $palette)
|
||||
{
|
||||
$this->palette = $palette;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $colorCount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function extract($colorCount = 1)
|
||||
{
|
||||
if (!$this->isInitialized()) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
return self::mergeColors($this->sortedColors, $colorCount, 100 / $colorCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function isInitialized()
|
||||
{
|
||||
return $this->sortedColors !== null;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
$queue = new \SplPriorityQueue();
|
||||
$this->sortedColors = new \SplFixedArray(count($this->palette));
|
||||
|
||||
$i = 0;
|
||||
foreach ($this->palette as $color => $count) {
|
||||
$labColor = self::intColorToLab($color);
|
||||
$queue->insert(
|
||||
$color,
|
||||
(sqrt($labColor['a'] * $labColor['a'] + $labColor['b'] * $labColor['b']) ?: 1) *
|
||||
(1 - $labColor['L'] / 200) *
|
||||
sqrt($count)
|
||||
);
|
||||
++$i;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
while ($queue->valid()) {
|
||||
$this->sortedColors[$i] = $queue->current();
|
||||
$queue->next();
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SplFixedArray $colors
|
||||
* @param int $limit
|
||||
* @param int $maxDelta
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function mergeColors(\SplFixedArray $colors, $limit, $maxDelta)
|
||||
{
|
||||
$limit = min(count($colors), $limit);
|
||||
if ($limit === 1) {
|
||||
return [$colors[0]];
|
||||
}
|
||||
$labCache = new \SplFixedArray($limit - 1);
|
||||
$mergedColors = [];
|
||||
|
||||
foreach ($colors as $color) {
|
||||
$hasColorBeenMerged = false;
|
||||
|
||||
$colorLab = self::intColorToLab($color);
|
||||
|
||||
foreach ($mergedColors as $i => $mergedColor) {
|
||||
if (self::ciede2000DeltaE($colorLab, $labCache[$i]) < $maxDelta) {
|
||||
$hasColorBeenMerged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasColorBeenMerged) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mergedColorCount = count($mergedColors);
|
||||
$mergedColors[] = $color;
|
||||
|
||||
if ($mergedColorCount + 1 == $limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
$labCache[$mergedColorCount] = $colorLab;
|
||||
}
|
||||
|
||||
return $mergedColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $firstLabColor
|
||||
* @param array $secondLabColor
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected static function ciede2000DeltaE($firstLabColor, $secondLabColor)
|
||||
{
|
||||
$C1 = sqrt(pow($firstLabColor['a'], 2) + pow($firstLabColor['b'], 2));
|
||||
$C2 = sqrt(pow($secondLabColor['a'], 2) + pow($secondLabColor['b'], 2));
|
||||
$Cb = ($C1 + $C2) / 2;
|
||||
|
||||
$G = .5 * (1 - sqrt(pow($Cb, 7) / (pow($Cb, 7) + pow(25, 7))));
|
||||
|
||||
$a1p = (1 + $G) * $firstLabColor['a'];
|
||||
$a2p = (1 + $G) * $secondLabColor['a'];
|
||||
|
||||
$C1p = sqrt(pow($a1p, 2) + pow($firstLabColor['b'], 2));
|
||||
$C2p = sqrt(pow($a2p, 2) + pow($secondLabColor['b'], 2));
|
||||
|
||||
$h1p = $a1p == 0 && $firstLabColor['b'] == 0 ? 0 : atan2($firstLabColor['b'], $a1p);
|
||||
$h2p = $a2p == 0 && $secondLabColor['b'] == 0 ? 0 : atan2($secondLabColor['b'], $a2p);
|
||||
|
||||
$LpDelta = $secondLabColor['L'] - $firstLabColor['L'];
|
||||
$CpDelta = $C2p - $C1p;
|
||||
|
||||
if ($C1p * $C2p == 0) {
|
||||
$hpDelta = 0;
|
||||
} elseif (abs($h2p - $h1p) <= 180) {
|
||||
$hpDelta = $h2p - $h1p;
|
||||
} elseif ($h2p - $h1p > 180) {
|
||||
$hpDelta = $h2p - $h1p - 360;
|
||||
} else {
|
||||
$hpDelta = $h2p - $h1p + 360;
|
||||
}
|
||||
|
||||
$HpDelta = 2 * sqrt($C1p * $C2p) * sin($hpDelta / 2);
|
||||
|
||||
$Lbp = ($firstLabColor['L'] + $secondLabColor['L']) / 2;
|
||||
$Cbp = ($C1p + $C2p) / 2;
|
||||
|
||||
if ($C1p * $C2p == 0) {
|
||||
$hbp = $h1p + $h2p;
|
||||
} elseif (abs($h1p - $h2p) <= 180) {
|
||||
$hbp = ($h1p + $h2p) / 2;
|
||||
} elseif ($h1p + $h2p < 360) {
|
||||
$hbp = ($h1p + $h2p + 360) / 2;
|
||||
} else {
|
||||
$hbp = ($h1p + $h2p - 360) / 2;
|
||||
}
|
||||
|
||||
$T = 1 - .17 * cos($hbp - 30) + .24 * cos(2 * $hbp) + .32 * cos(3 * $hbp + 6) - .2 * cos(4 * $hbp - 63);
|
||||
|
||||
$sigmaDelta = 30 * exp(-pow(($hbp - 275) / 25, 2));
|
||||
|
||||
$Rc = 2 * sqrt(pow($Cbp, 7) / (pow($Cbp, 7) + pow(25, 7)));
|
||||
|
||||
$Sl = 1 + ((.015 * pow($Lbp - 50, 2)) / sqrt(20 + pow($Lbp - 50, 2)));
|
||||
$Sc = 1 + .045 * $Cbp;
|
||||
$Sh = 1 + .015 * $Cbp * $T;
|
||||
|
||||
$Rt = -sin(2 * $sigmaDelta) * $Rc;
|
||||
|
||||
return sqrt(
|
||||
pow($LpDelta / $Sl, 2) +
|
||||
pow($CpDelta / $Sc, 2) +
|
||||
pow($HpDelta / $Sh, 2) +
|
||||
$Rt * ($CpDelta / $Sc) * ($HpDelta / $Sh)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $color
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function intColorToLab($color)
|
||||
{
|
||||
return self::xyzToLab(
|
||||
self::srgbToXyz(
|
||||
self::rgbToSrgb(
|
||||
[
|
||||
'R' => ($color >> 16) & 0xFF,
|
||||
'G' => ($color >> 8) & 0xFF,
|
||||
'B' => $color & 0xFF,
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected static function rgbToSrgbStep($value)
|
||||
{
|
||||
$value /= 255;
|
||||
|
||||
return $value <= .03928 ?
|
||||
$value / 12.92 :
|
||||
pow(($value + .055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $rgb
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function rgbToSrgb($rgb)
|
||||
{
|
||||
return [
|
||||
'R' => self::rgbToSrgbStep($rgb['R']),
|
||||
'G' => self::rgbToSrgbStep($rgb['G']),
|
||||
'B' => self::rgbToSrgbStep($rgb['B']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $rgb
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function srgbToXyz($rgb)
|
||||
{
|
||||
return [
|
||||
'X' => (.4124564 * $rgb['R']) + (.3575761 * $rgb['G']) + (.1804375 * $rgb['B']),
|
||||
'Y' => (.2126729 * $rgb['R']) + (.7151522 * $rgb['G']) + (.0721750 * $rgb['B']),
|
||||
'Z' => (.0193339 * $rgb['R']) + (.1191920 * $rgb['G']) + (.9503041 * $rgb['B']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected static function xyzToLabStep($value)
|
||||
{
|
||||
return $value > 216 / 24389 ? pow($value, 1 / 3) : 841 * $value / 108 + 4 / 29;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $xyz
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function xyzToLab($xyz)
|
||||
{
|
||||
//http://en.wikipedia.org/wiki/Illuminant_D65#Definition
|
||||
$Xn = .95047;
|
||||
$Yn = 1;
|
||||
$Zn = 1.08883;
|
||||
|
||||
// http://en.wikipedia.org/wiki/Lab_color_space#CIELAB-CIEXYZ_conversions
|
||||
return [
|
||||
'L' => 116 * self::xyzToLabStep($xyz['Y'] / $Yn) - 16,
|
||||
'a' => 500 * (self::xyzToLabStep($xyz['X'] / $Xn) - self::xyzToLabStep($xyz['Y'] / $Yn)),
|
||||
'b' => 200 * (self::xyzToLabStep($xyz['Y'] / $Yn) - self::xyzToLabStep($xyz['Z'] / $Zn)),
|
||||
];
|
||||
}
|
||||
}
|
||||
126
vendor/league/color-extractor/src/League/ColorExtractor/Palette.php
vendored
Normal file
126
vendor/league/color-extractor/src/League/ColorExtractor/Palette.php
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace League\ColorExtractor;
|
||||
|
||||
class Palette implements \Countable, \IteratorAggregate
|
||||
{
|
||||
/** @var array */
|
||||
protected $colors;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $color
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getColorCount($color)
|
||||
{
|
||||
return $this->colors[$color];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit = null
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMostUsedColors($limit = null)
|
||||
{
|
||||
return array_slice($this->colors, 0, $limit, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @param int|null $backgroundColor
|
||||
*
|
||||
* @return Palette
|
||||
*/
|
||||
public static function fromFilename($filename, $backgroundColor = null)
|
||||
{
|
||||
$image = imagecreatefromstring(file_get_contents($filename));
|
||||
$palette = self::fromGD($image, $backgroundColor);
|
||||
imagedestroy($image);
|
||||
|
||||
return $palette;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $image
|
||||
* @param int|null $backgroundColor
|
||||
*
|
||||
* @return Palette
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function fromGD($image, $backgroundColor = null)
|
||||
{
|
||||
if (!is_resource($image) || get_resource_type($image) != 'gd') {
|
||||
throw new \InvalidArgumentException('Image must be a gd resource');
|
||||
}
|
||||
if ($backgroundColor !== null && (!is_numeric($backgroundColor) || $backgroundColor < 0 || $backgroundColor > 16777215)) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" does not represent a valid color', $backgroundColor));
|
||||
}
|
||||
|
||||
$palette = new self();
|
||||
|
||||
$areColorsIndexed = !imageistruecolor($image);
|
||||
$imageWidth = imagesx($image);
|
||||
$imageHeight = imagesy($image);
|
||||
$palette->colors = [];
|
||||
|
||||
$backgroundColorRed = ($backgroundColor >> 16) & 0xFF;
|
||||
$backgroundColorGreen = ($backgroundColor >> 8) & 0xFF;
|
||||
$backgroundColorBlue = $backgroundColor & 0xFF;
|
||||
|
||||
for ($x = 0; $x < $imageWidth; ++$x) {
|
||||
for ($y = 0; $y < $imageHeight; ++$y) {
|
||||
$color = imagecolorat($image, $x, $y);
|
||||
if ($areColorsIndexed) {
|
||||
$colorComponents = imagecolorsforindex($image, $color);
|
||||
$color = ($colorComponents['alpha'] * 16777216) +
|
||||
($colorComponents['red'] * 65536) +
|
||||
($colorComponents['green'] * 256) +
|
||||
($colorComponents['blue']);
|
||||
}
|
||||
|
||||
if ($alpha = $color >> 24) {
|
||||
if ($backgroundColor === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$alpha /= 127;
|
||||
$color = (int) (($color >> 16 & 0xFF) * (1 - $alpha) + $backgroundColorRed * $alpha) * 65536 +
|
||||
(int) (($color >> 8 & 0xFF) * (1 - $alpha) + $backgroundColorGreen * $alpha) * 256 +
|
||||
(int) (($color & 0xFF) * (1 - $alpha) + $backgroundColorBlue * $alpha);
|
||||
}
|
||||
|
||||
isset($palette->colors[$color]) ?
|
||||
$palette->colors[$color] += 1 :
|
||||
$palette->colors[$color] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
arsort($palette->colors);
|
||||
|
||||
return $palette;
|
||||
}
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
$this->colors = [];
|
||||
}
|
||||
}
|
||||
67
vendor/league/color-extractor/tests/League/ColorExtractor/Test/PaletteTest.php
vendored
Normal file
67
vendor/league/color-extractor/tests/League/ColorExtractor/Test/PaletteTest.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace League\ColorExtractor\Test;
|
||||
|
||||
use League\ColorExtractor\Color;
|
||||
use League\ColorExtractor\ColorExtractor;
|
||||
use League\ColorExtractor\Palette;
|
||||
|
||||
class PaletteTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $jpegPath = './tests/assets/test.jpeg';
|
||||
protected $gifPath = './tests/assets/test.gif';
|
||||
protected $pngPath = './tests/assets/test.png';
|
||||
protected $transparentPngPath = './tests/assets/red-transparent-50.png';
|
||||
|
||||
public function testJpegExtractSingleColor()
|
||||
{
|
||||
$extractor = new ColorExtractor(Palette::fromFilename($this->jpegPath));
|
||||
$colors = $extractor->extract(1);
|
||||
|
||||
$this->assertInternalType('array', $colors);
|
||||
$this->assertCount(1, $colors);
|
||||
$this->assertEquals(15985688, $colors[0]);
|
||||
}
|
||||
|
||||
public function testGifExtractSingleColor()
|
||||
{
|
||||
$extractor = new ColorExtractor(Palette::fromFilename($this->gifPath));
|
||||
$colors = $extractor->extract(1);
|
||||
|
||||
$this->assertInternalType('array', $colors);
|
||||
$this->assertCount(1, $colors);
|
||||
$this->assertEquals(12022491, $colors[0]);
|
||||
}
|
||||
|
||||
public function testPngExtractSingleColor()
|
||||
{
|
||||
$extractor = new ColorExtractor(Palette::fromFilename($this->pngPath));
|
||||
$colors = $extractor->extract(1);
|
||||
|
||||
$this->assertInternalType('array', $colors);
|
||||
$this->assertCount(1, $colors);
|
||||
$this->assertEquals(14024704, $colors[0]);
|
||||
}
|
||||
|
||||
public function testJpegExtractMultipleColors()
|
||||
{
|
||||
$extractor = new ColorExtractor(Palette::fromFilename($this->pngPath));
|
||||
$numColors = 3;
|
||||
$colors = $extractor->extract($numColors);
|
||||
|
||||
$this->assertInternalType('array', $colors);
|
||||
$this->assertCount($numColors, $colors);
|
||||
$this->assertEquals($colors, [14024704, 3407872, 7111569]);
|
||||
}
|
||||
|
||||
public function testTransparencyHandling()
|
||||
{
|
||||
$this->assertCount(0, Palette::fromFilename($this->transparentPngPath));
|
||||
|
||||
$whiteBackgroundPalette = Palette::fromFilename($this->transparentPngPath, Color::fromHexToInt('#FFFFFF'));
|
||||
$this->assertEquals(iterator_to_array($whiteBackgroundPalette), [Color::fromHexToInt('#FF8080') => 1]);
|
||||
|
||||
$blackBackgroundPalette = Palette::fromFilename($this->transparentPngPath, Color::fromHexToInt('#000000'));
|
||||
$this->assertEquals(iterator_to_array($blackBackgroundPalette), [Color::fromHexToInt('#7E0000') => 1]);
|
||||
}
|
||||
}
|
||||
BIN
vendor/league/color-extractor/tests/assets/google.png
vendored
Normal file
BIN
vendor/league/color-extractor/tests/assets/google.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
vendor/league/color-extractor/tests/assets/red-transparent-50.png
vendored
Normal file
BIN
vendor/league/color-extractor/tests/assets/red-transparent-50.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 B |
BIN
vendor/league/color-extractor/tests/assets/test.gif
vendored
Normal file
BIN
vendor/league/color-extractor/tests/assets/test.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
BIN
vendor/league/color-extractor/tests/assets/test.jpeg
vendored
Normal file
BIN
vendor/league/color-extractor/tests/assets/test.jpeg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
vendor/league/color-extractor/tests/assets/test.png
vendored
Normal file
BIN
vendor/league/color-extractor/tests/assets/test.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 289 KiB |
4
vendor/league/color-extractor/tests/bootstrap.php
vendored
Normal file
4
vendor/league/color-extractor/tests/bootstrap.php
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
$loader = require __DIR__.'/../vendor/autoload.php';
|
||||
$loader->addPsr4('', __DIR__);
|
||||
Reference in New Issue
Block a user