Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
66 / 66
100.00% covered (success)
100.00%
15 / 15
CRAP
100.00% covered (success)
100.00%
1 / 1
Cmyk
100.00% covered (success)
100.00%
66 / 66
100.00% covered (success)
100.00%
15 / 15
32
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 setC
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 setM
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 setY
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 setK
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getC
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getM
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getY
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getK
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toRgb
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 toGray
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 render
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
5
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 channels
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Color\Color;
16
17use OutOfRangeException;
18
19/**
20 * Image CMYK color class
21 *
22 * @category   Pop
23 * @package    Pop\Image
24 * @author     Nick Sagona, III <nick@popphp.org>
25 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
26 * @license    https://www.popphp.org/license     New BSD License
27 * @version    2.0.0
28 */
29class Cmyk extends AbstractColor
30{
31
32    /**
33     * Cyan
34     * @var float
35     */
36    protected float $c = 0;
37
38    /**
39     * Magenta
40     * @var float
41     */
42    protected float $m = 0;
43
44    /**
45     * Yellow
46     * @var float
47     */
48    protected float $y = 0;
49
50    /**
51     * Black
52     * @var float
53     */
54    protected float $k = 0;
55
56    /**
57     * Constructor
58     *
59     * Instantiate a PERCENT CMYK Color object
60     *
61     * @param  mixed $c   0 - 100
62     * @param  mixed $m   0 - 100
63     * @param  mixed $y   0 - 100
64     * @param  mixed $k   0 - 100
65     */
66    public function __construct(mixed $c, mixed $m, mixed $y, mixed $k)
67    {
68        $this->setC($c);
69        $this->setM($m);
70        $this->setY($y);
71        $this->setK($k);
72    }
73
74    /**
75     * Set the cyan value
76     *
77     * @param  mixed $c
78     * @throws OutOfRangeException
79     * @return Cmyk
80     */
81    public function setC(mixed $c): Cmyk
82    {
83        $c = (float)$c;
84        if (($c < 0) || ($c > 100)) {
85            throw new OutOfRangeException('Error: The value must be between 0 and 100');
86        } else if ($c <= 1) {
87            $c = (float)($c * 100);
88        }
89        $this->c = $c;
90        return $this;
91    }
92
93    /**
94     * Set the magenta value
95     *
96     * @param  mixed $m
97     * @throws OutOfRangeException
98     * @return Cmyk
99     */
100    public function setM(mixed $m): Cmyk
101    {
102        $m = (float)$m;
103        if (($m < 0) || ($m > 100)) {
104            throw new OutOfRangeException('Error: The value must be between 0 and 100');
105        } else if ($m <= 1) {
106            $m = (float)($m * 100);
107        }
108        $this->m = $m;
109        return $this;
110    }
111
112    /**
113     * Set the yellow value
114     *
115     * @param  mixed $y
116     * @throws OutOfRangeException
117     * @return Cmyk
118     */
119    public function setY(mixed $y): Cmyk
120    {
121        $y = (float)$y;
122        if (($y < 0) || ($y > 100)) {
123            throw new OutOfRangeException('Error: The value must be between 0 and 100');
124        } else if ($y <= 1) {
125            $y = (float)($y * 100);
126        }
127        $this->y = $y;
128        return $this;
129    }
130
131    /**
132     * Set the black value
133     *
134     * @param  mixed $k
135     * @throws OutOfRangeException
136     * @return Cmyk
137     */
138    public function setK(mixed $k): Cmyk
139    {
140        $k = (float)$k;
141        if (($k < 0) || ($k > 100)) {
142            throw new OutOfRangeException('Error: The value must be between 0 and 100');
143        } else if ($k <= 1) {
144            $k = (float)($k * 100);
145        }
146        $this->k = $k;
147        return $this;
148    }
149
150    /**
151     * Get the cyan value
152     *
153     * @return float
154     */
155    public function getC(): float
156    {
157        return $this->c;
158    }
159
160    /**
161     * Get the magenta value
162     *
163     * @return float
164     */
165    public function getM(): float
166    {
167        return $this->m;
168    }
169
170    /**
171     * Get the yellow value
172     *
173     * @return float
174     */
175    public function getY(): float
176    {
177        return $this->y;
178    }
179
180    /**
181     * Get the black value
182     *
183     * @return float
184     */
185    public function getK(): float
186    {
187        return $this->k;
188    }
189
190    /**
191     * Convert to RGB
192     *
193     * @return Rgb
194     */
195    public function toRgb(): Rgb
196    {
197        // Calculate CMY.
198        $c = $this->c / 100;
199        $m = $this->m / 100;
200        $y = $this->y / 100;
201        $k = $this->k / 100;
202
203        $cyan    = (($c * (1 - $k)) + $k);
204        $magenta = (($m * (1 - $k)) + $k);
205        $yellow  = (($y * (1 - $k)) + $k);
206
207        // Calculate RGB.
208        $r = (int)round((1 - $cyan) * 255);
209        $g = (int)round((1 - $magenta) * 255);
210        $b = (int)round((1 - $yellow) * 255);
211
212        return new Rgb($r, $g, $b);
213    }
214
215    /**
216     * Convert to Gray
217     *
218     * @return Grayscale
219     */
220    public function toGray(): Grayscale
221    {
222        return new Grayscale($this->k);
223    }
224
225    /**
226     * Convert to array
227     *
228     * @param  bool $assoc
229     * @return array
230     */
231    public function toArray(bool $assoc = true): array
232    {
233        $cmyk = [];
234
235        if ($assoc) {
236            $cmyk['c'] = $this->c;
237            $cmyk['m'] = $this->m;
238            $cmyk['y'] = $this->y;
239            $cmyk['k'] = $this->k;
240        } else {
241            $cmyk[] = $this->c;
242            $cmyk[] = $this->m;
243            $cmyk[] = $this->y;
244            $cmyk[] = $this->k;
245        }
246
247        return $cmyk;
248    }
249
250    /**
251     * Convert to readable string
252     *
253     * @param  ?string $format
254     * @return string
255     */
256    public function render(?string $format = null): string
257    {
258        return match ($format) {
259            self::COMMA => $this->c . ', ' . $this->m . ', ' . $this->y . ', ' . $this->k,
260            self::CSS => $this->toRgb()->render($format),
261            self::PERCENT => round(($this->c / 100), 2) . ' ' . round(($this->m / 100), 2) . ' ' .
262                round(($this->y / 100), 2) . ' ' . round(($this->k / 100), 2),
263            default => $this->c . ' ' . $this->m . ' ' . $this->y . ' ' . $this->k,
264        };
265    }
266
267    /**
268     * Method to print the color object
269     *
270     * @return string
271     */
272    public function __toString()
273    {
274        return $this->render(self::PERCENT);
275    }
276
277    /**
278     * Get the valid channel names
279     *
280     * @return array
281     */
282    protected function channels(): array
283    {
284        return ['c', 'm', 'y', 'k'];
285    }
286
287}