Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
96 / 96
100.00% covered (success)
100.00%
22 / 22
CRAP
100.00% covered (success)
100.00%
1 / 1
Cmyk
100.00% covered (success)
100.00%
96 / 96
100.00% covered (success)
100.00%
22 / 22
51
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%
6 / 6
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%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __set
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __isset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __unset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetExists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
4
 offsetGet
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
6
 offsetSet
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
 offsetUnset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (https://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@noladev.com>
7 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC.
8 * @license    https://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Color\Color;
15
16use OutOfRangeException;
17
18/**
19 * Image CMYK color class
20 *
21 * @category   Pop
22 * @package    Pop\Image
23 * @author     Nick Sagona, III <dev@noladev.com>
24 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC.
25 * @license    https://www.popphp.org/license     New BSD License
26 * @version    1.0.2
27 */
28class Cmyk extends AbstractColor implements \ArrayAccess
29{
30
31    /**
32     * Cyan
33     * @var float
34     */
35    protected float $c = 0;
36
37    /**
38     * Magenta
39     * @var float
40     */
41    protected float $m = 0;
42
43    /**
44     * Yellow
45     * @var float
46     */
47    protected float $y = 0;
48
49    /**
50     * Black
51     * @var float
52     */
53    protected float $k = 0;
54
55    /**
56     * Constructor
57     *
58     * Instantiate a PERCENT CMYK Color object
59     *
60     * @param  mixed $c   0 - 100
61     * @param  mixed $m   0 - 100
62     * @param  mixed $y   0 - 100
63     * @param  mixed $k   0 - 100
64     */
65    public function __construct(mixed $c, mixed $m, mixed $y, mixed $k)
66    {
67        $this->setC($c);
68        $this->setM($m);
69        $this->setY($y);
70        $this->setK($k);
71    }
72
73    /**
74     * Set the cyan value
75     *
76     * @param  mixed $c
77     * @throws OutOfRangeException
78     * @return Cmyk
79     */
80    public function setC(mixed $c): Cmyk
81    {
82        $c = (float)$c;
83        if (($c < 0) || ($c > 100)) {
84            throw new OutOfRangeException('Error: The value must be between 0 and 100');
85        } else if ($c < 1) {
86            $c = (float)($c * 100);
87        }
88        $this->c = $c;
89        return $this;
90    }
91
92    /**
93     * Set the magenta value
94     *
95     * @param  mixed $m
96     * @throws OutOfRangeException
97     * @return Cmyk
98     */
99    public function setM(mixed $m): Cmyk
100    {
101        $m = (float)$m;
102        if (($m < 0) || ($m > 100)) {
103            throw new OutOfRangeException('Error: The value must be between 0 and 100');
104        } else if ($m < 1) {
105            $m = (float)($m * 100);
106        }
107        $this->m = $m;
108        return $this;
109    }
110
111    /**
112     * Set the yellow value
113     *
114     * @param  mixed $y
115     * @throws OutOfRangeException
116     * @return Cmyk
117     */
118    public function setY(mixed $y): Cmyk
119    {
120        $y = (float)$y;
121        if (((int)$y < 0) || ((int)$y > 100)) {
122            throw new OutOfRangeException('Error: The value must be between 0 and 100');
123        } else if ($y < 1) {
124            $y = (float)($y * 100);
125        }
126        $this->y = $y;
127        return $this;
128    }
129
130    /**
131     * Set the black value
132     *
133     * @param  mixed $k
134     * @throws OutOfRangeException
135     * @return Cmyk
136     */
137    public function setK(mixed $k): Cmyk
138    {
139        if (((int)$k < 0) || ((int)$k > 100)) {
140            throw new OutOfRangeException('Error: The value must be between 0 and 100');
141        } else if ($k < 1) {
142            $k = (float)($k * 100);
143        }
144        $this->k = $k;
145        return $this;
146    }
147
148    /**
149     * Get the cyan value
150     *
151     * @return float
152     */
153    public function getC(): float
154    {
155        return $this->c;
156    }
157
158    /**
159     * Get the magenta value
160     *
161     * @return float
162     */
163    public function getM(): float
164    {
165        return $this->m;
166    }
167
168    /**
169     * Get the yellow value
170     *
171     * @return float
172     */
173    public function getY(): float
174    {
175        return $this->y;
176    }
177
178    /**
179     * Get the black value
180     *
181     * @return float
182     */
183    public function getK(): float
184    {
185        return $this->k;
186    }
187
188    /**
189     * Convert to RGB
190     *
191     * @return Rgb
192     */
193    public function toRgb(): Rgb
194    {
195        // Calculate CMY.
196        $c = $this->c / 100;
197        $m = $this->m / 100;
198        $y = $this->y / 100;
199        $k = $this->k / 100;
200
201        $cyan    = (($c * (1 - $k)) + $k);
202        $magenta = (($m * (1 - $k)) + $k);
203        $yellow  = (($y * (1 - $k)) + $k);
204
205        // Calculate RGB.
206        $r = round((1 - $cyan) * 255);
207        $g = round((1 - $magenta) * 255);
208        $b = round((1 - $yellow) * 255);
209
210        return new Rgb($r, $g, $b);
211    }
212
213    /**
214     * Convert to Gray
215     *
216     * @return Grayscale
217     */
218    public function toGray(): Grayscale
219    {
220        return new Grayscale($this->k);
221    }
222
223    /**
224     * Convert to array
225     *
226     * @param  bool $assoc
227     * @return array
228     */
229    public function toArray(bool $assoc = true): array
230    {
231        $cmyk = [];
232
233        if ($assoc) {
234            $cmyk['c'] = $this->c;
235            $cmyk['m'] = $this->m;
236            $cmyk['y'] = $this->y;
237            $cmyk['k'] = $this->k;
238        } else {
239            $cmyk[] = $this->c;
240            $cmyk[] = $this->m;
241            $cmyk[] = $this->y;
242            $cmyk[] = $this->k;
243        }
244
245        return $cmyk;
246    }
247
248    /**
249     * Convert to readable string
250     *
251     * @param  ?string $format
252     * @return string
253     */
254    public function render(?string $format = null): string
255    {
256        if ($format == self::COMMA) {
257            return $this->c . ', ' . $this->m . ', ' . $this->y . ', ' . $this->k;
258        } else if ($format == self::CSS) {
259            $rgb = $this->toRgb();
260            return $rgb->render($format);
261        } else if ($format == self::PERCENT) {
262            return round(($this->c / 100), 2) . ' ' . round(($this->m / 100), 2) . ' ' .
263                round(($this->y / 100), 2) . ' ' . round(($this->k / 100), 2);
264        } else {
265            return $this->c . ' ' . $this->m . ' ' . $this->y . ' ' . $this->k;
266        }
267    }
268
269    /**
270     * Method to print the color object
271     *
272     * @return string
273     */
274    public function __toString()
275    {
276        return $this->render(self::PERCENT);
277    }
278
279    /**
280     * Magic method to set the color value
281     *
282     * @param  string $name
283     * @param  mixed  $value
284     * @throws Exception
285     * @return void
286     */
287    public function __set(string $name, mixed $value): void
288    {
289        $this->offsetSet($name, $value);
290    }
291
292    /**
293     * Magic method to return the color value
294     *
295     * @param  string $name
296     * @throws Exception
297     * @return mixed
298     */
299    public function __get(string $name): mixed
300    {
301        return $this->offsetGet($name);
302    }
303
304    /**
305     * Magic method to return whether the color value exists
306     *
307     * @param  string $name
308     * @return bool
309     */
310    public function __isset(string $name): bool
311    {
312        return $this->offsetExists($name);
313    }
314
315    /**
316     * Magic method to unset color value
317     *
318     * @param  string $name
319     * @throws Exception
320     * @return void
321     */
322    public function __unset(string $name): void
323    {
324        throw new Exception('You cannot unset the properties of this color object.');
325    }
326
327    /**
328     * ArrayAccess offsetExists
329     *
330     * @param  mixed $offset
331     * @return bool
332     */
333    public function offsetExists(mixed $offset): bool
334    {
335        return (($offset == 'c') || ($offset == 'm') || ($offset == 'y') || ($offset == 'm'));
336    }
337
338    /**
339     * ArrayAccess offsetGet
340     *
341     * @param  mixed $offset
342     * @throws Exception
343     * @return mixed
344     */
345    public function offsetGet(mixed $offset): mixed
346    {
347        switch ($offset) {
348            case 'c':
349                return $this->getC();
350                break;
351            case 'm':
352                return $this->getM();
353                break;
354            case 'y':
355                return $this->getY();
356                break;
357            case 'k':
358                return $this->getK();
359                break;
360            default:
361                throw new Exception("Error: You can only use 'c', 'm', 'y' or 'k'.");
362        }
363    }
364
365    /**
366     * ArrayAccess offsetSet
367     *
368     * @param  mixed $offset
369     * @param  mixed $value
370     * @throws Exception
371     * @return void
372     */
373    public function offsetSet(mixed $offset, mixed $value): void
374    {
375        switch ($offset) {
376            case 'c':
377                $this->setC($value);
378                break;
379            case 'm':
380                $this->setM($value);
381                break;
382            case 'y':
383                $this->setY($value);
384                break;
385            case 'k':
386                $this->setK($value);
387                break;
388            default:
389                throw new Exception("Error: You can only use 'c', 'm', 'y' or 'k'.");
390        }
391    }
392
393    /**
394     * ArrayAccess offsetUnset
395     *
396     * @param  mixed $offset
397     * @throws Exception
398     * @return void
399     */
400    public function offsetUnset(mixed $offset): void
401    {
402        throw new Exception('You cannot unset the properties of this color object.');
403    }
404
405}