Passed
Push — master ( 4f783c...449b2c )
by Paul
07:14
created

PixelAvatar::addBody()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 7
c 1
b 0
f 1
dl 0
loc 9
ccs 0
cts 9
cp 0
rs 10
cc 3
nc 3
nop 0
crap 12
1
<?php
2
3
/**
4
 * Adapted from: https://github.com/BinaryMoon/wp-toolbelt/tree/master/modules/avatars
5
 * @see: https://www.binarymoon.co.uk/2020/08/pixel-avatars-a-privacy-first-gravatar-replacement/
6
 */
7
8
namespace GeminiLabs\SiteReviews\Modules;
9
10
class PixelAvatar
11
{
12
    const HEIGHT = 11;
13
    const WIDTH = 11;
14
15
    /**
16
     * @var array
17
     */
18
    public $data;
19
20
    /**
21
     * @var string
22
     */
23
    public $hash;
24
25
    /**
26
     * @var int
27
     */
28
    public $hashIndex = 0;
29
30
    /**
31
     * @var array
32
     */
33
    public $pixels = [
34
        'palette' => [
35
            'all' => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 215, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350],
36
            'skin' => [60, 80, 100, 120, 140, 160, 180, 220, 240, 280, 300, 320, 340],
37
        ],
38
        'face' => [
39
            [
40
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
41
                [0, 0, 2, 1, 9, 1, 9, 1, 2, 0, 0],
42
                [0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0],
43
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
44
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
45
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
46
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
47
            ],
48
            [
49
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
50
                [0, 0, 2, 1, 9, 1, 9, 1, 2, 0, 0],
51
                [0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0],
52
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
53
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
54
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
55
                [0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0],
56
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
57
            ],
58
            [
59
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
60
                [0, 0, 2, 1, 9, 1, 9, 1, 2, 0, 0],
61
                [0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0],
62
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
63
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
64
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
65
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
66
            ],
67
            [
68
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
69
                [0, 2, 1, 1, 9, 1, 9, 1, 1, 2, 0],
70
                [0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0],
71
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
72
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
73
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
74
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
75
            ],
76
            [
77
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
78
                [0, 0, 2, 1, 9, 1, 9, 1, 2, 0, 0],
79
                [0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0],
80
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
81
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
82
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
83
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
84
            ],
85
            [
86
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
87
                [0, 0, 2, 1, 9, 1, 9, 1, 2, 0, 0],
88
                [0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0],
89
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
90
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
91
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
92
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
93
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
94
            ],
95
            [
96
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
97
                [0, 0, 2, 1, 9, 1, 9, 1, 2, 0, 0],
98
                [0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0],
99
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
100
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
101
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
102
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
103
            ],
104
        ],
105
        'mouth' => [
106
            [1, 1, 1],
107
            [1, 1, 1],
108
            [1, 1, 1],
109
            [0, 1, 0],
110
            [0, 1, 1],
111
            [1, 1, 0],
112
        ],
113
        'body' => [
114
            [
115
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
116
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
117
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
118
            ],
119
            [
120
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
121
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
122
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
123
            ],
124
            [
125
                [0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0],
126
                [0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0],
127
                [0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0],
128
            ],
129
            [
130
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
131
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
132
                [0, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0],
133
            ],
134
            [
135
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
136
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
137
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
138
            ],
139
            [
140
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
141
                [0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0],
142
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
143
            ],
144
            [
145
                [0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0],
146
                [0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0],
147
                [0, 0, 1, 1, 1, 2, 1, 1, 1, 0, 0],
148
            ],
149
            [
150
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
151
                [0, 0, 1, 2, 1, 2, 1, 2, 1, 0, 0],
152
                [0, 0, 1, 2, 1, 2, 1, 2, 1, 0, 0],
153
            ],
154
            [
155
                [0, 0, 0, 0, 2, 9, 2, 0, 0, 0, 0],
156
                [0, 0, 1, 1, 1, 9, 1, 1, 1, 0, 0],
157
                [0, 0, 1, 1, 1, 9, 1, 1, 1, 0, 0],
158
            ],
159
        ],
160
        'hair' => [
161
            [
162
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
163
            ],
164
            [
165
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
166
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
167
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
168
            ],
169
            [
170
                [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
171
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
172
                [0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0],
173
            ],
174
            [
175
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
176
                [0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0],
177
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
178
            ],
179
            [
180
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
181
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
182
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
183
                [0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0],
184
            ],
185
            [
186
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
187
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
188
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
189
                [0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0],
190
            ],
191
            [
192
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
193
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
194
                [0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0],
195
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
196
            ],
197
            [
198
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
199
                [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
200
                [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0],
201
            ],
202
            [
203
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
204
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
205
                [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0],
206
            ],
207
            [
208
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
209
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
210
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
211
                [0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0],
212
            ],
213
            [
214
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
215
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
216
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
217
                [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
218
                [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
219
            ],
220
            [
221
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
222
                [0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0],
223
                [0, 0, 0, 1, 2, 1, 2, 1, 0, 0, 0],
224
                [0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0],
225
            ],
226
            [
227
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
228
                [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
229
                [0, 0, 0, 0, 2, 2, 2, 1, 0, 0, 0],
230
                [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
231
            ],
232
            [
233
                [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0],
234
                [0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0],
235
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
236
            ],
237
            [
238
                [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
239
                [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0],
240
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
241
            ],
242
            [
243
                [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
244
                [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
245
                [0, 0, 0, 1, 2, 2, 2, 0, 0, 0, 0],
246
                [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
247
            ],
248
            [
249
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
250
                [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
251
                [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
252
            ],
253
            [
254
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
255
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
256
                [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0],
257
            ],
258
            [
259
                [0, 0, 0, 8, 1, 1, 1, 0, 0, 0, 0],
260
                [0, 0, 0, 1, 8, 1, 1, 1, 0, 0, 0],
261
                [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0],
262
            ],
263
            [
264
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
265
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
266
                [0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0],
267
                [0, 1, 1, 2, 0, 0, 0, 2, 1, 1, 0],
268
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
269
                [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
270
            ],
271
            [
272
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
273
                [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0],
274
                [0, 0, 1, 2, 2, 1, 2, 2, 1, 0, 0],
275
                [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
276
            ],
277
            [
278
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
279
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
280
                [0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0],
281
                [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
282
                [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
283
                [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
284
            ],
285
            [
286
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
287
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
288
                [0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0],
289
            ],
290
            [
291
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
292
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
293
                [0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0],
294
                [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
295
            ],
296
            [
297
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
298
                [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
299
                [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
300
                [0, 0, 1, 2, 0, 0, 0, 2, 1, 0, 0],
301
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
302
                [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
303
            ],
304
            [
305
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
306
                [0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0],
307
                [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
308
                [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
309
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
310
                [0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
311
            ],
312
        ],
313
    ];
314
315
    /**
316
     * @param string $hash
317
     * @return string
318
     */
319
    public function generate($hash)
320
    {
321
        $this->data = $this->newData();
322
        $this->hash = $hash;
323
        $this->hashIndex = 0;
324
        $this->addBody();
325
        $this->addFace();
326
        $this->addMouth();
327
        $this->addHair();
328
        return $this->draw();
329
    }
330
331
    /**
332
     * @return void
333
     */
334
    protected function addBody()
335
    {
336
        $color = $this->getColor(50, 45);
337
        $pixels = $this->getPixels('body');
338
        $yOffset = 8;
339
        for ($y = 0; $y < static::HEIGHT - $yOffset; ++$y) {
340
            for ($x = 0; $x < static::WIDTH; ++$x) {
341
                $pixelColor = $this->setPixelColour($pixels[$y][$x], $this->data[$y + $yOffset][$x], $color);
342
                $this->data[$y + $yOffset][$x] = $pixelColor;
343
            }
344
        }
345
    }
346
347
    /**
348
     * @return void
349
     */
350
    protected function addFace()
351
    {
352
        $color = $this->getColor(40, 65, 'skin');
353
        $pixels = $this->getPixels('face');
354
        $numPixels = count($pixels);
355
        $yOffset = 3;
356
        for ($y = 0; $y < $numPixels; ++$y) {
357
            for ($x = 0; $x < static::WIDTH; ++$x) {
358
                $pixelColor = $this->setPixelColour($pixels[$y][$x], $this->data[$y + $yOffset][$x], $color);
359
                $this->data[$y + $yOffset][$x] = $pixelColor;
360
            }
361
        }
362
    }
363
364
    /**
365
     * @return void
366
     */
367
    protected function addHair()
368
    {
369
        $color = $this->getColor(70, 45);
370
        $pixels = $this->getPixels('hair');
371
        $numPixels = count($pixels);
372
        for ($y = 0; $y < $numPixels; ++$y) {
373
            for ($x = 0; $x < static::WIDTH; ++$x) {
374
                $pixelColor = $this->setPixelColour($pixels[$y][$x], $this->data[$y][$x], $color);
375
                $this->data[$y][$x] = $pixelColor;
376
            }
377
        }
378
    }
379
380
    /**
381
     * @return void
382
     */
383
    protected function addMouth()
384
    {
385
        $color = $this->getColor(60, 30);
386
        $pixels = $this->getPixels('mouth');
387
        if (1 === $pixels[0]) {
388
            $this->data[6][4] = $color[0];
389
        }
390
        if (1 === $pixels[1]) {
391
            $this->data[6][5] = $color[0];
392
        }
393
        if (1 === $pixels[2]) {
394
            $this->data[6][6] = $color[0];
395
        }
396
    }
397
398
    /**
399
     * @return string
400
     */
401
    protected function draw()
402
    {
403
        $paths = [];
404
        $background = $this->getColor(85, 85);
405
        $commands = [];
406
        $commands[$background[0]] = sprintf('M0 0h%dv%dH0z', static::WIDTH, static::HEIGHT);
407
        for ($y = 0; $y < static::HEIGHT; ++$y) {
408
            for ($x = 0; $x < static::WIDTH; ++$x) {
409
                if ($fill = $this->data[$y][$x]) {
410
                    if (!isset($commands[$fill])) {
411
                        $commands[$fill] = '';
412
                    }
413
                    $commands[$fill] .= sprintf('M%d %dh1v1H%dz', $x, $y, $x);
414
                }
415
            }
416
        }
417
        foreach ($commands as $fill => $d) {
418
            $paths[] = sprintf('<path fill="%s" d="%s"/>', $fill, $d);
419
        }
420
        return sprintf('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d">%s</svg>',
421
            static::WIDTH,
422
            static::HEIGHT,
423
            implode('', $paths)
424
        );
425
    }
426
427
    /**
428
     * @param int $saturation
429
     * @param int $lightness
430
     * @param string $paletteKey
431
     * @return array
432
     * @see https://www.w3schools.com/colors/colors_hsl.asp
433
     */
434
    protected function getColor($saturation, $lightness, $paletteKey = 'all')
435
    {
436
        $palette = $this->pixels['palette'][$paletteKey];
437
        $index = $this->stringVal() % count($palette);
438
        $hue = $palette[$index];
439
        return [
440
            $this->hslToHex($hue, $saturation / 100, $lightness / 100),
441
            $this->hslToHex($hue, ($saturation + 10) / 100, ($lightness - 20) / 100),
442
        ];
443
    }
444
445
    /**
446
     * @param string $name
447
     * @return array
448
     */
449
    protected function getPixels($name)
450
    {
451
        $index = $this->stringVal() % count($this->pixels[$name]);
452
        return $this->pixels[$name][$index];
453
    }
454
455
    /**
456
     * @param float $hue
457
     * @param float $saturation
458
     * @param float $lightness
459
     * @return string
460
     */
461
    protected function hslToHex($hue, $saturation, $lightness)
462
    {
463
        $hue = $hue / 360;
464
        if (0 == $saturation) {
465
            $red = $green = $blue = $lightness; // achromatic
466
        } else {
467
            if ($lightness < 0.5) {
468
                $v2 = $lightness * (1 + $saturation);
469
            } else {
470
                $v2 = ($lightness + $saturation) - ($lightness * $saturation);
471
            }
472
            $v1 = 2 * $lightness - $v2;
473
            $red = $this->hueToRgb($v1, $v2, $hue + (1 / 3));
474
            $green = $this->hueToRgb($v1, $v2, $hue);
475
            $blue = $this->hueToRgb($v1, $v2, $hue - (1 / 3));
476
        }
477
        $red = (int) round($red * 255);
478
        $green = (int) round($green * 255);
479
        $blue = (int) round($blue * 255);
480
        return '#'.str_pad(dechex(($red << 16) + ($green << 8) + $blue), 6, '0', STR_PAD_LEFT);
481
    }
482
483
    /**
484
     * @param float $v1
485
     * @param float $v2
486
     * @param float $vH
487
     * @return float
488
     */
489
    protected function hueToRgb($v1, $v2, $vH)
490
    {
491
        if ($vH < 0) {
492
            ++$vH;
493
        }
494
        if ($vH > 1) {
495
            --$vH;
496
        }
497
        if ($vH < (1 / 6)) {
498
            return $v1 + ($v2 - $v1) * 6 * $vH;
499
        }
500
        if ($vH < (1 / 2)) {
501
            return $v2;
502
        }
503
        if ($vH < (2 / 3)) {
504
            return $v1 + ($v2 - $v1) * ((2 / 3) - $vH) * 6;
505
        }
506
        return $v1;
507
    }
508
509
    /**
510
     * @return array
511
     */
512
    protected function newData()
513
    {
514
        $data = [];
515
        for ($y = 0; $y < static::HEIGHT; ++$y) {
516
            $data[$y] = [];
517
            for ($x = 0; $x < static::WIDTH; ++$x) {
518
                $data[$y][$x] = null;
519
            }
520
        }
521
        return $data;
522
    }
523
524
    /**
525
     * @param int $pixel
526
     * @param string $current
527
     * @param array $palette
528
     * @return string
529
     */
530
    protected function setPixelColour($pixel, $current, $palette)
531
    {
532
        $color = $current;
533
        switch ($pixel) {
534
            case 1:
535
                $color = $palette[0];
536
                break;
537
            case 2:
538
                $color = $palette[1];
539
                break;
540
            case 8:
541
                $color = '#fff';
542
                break;
543
            case 9:
544
                $color = '#000';
545
                break;
546
        }
547
        return $color;
548
    }
549
550
    /**
551
     * Get the value of the next character in the hash.
552
     * @return int
553
     */
554
    protected function stringVal()
555
    {
556
        ++$this->hashIndex;
557
        $this->hashIndex = $this->hashIndex % strlen($this->hash);
558
        return ord($this->hash[$this->hashIndex]) + (ord("\0") << 8);
559
    }
560
}
561