Issues (459)

src/image/DigitalLED74.php (1 issue)

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Image;
8
9
use Amenadiel\JpGraph\Util;
10
11
/*
12
 * File:        JPGRAPH_LED.PHP
13
 * // Description: Module to generate Dotted LED-like digits
14
 * // Created:     2006-11-26
15
 * // Ver:         $Id: jpgraph_led.php 1674 2009-07-22 19:42:23Z ljp $
16
 * //
17
 * // Copyright 2006 (c) Asial Corporation. All rights reserved.
18
 * //
19
 * // Changed: 2007-08-06 by Alexander Kurochkin ([email protected])
20
 */
21
// Constants for color schema
22
define('LEDC_RED', 0);
23
define('LEDC_GREEN', 1);
24
define('LEDC_BLUE', 2);
25
define('LEDC_YELLOW', 3);
26
define('LEDC_GRAY', 4);
27
define('LEDC_CHOCOLATE', 5);
28
define('LEDC_PERU', 6);
29
define('LEDC_GOLDENROD', 7);
30
define('LEDC_KHAKI', 8);
31
define('LEDC_OLIVE', 9);
32
define('LEDC_LIMEGREEN', 10);
33
define('LEDC_FORESTGREEN', 11);
34
define('LEDC_TEAL', 12);
35
define('LEDC_STEELBLUE', 13);
36
define('LEDC_NAVY', 14);
37
define('LEDC_INVERTGRAY', 15);
38
39
// Check that mb_strlen() is available
40
if (!function_exists('mb_strlen')) {
41
    Util\JpGraphError::RaiseL(25500);
42
    //'Multibyte strings must be enabled in the PHP installation in order to run the LED module
43
    // so that the function mb_strlen() is available. See PHP documentation for more information.'
44
}
45
46
/**
47
 * @class DigitalLED74
48
 * // Description:
49
 * // Construct a number as an image that looks like LED numbers in a
50
 * // 7x4 digital matrix
51
 */
52
class DigitalLED74
53
{
54
    private $iLED_X       = 4;
55
    private $iLED_Y       = 7;
56
    private $iColorSchema = [
57
        LEDC_RED         => ['red', 'darkred:0.9', 'red:0.3'], // 0
58
        LEDC_GREEN       => ['green', 'darkgreen', 'green:0.3'], // 1
59
        LEDC_BLUE        => ['lightblue:0.9', 'darkblue:0.85', 'darkblue:0.7'], // 2
60
        LEDC_YELLOW      => ['yellow', 'yellow:0.4', 'yellow:0.3'], // 3
61
        LEDC_GRAY        => ['gray:1.4', 'darkgray:0.85', 'darkgray:0.7'],
62
        LEDC_CHOCOLATE   => ['chocolate', 'chocolate:0.7', 'chocolate:0.5'],
63
        LEDC_PERU        => ['peru:0.95', 'peru:0.6', 'peru:0.5'],
64
        LEDC_GOLDENROD   => ['goldenrod', 'goldenrod:0.6', 'goldenrod:0.5'],
65
        LEDC_KHAKI       => ['khaki:0.7', 'khaki:0.4', 'khaki:0.3'],
66
        LEDC_OLIVE       => ['#808000', '#808000:0.7', '#808000:0.6'],
67
        LEDC_LIMEGREEN   => ['limegreen:0.9', 'limegreen:0.5', 'limegreen:0.4'],
68
        LEDC_FORESTGREEN => ['forestgreen', 'forestgreen:0.7', 'forestgreen:0.5'],
69
        LEDC_TEAL        => ['teal', 'teal:0.7', 'teal:0.5'],
70
        LEDC_STEELBLUE   => ['steelblue', 'steelblue:0.65', 'steelblue:0.5'],
71
        LEDC_NAVY        => ['navy:1.3', 'navy:0.95', 'navy:0.8'], //14
72
        LEDC_INVERTGRAY  => ['darkgray', 'lightgray:1.5', 'white'], //15
73
    ];
74
    private $iLEDSpec = [
75
        0    => [6, 9, 11, 15, 13, 9, 6],
76
        1    => [2, 6, 10, 2, 2, 2, 2],
77
        2    => [6, 9, 1, 2, 4, 8, 15],
78
        3    => [6, 9, 1, 6, 1, 9, 6],
79
        4    => [1, 3, 5, 9, 15, 1, 1],
80
        5    => [15, 8, 8, 14, 1, 9, 6],
81
        6    => [6, 8, 8, 14, 9, 9, 6],
82
        7    => [15, 1, 1, 2, 4, 4, 4],
83
        8    => [6, 9, 9, 6, 9, 9, 6],
84
        9    => [6, 9, 9, 7, 1, 1, 6],
85
        '!'  => [4, 4, 4, 4, 4, 0, 4],
86
        '?'  => [6, 9, 1, 2, 2, 0, 2],
87
        '#'  => [0, 9, 15, 9, 15, 9, 0],
88
        '@'  => [6, 9, 11, 11, 10, 9, 6],
89
        '-'  => [0, 0, 0, 15, 0, 0, 0],
90
        '_'  => [0, 0, 0, 0, 0, 0, 15],
91
        '='  => [0, 0, 15, 0, 15, 0, 0],
92
        '+'  => [0, 0, 4, 14, 4, 0, 0],
93
        '|'  => [4, 4, 4, 4, 4, 4, 4], //vertical line, used for simulate rus 'Ы'
94
        ','  => [0, 0, 0, 0, 0, 12, 4],
95
        '.'  => [0, 0, 0, 0, 0, 12, 12],
96
        ':'  => [12, 12, 0, 0, 0, 12, 12],
97
        ';'  => [12, 12, 0, 0, 0, 12, 4],
98
        '['  => [3, 2, 2, 2, 2, 2, 3],
99
        ']'  => [12, 4, 4, 4, 4, 4, 12],
100
        '('  => [1, 2, 2, 2, 2, 2, 1],
101
        ')'  => [8, 4, 4, 4, 4, 4, 8],
102
        '{'  => [3, 2, 2, 6, 2, 2, 3],
103
        '}'  => [12, 4, 4, 6, 4, 4, 12],
104
        '<'  => [1, 2, 4, 8, 4, 2, 1],
105
        '>'  => [8, 4, 2, 1, 2, 4, 8],
106
        '*'  => [9, 6, 15, 6, 9, 0, 0],
107
        '"'  => [10, 10, 0, 0, 0, 0, 0],
108
        '\'' => [4, 4, 0, 0, 0, 0, 0],
109
        '`'  => [4, 2, 0, 0, 0, 0, 0],
110
        '~'  => [13, 11, 0, 0, 0, 0, 0],
111
        '^'  => [4, 10, 0, 0, 0, 0, 0],
112
        '\\' => [8, 8, 4, 6, 2, 1, 1],
113
        '/'  => [1, 1, 2, 6, 4, 8, 8],
114
        '%'  => [1, 9, 2, 6, 4, 9, 8],
115
        '&'  => [0, 4, 10, 4, 11, 10, 5],
116
        '$'  => [2, 7, 8, 6, 1, 14, 4],
117
        ' '  => [0, 0, 0, 0, 0, 0, 0],
118
        '•'  => [0, 0, 6, 6, 0, 0, 0], //149
119
        '°'  => [14, 10, 14, 0, 0, 0, 0], //176
120
        '†'  => [4, 4, 14, 4, 4, 4, 4], //134
121
        '‡'  => [4, 4, 14, 4, 14, 4, 4], //135
122
        '±'  => [0, 4, 14, 4, 0, 14, 0], //177
123
        '‰'  => [0, 4, 2, 15, 2, 4, 0], //137 show right arrow
124
        '™'  => [0, 2, 4, 15, 4, 2, 0], //156 show left arrow
125
        'Ў'  => [0, 0, 8, 8, 0, 0, 0], //159 show small hi-stick - that need for simulate rus 'Ф'
126
        "\t" => [8, 8, 8, 0, 0, 0, 0], //show hi-stick - that need for simulate rus 'У'
127
        "\r" => [8, 8, 8, 8, 8, 8, 8], //vertical line - that need for simulate 'M', 'W' and rus 'М','Ш' ,'Щ'
128
        "\n" => [15, 15, 15, 15, 15, 15, 15], //fill up - that need for simulate rus 'Ж'
129
        'Ґ'  => [10, 5, 10, 5, 10, 5, 10], //chess
130
        'µ'  => [15, 0, 15, 0, 15, 0, 15], //4 horizontal lines
131
        // latin
132
        'A'  => [6, 9, 9, 15, 9, 9, 9],
133
        'B'  => [14, 9, 9, 14, 9, 9, 14],
134
        'C'  => [6, 9, 8, 8, 8, 9, 6],
135
        'D'  => [14, 9, 9, 9, 9, 9, 14],
136
        'E'  => [15, 8, 8, 14, 8, 8, 15],
137
        'F'  => [15, 8, 8, 14, 8, 8, 8],
138
        'G'  => [6, 9, 8, 8, 11, 9, 6],
139
        'H'  => [9, 9, 9, 15, 9, 9, 9],
140
        'I'  => [14, 4, 4, 4, 4, 4, 14],
141
        'J'  => [15, 1, 1, 1, 1, 9, 6],
142
        'K'  => [8, 9, 10, 12, 12, 10, 9],
143
        'L'  => [8, 8, 8, 8, 8, 8, 15],
144
        'M'  => [8, 13, 10, 8, 8, 8, 8], // need to add \r
145
        'N'  => [9, 9, 13, 11, 9, 9, 9],
146
        'O'  => [6, 9, 9, 9, 9, 9, 6],
147
        'P'  => [14, 9, 9, 14, 8, 8, 8],
148
        'Q'  => [6, 9, 9, 9, 13, 11, 6],
149
        'R'  => [14, 9, 9, 14, 12, 10, 9],
150
        'S'  => [6, 9, 8, 6, 1, 9, 6],
151
        'T'  => [14, 4, 4, 4, 4, 4, 4],
152
        'U'  => [9, 9, 9, 9, 9, 9, 6],
153
        'V'  => [0, 0, 0, 10, 10, 10, 4],
154
        'W'  => [8, 8, 8, 8, 10, 13, 8], // need to add \r
155
        'X'  => [9, 9, 6, 6, 6, 9, 9],
156
        'Y'  => [10, 10, 10, 10, 4, 4, 4],
157
        'Z'  => [15, 1, 2, 6, 4, 8, 15],
158
        // russian utf-8
159
        'А'  => [6, 9, 9, 15, 9, 9, 9],
160
        'Б'  => [14, 8, 8, 14, 9, 9, 14],
161
        'В'  => [14, 9, 9, 14, 9, 9, 14],
162
        'Г'  => [15, 8, 8, 8, 8, 8, 8],
163
        'Д'  => [14, 9, 9, 9, 9, 9, 14],
164
        'Е'  => [15, 8, 8, 14, 8, 8, 15],
165
        'Ё'  => [6, 15, 8, 14, 8, 8, 15],
166
        //Ж is combine: >\n<
167
        'З'  => [6, 9, 1, 2, 1, 9, 6],
168
        'И'  => [9, 9, 9, 11, 13, 9, 9],
169
        'Й'  => [13, 9, 9, 11, 13, 9, 9],
170
        'К'  => [9, 10, 12, 10, 9, 9, 9],
171
        'Л'  => [7, 9, 9, 9, 9, 9, 9],
172
        'М'  => [8, 13, 10, 8, 8, 8, 8], // need to add \r
173
        'Н'  => [9, 9, 9, 15, 9, 9, 9],
174
        'О'  => [6, 9, 9, 9, 9, 9, 6],
175
        'П'  => [15, 9, 9, 9, 9, 9, 9],
176
        'Р'  => [14, 9, 9, 14, 8, 8, 8],
177
        'С'  => [6, 9, 8, 8, 8, 9, 6],
178
        'Т'  => [14, 4, 4, 4, 4, 4, 4],
179
        'У'  => [9, 9, 9, 7, 1, 9, 6],
180
        'Ф'  => [2, 7, 10, 10, 7, 2, 2], // need to add Ў
181
        'Х'  => [9, 9, 6, 6, 6, 9, 9],
182
        'Ц'  => [10, 10, 10, 10, 10, 15, 1],
183
        'Ч'  => [9, 9, 9, 7, 1, 1, 1],
184
        'Ш'  => [10, 10, 10, 10, 10, 10, 15], // \r
185
        'Щ'  => [10, 10, 10, 10, 10, 15, 0], // need to add \r
186
        'Ъ'  => [12, 4, 4, 6, 5, 5, 6],
187
        'Ы'  => [8, 8, 8, 14, 9, 9, 14], // need to add |
188
        'Ь'  => [8, 8, 8, 14, 9, 9, 14],
189
        'Э'  => [6, 9, 1, 7, 1, 9, 6],
190
        'Ю'  => [2, 2, 2, 3, 2, 2, 2], // need to add O
191
        'Я'  => [7, 9, 9, 7, 3, 5, 9],
192
    ];
193
    private $iSuperSampling = 3;
194
    private $iMarg          = 1;
195
    private $iRad           = 4;
196
197
    public function __construct($aRadius = 2, $aMargin = 0.6)
198
    {
199
        $this->iRad  = $aRadius;
200
        $this->iMarg = $aMargin;
201
    }
202
203
    public function SetSupersampling($aSuperSampling = 2)
204
    {
205
        $this->iSuperSampling = $aSuperSampling;
206
    }
207
208
    public function _GetLED($aLedIdx, $aColor = 0)
209
    {
210
        $width  = $this->iLED_X * $this->iRad * 2 + ($this->iLED_X + 1) * $this->iMarg + $this->iRad;
211
        $height = $this->iLED_Y * $this->iRad * 2 + ($this->iLED_Y) * $this->iMarg + $this->iRad * 2;
212
213
        // Adjust radious for supersampling
214
        $rad = $this->iRad * $this->iSuperSampling;
215
216
        // Margin in between "Led" dots
217
        $marg = $this->iMarg * $this->iSuperSampling;
218
219
        $swidth  = $width * $this->iSuperSampling;
220
        $sheight = $height * $this->iSuperSampling;
221
222
        $simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false);
223
        $simg->SetColor($this->iColorSchema[$aColor][2]);
224
        $simg->FilledRectangle(0, 0, $swidth - 1, $sheight - 1);
225
226
        if (array_key_exists($aLedIdx, $this->iLEDSpec)) {
227
            $d = $this->iLEDSpec[$aLedIdx];
228
        } else {
229
            $d = [0, 0, 0, 0, 0, 0, 0];
230
        }
231
232
        for ($r = 0; $r < 7; ++$r) {
233
            $dr = $d[$r];
234
            for ($c = 0; $c < 4; ++$c) {
235
                if (($dr & pow(2, 3 - $c)) !== 0) {
236
                    $color = $this->iColorSchema[$aColor][0];
237
                } else {
238
                    $color = $this->iColorSchema[$aColor][1];
239
                }
240
241
                $x = 2 * $rad * $c + $rad + ($c + 1) * $marg + $rad;
242
                $y = 2 * $rad * $r + $rad + ($r + 1) * $marg + $rad;
243
244
                $simg->SetColor($color);
245
                $simg->FilledCircle($x, $y, $rad);
246
            }
247
        }
248
249
        $img = new Image($width, $height, DEFAULT_GFORMAT, false);
250
        $img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight);
251
        $simg->Destroy();
252
        unset($simg);
253
254
        return $img;
255
    }
256
257
    public function Stroke($aValStr, $aColor = 0, $aFileName = '')
258
    {
259
        $this->StrokeNumber($aValStr, $aColor, $aFileName);
260
    }
261
262
    public function StrokeNumber($aValStr, $aColor = 0, $aFileName = '')
263
    {
264
        if ($aColor < 0 || $aColor >= safe_count($this->iColorSchema)) {
265
            $aColor = 0;
266
        }
267
268
        if (($n = mb_strlen($aValStr, 'utf8')) == 0) {
269
            $aValStr = ' ';
270
            $n       = 1;
271
        }
272
273
        for ($i = 0; $i < $n; ++$i) {
274
            $d = mb_substr($aValStr, $i, 1, 'utf8');
275
            if (ctype_digit($d)) {
276
                $d = (int) $d;
277
            } else {
278
                $d = strtoupper($d);
279
            }
280
            $digit_img[$i] = $this->_GetLED($d, $aColor);
281
        }
282
283
        $w = imagesx($digit_img[0]->img);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $digit_img does not seem to be defined for all execution paths leading up to this point.
Loading history...
284
        $h = imagesy($digit_img[0]->img);
285
286
        $number_img = new Image\Image($w * $n, $h, DEFAULT_GFORMAT, false);
287
288
        for ($i = 0; $i < $n; ++$i) {
289
            $number_img->Copy($digit_img[$i]->img, $i * $w, 0, 0, 0, $w, $h, $w, $h);
290
        }
291
292
        if ($aFileName != '') {
293
            $number_img->Stream($aFileName);
294
        } else {
295
            $number_img->Headers();
296
            $number_img->Stream();
297
        }
298
    }
299
}
300