Вход Регистрация
Файл: vendor/intervention/image/src/Colors/Rgb/Colorspace.php
Строк: 287
<?php

declare(strict_types=1);

namespace 
InterventionImageColorsRgb;

use 
InterventionImageColorsAbstractColorspace;
use 
InterventionImageColorsCmykColor as CmykColor;
use 
InterventionImageColorsHslColor as HslColor;
use 
InterventionImageColorsHsvColor as HsvColor;
use 
InterventionImageColorsOklabColor as OklabColor;
use 
InterventionImageColorsOklabColorspace as Oklab;
use 
InterventionImageColorsOklchColor as OklchColor;
use 
InterventionImageColorsRgbColor as RgbColor;
use 
InterventionImageColorsRgbDecodersHexColorDecoder;
use 
InterventionImageExceptionsColorException;
use 
InterventionImageExceptionsDriverException;
use 
InterventionImageExceptionsInvalidArgumentException;
use 
InterventionImageExceptionsNotSupportedException;
use 
InterventionImageInputHandler;
use 
InterventionImageInterfacesColorChannelInterface;
use 
InterventionImageInterfacesColorInterface;
use 
TypeError;

class 
Colorspace extends AbstractColorspace
{
    
/**
     * Channel class names of colorspace.
     *
     * @var array<string>
     */
    
public static array $channels = [
        
ChannelsRed::class,
        
ChannelsGreen::class,
        
ChannelsBlue::class,
        
ChannelsAlpha::class,
    ];

    
/**
     * {@inheritdoc}
     *
     * @see ColorspaceInterface::colorFromNormalized()
     *
     * @throws InvalidArgumentException
     */
    
public static function colorFromNormalized(array $normalized): RgbColor
    
{
        if (!
in_array(count($normalized), [34])) {
            throw new 
InvalidArgumentException('Number of color channels must be 3 or 4 for ' . static::class);
        }

        
// add alpha value if missing
        
$normalized count($normalized) === array_pad($normalized41) : $normalized;

        return new 
Color(...array_map(
            function (
string $channelnull|float $normalized) {
                try {
                    return 
$channel::fromNormalized($normalized);
                } catch (
TypeError $e) {
                    throw new 
InvalidArgumentException(
                        
'Normalized color value must be in range 0 to 1',
                        
previous$e,
                    );
                }
            },
            
self::$channels,
            
$normalized,
        ));
    }

    
/**
     * {@inheritdoc}
     *
     * @see ColorspaceInterface::importColor()
     *
     * @throws ColorException
     */
    
public function importColor(ColorInterface $color): RgbColor
    
{
        return 
match ($color::class) {
            
CmykColor::class => $this->importCmykColor($color),
            
HsvColor::class => $this->importHsvColor($color),
            
HslColor::class => $this->importHslColor($color),
            
OklabColor::class => $this->importOklabColor($color),
            
OklchColor::class => $this->importOklchColor($color),
            
NamedColor::class => $this->importNamedColor($color),
            
RgbColor::class => $color,
            default => throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
            ),
        };
    }

    
/**
     * @throws ColorException
     */
    
private function importCmykColor(CmykColor $color): RgbColor
    
{
        try {
            return new 
Color(
                (int) (
255 * ($color->cyan()->normalized()) * ($color->key()->normalized())),
                (int) (
255 * ($color->magenta()->normalized()) * ($color->key()->normalized())),
                (int) (
255 * ($color->yellow()->normalized()) * ($color->key()->normalized())),
                
$color->alpha()->normalized(),
            );
        } catch (
InvalidArgumentException $e) {
            throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
                
previous$e,
            );
        }
    }

    
/**
     * Import given HSV color to RGB color space.
     *
     * @throws ColorException
     */
    
private function importHsvColor(HsvColor $color): RgbColor
    
{
        
$chroma $color->value()->normalized() * $color->saturation()->normalized();
        
$hue $color->hue()->normalized() * 6;
        
$x $chroma * (abs(fmod($hue2) - 1));

        
// connect channel values
        
$values match (true) {
            
$hue => [$chroma$x0],
            
$hue => [$x$chroma0],
            
$hue => [0$chroma$x],
            
$hue => [0$x$chroma],
            
$hue => [$x0$chroma],
            default => [
$chroma0$x],
        };

        
// add to each value
        
$values array_map(
            
fn(float|int $value): float => max(0.0min(1.0$value $color->value()->normalized() - $chroma)),
            
$values,
        );

        
$values[] = $color->alpha()->normalized(); // append alpha channel value

        
try {
            return 
$this->colorFromNormalized($values);
        } catch (
InvalidArgumentException $e) {
            throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
                
previous$e,
            );
        }
    }

    
/**
     * Import given HSL color to RGB color space.
     *
     * @throws ColorException
     */
    
private function importHslColor(HslColor $color): RgbColor
    
{
        
// normalized values of hsl channels
        
[$h$s$l] = array_map(
            
fn(ColorChannelInterface $channel): float => $channel->normalized(),
            
$color->channels(),
        );

        
$c = (abs($l 1)) * $s;
        
$x $c * (abs(fmod($h 62) - 1));
        
$m $l $c 2;

        
$values match (true) {
            
$h => [$c$x0],
            
$h => [$x$c0],
            
$h => [0$c$x],
            
$h => [0$x$c],
            
$h => [$x0$c],
            default => [
$c0$x],
        };

        
$values array_map(fn(float|int $value): float => max(0.0min(1.0$value $m)), $values);
        
$values[] = $color->alpha()->normalized(); // append alpha channel value

        
try {
            
$color $this->colorFromNormalized($values);
        } catch (
InvalidArgumentException $e) {
            throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
                
previous$e,
            );
        }

        return 
$color;
    }

    
/**
     * Import given OKLAB color to RGB color space.
     *
     * @throws ColorException
     */
    
private function importOklabColor(OklabColor $color): RgbColor
    
{
        
$linearToRgb = function (float $c): float {
            
$c max(0.0min(1.0$c));

            if (
$c <= 0.0031308) {
                return 
12.92 $c;
            }

            return 
1.055 * ($c ** (2.4)) - 0.055;
        };

        
$l $color->lightness()->value() + 0.3963377774 $color->a()->value() + 0.2158037573 $color->b()->value();
        
$m $color->lightness()->value() - 0.1055613458 $color->a()->value() - 0.0638541728 $color->b()->value();
        
$s $color->lightness()->value() - 0.0894841775 $color->a()->value() - 1.2914855480 $color->b()->value();

        
$l $l ** 3;
        
$m $m ** 3;
        
$s $s ** 3;

        
$r = +4.0767416621 $l 3.3077115913 $m 0.2309699292 $s;
        
$g = -1.2684380046 $l 2.6097574011 $m 0.3413193965 $s;
        
$b = -0.0041960863 $l 0.7034186147 $m 1.7076147010 $s;

        
$r $linearToRgb($r);
        
$g $linearToRgb($g);
        
$b $linearToRgb($b);

        try {
            return new 
Color(
                (int) 
round($r 255),
                (int) 
round($g 255),
                (int) 
round($b 255),
                
$color->alpha()->normalized(),
            );
        } catch (
InvalidArgumentException $e) {
            throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
                
previous$e,
            );
        }
    }

    
/**
     * Import given OKLCH color to RGB color space.
     *
     * @throws ColorException
     */
    
private function importOklchColor(OklchColor $color): RgbColor
    
{
        try {
            
$color $color->toColorspace(Oklab::class);
        } catch (
InvalidArgumentException $e) {
            throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
                
previous$e,
            );
        }

        if (!
$color instanceof OklabColor) {
            throw new 
ColorException(
                
'Failed to import color ' $color::class . ' to ' $this::class,
            );
        }

        return 
$this->importOklabColor($color);
    }

    
/**
     * Import given named color to RGB color space.
     *
     * @throws ColorException
     */
    
private function importNamedColor(NamedColor $color): RgbColor
    
{
        try {
            
$output InputHandler::usingDecoders([
                
HexColorDecoder::class,
            ])->
handle($color->toHex());
        } catch (
InvalidArgumentException NotSupportedException DriverException $e) {
            throw new 
ColorException('Failed to import named color to rgb color space'previous$e);
        }

        return 
$output instanceof RgbColor
            
$output
            
: throw new ColorException('Failed to import named color to rgb color space');
    }
}
Онлайн: 1
Реклама