src/image/DigitalLED74.php
<?php
/**
* JPGraph v4.0.3
*/
namespace Amenadiel\JpGraph\Image;
use Amenadiel\JpGraph\Util;
/*
* File: JPGRAPH_LED.PHP
* // Description: Module to generate Dotted LED-like digits
* // Created: 2006-11-26
* // Ver: $Id: jpgraph_led.php 1674 2009-07-22 19:42:23Z ljp $
* //
* // Copyright 2006 (c) Asial Corporation. All rights reserved.
* //
* // Changed: 2007-08-06 by Alexander Kurochkin (inspector@list.ru)
*/
// Constants for color schema
define('LEDC_RED', 0);
define('LEDC_GREEN', 1);
define('LEDC_BLUE', 2);
define('LEDC_YELLOW', 3);
define('LEDC_GRAY', 4);
define('LEDC_CHOCOLATE', 5);
define('LEDC_PERU', 6);
define('LEDC_GOLDENROD', 7);
define('LEDC_KHAKI', 8);
define('LEDC_OLIVE', 9);
define('LEDC_LIMEGREEN', 10);
define('LEDC_FORESTGREEN', 11);
define('LEDC_TEAL', 12);
define('LEDC_STEELBLUE', 13);
define('LEDC_NAVY', 14);
define('LEDC_INVERTGRAY', 15);
// Check that mb_strlen() is available
if (!function_exists('mb_strlen')) {
Util\JpGraphError::RaiseL(25500);
//'Multibyte strings must be enabled in the PHP installation in order to run the LED module
// so that the function mb_strlen() is available. See PHP documentation for more information.'
}
/**
* @class DigitalLED74
* // Description:
* // Construct a number as an image that looks like LED numbers in a
* // 7x4 digital matrix
*/
class DigitalLED74
{
private $iLED_X = 4;
private $iLED_Y = 7;
private $iColorSchema = [
LEDC_RED => ['red', 'darkred:0.9', 'red:0.3'], // 0
LEDC_GREEN => ['green', 'darkgreen', 'green:0.3'], // 1
LEDC_BLUE => ['lightblue:0.9', 'darkblue:0.85', 'darkblue:0.7'], // 2
LEDC_YELLOW => ['yellow', 'yellow:0.4', 'yellow:0.3'], // 3
LEDC_GRAY => ['gray:1.4', 'darkgray:0.85', 'darkgray:0.7'],
LEDC_CHOCOLATE => ['chocolate', 'chocolate:0.7', 'chocolate:0.5'],
LEDC_PERU => ['peru:0.95', 'peru:0.6', 'peru:0.5'],
LEDC_GOLDENROD => ['goldenrod', 'goldenrod:0.6', 'goldenrod:0.5'],
LEDC_KHAKI => ['khaki:0.7', 'khaki:0.4', 'khaki:0.3'],
LEDC_OLIVE => ['#808000', '#808000:0.7', '#808000:0.6'],
LEDC_LIMEGREEN => ['limegreen:0.9', 'limegreen:0.5', 'limegreen:0.4'],
LEDC_FORESTGREEN => ['forestgreen', 'forestgreen:0.7', 'forestgreen:0.5'],
LEDC_TEAL => ['teal', 'teal:0.7', 'teal:0.5'],
LEDC_STEELBLUE => ['steelblue', 'steelblue:0.65', 'steelblue:0.5'],
LEDC_NAVY => ['navy:1.3', 'navy:0.95', 'navy:0.8'], //14
LEDC_INVERTGRAY => ['darkgray', 'lightgray:1.5', 'white'], //15
];
private $iLEDSpec = [
0 => [6, 9, 11, 15, 13, 9, 6],
1 => [2, 6, 10, 2, 2, 2, 2],
2 => [6, 9, 1, 2, 4, 8, 15],
3 => [6, 9, 1, 6, 1, 9, 6],
4 => [1, 3, 5, 9, 15, 1, 1],
5 => [15, 8, 8, 14, 1, 9, 6],
6 => [6, 8, 8, 14, 9, 9, 6],
7 => [15, 1, 1, 2, 4, 4, 4],
8 => [6, 9, 9, 6, 9, 9, 6],
9 => [6, 9, 9, 7, 1, 1, 6],
'!' => [4, 4, 4, 4, 4, 0, 4],
'?' => [6, 9, 1, 2, 2, 0, 2],
'#' => [0, 9, 15, 9, 15, 9, 0],
'@' => [6, 9, 11, 11, 10, 9, 6],
'-' => [0, 0, 0, 15, 0, 0, 0],
'_' => [0, 0, 0, 0, 0, 0, 15],
'=' => [0, 0, 15, 0, 15, 0, 0],
'+' => [0, 0, 4, 14, 4, 0, 0],
'|' => [4, 4, 4, 4, 4, 4, 4], //vertical line, used for simulate rus 'Ы'
',' => [0, 0, 0, 0, 0, 12, 4],
'.' => [0, 0, 0, 0, 0, 12, 12],
':' => [12, 12, 0, 0, 0, 12, 12],
';' => [12, 12, 0, 0, 0, 12, 4],
'[' => [3, 2, 2, 2, 2, 2, 3],
']' => [12, 4, 4, 4, 4, 4, 12],
'(' => [1, 2, 2, 2, 2, 2, 1],
')' => [8, 4, 4, 4, 4, 4, 8],
'{' => [3, 2, 2, 6, 2, 2, 3],
'}' => [12, 4, 4, 6, 4, 4, 12],
'<' => [1, 2, 4, 8, 4, 2, 1],
'>' => [8, 4, 2, 1, 2, 4, 8],
'*' => [9, 6, 15, 6, 9, 0, 0],
'"' => [10, 10, 0, 0, 0, 0, 0],
'\'' => [4, 4, 0, 0, 0, 0, 0],
'`' => [4, 2, 0, 0, 0, 0, 0],
'~' => [13, 11, 0, 0, 0, 0, 0],
'^' => [4, 10, 0, 0, 0, 0, 0],
'\\' => [8, 8, 4, 6, 2, 1, 1],
'/' => [1, 1, 2, 6, 4, 8, 8],
'%' => [1, 9, 2, 6, 4, 9, 8],
'&' => [0, 4, 10, 4, 11, 10, 5],
'$' => [2, 7, 8, 6, 1, 14, 4],
' ' => [0, 0, 0, 0, 0, 0, 0],
'•' => [0, 0, 6, 6, 0, 0, 0], //149
'°' => [14, 10, 14, 0, 0, 0, 0], //176
'†' => [4, 4, 14, 4, 4, 4, 4], //134
'‡' => [4, 4, 14, 4, 14, 4, 4], //135
'±' => [0, 4, 14, 4, 0, 14, 0], //177
'‰' => [0, 4, 2, 15, 2, 4, 0], //137 show right arrow
'™' => [0, 2, 4, 15, 4, 2, 0], //156 show left arrow
'Ў' => [0, 0, 8, 8, 0, 0, 0], //159 show small hi-stick - that need for simulate rus 'Ф'
"\t" => [8, 8, 8, 0, 0, 0, 0], //show hi-stick - that need for simulate rus 'У'
"\r" => [8, 8, 8, 8, 8, 8, 8], //vertical line - that need for simulate 'M', 'W' and rus 'М','Ш' ,'Щ'
"\n" => [15, 15, 15, 15, 15, 15, 15], //fill up - that need for simulate rus 'Ж'
'Ґ' => [10, 5, 10, 5, 10, 5, 10], //chess
'µ' => [15, 0, 15, 0, 15, 0, 15], //4 horizontal lines
// latin
'A' => [6, 9, 9, 15, 9, 9, 9],
'B' => [14, 9, 9, 14, 9, 9, 14],
'C' => [6, 9, 8, 8, 8, 9, 6],
'D' => [14, 9, 9, 9, 9, 9, 14],
'E' => [15, 8, 8, 14, 8, 8, 15],
'F' => [15, 8, 8, 14, 8, 8, 8],
'G' => [6, 9, 8, 8, 11, 9, 6],
'H' => [9, 9, 9, 15, 9, 9, 9],
'I' => [14, 4, 4, 4, 4, 4, 14],
'J' => [15, 1, 1, 1, 1, 9, 6],
'K' => [8, 9, 10, 12, 12, 10, 9],
'L' => [8, 8, 8, 8, 8, 8, 15],
'M' => [8, 13, 10, 8, 8, 8, 8], // need to add \r
'N' => [9, 9, 13, 11, 9, 9, 9],
'O' => [6, 9, 9, 9, 9, 9, 6],
'P' => [14, 9, 9, 14, 8, 8, 8],
'Q' => [6, 9, 9, 9, 13, 11, 6],
'R' => [14, 9, 9, 14, 12, 10, 9],
'S' => [6, 9, 8, 6, 1, 9, 6],
'T' => [14, 4, 4, 4, 4, 4, 4],
'U' => [9, 9, 9, 9, 9, 9, 6],
'V' => [0, 0, 0, 10, 10, 10, 4],
'W' => [8, 8, 8, 8, 10, 13, 8], // need to add \r
'X' => [9, 9, 6, 6, 6, 9, 9],
'Y' => [10, 10, 10, 10, 4, 4, 4],
'Z' => [15, 1, 2, 6, 4, 8, 15],
// russian utf-8
'А' => [6, 9, 9, 15, 9, 9, 9],
'Б' => [14, 8, 8, 14, 9, 9, 14],
'В' => [14, 9, 9, 14, 9, 9, 14],
'Г' => [15, 8, 8, 8, 8, 8, 8],
'Д' => [14, 9, 9, 9, 9, 9, 14],
'Е' => [15, 8, 8, 14, 8, 8, 15],
'Ё' => [6, 15, 8, 14, 8, 8, 15],
//Ж is combine: >\n<
'З' => [6, 9, 1, 2, 1, 9, 6],
'И' => [9, 9, 9, 11, 13, 9, 9],
'Й' => [13, 9, 9, 11, 13, 9, 9],
'К' => [9, 10, 12, 10, 9, 9, 9],
'Л' => [7, 9, 9, 9, 9, 9, 9],
'М' => [8, 13, 10, 8, 8, 8, 8], // need to add \r
'Н' => [9, 9, 9, 15, 9, 9, 9],
'О' => [6, 9, 9, 9, 9, 9, 6],
'П' => [15, 9, 9, 9, 9, 9, 9],
'Р' => [14, 9, 9, 14, 8, 8, 8],
'С' => [6, 9, 8, 8, 8, 9, 6],
'Т' => [14, 4, 4, 4, 4, 4, 4],
'У' => [9, 9, 9, 7, 1, 9, 6],
'Ф' => [2, 7, 10, 10, 7, 2, 2], // need to add Ў
'Х' => [9, 9, 6, 6, 6, 9, 9],
'Ц' => [10, 10, 10, 10, 10, 15, 1],
'Ч' => [9, 9, 9, 7, 1, 1, 1],
'Ш' => [10, 10, 10, 10, 10, 10, 15], // \r
'Щ' => [10, 10, 10, 10, 10, 15, 0], // need to add \r
'Ъ' => [12, 4, 4, 6, 5, 5, 6],
'Ы' => [8, 8, 8, 14, 9, 9, 14], // need to add |
'Ь' => [8, 8, 8, 14, 9, 9, 14],
'Э' => [6, 9, 1, 7, 1, 9, 6],
'Ю' => [2, 2, 2, 3, 2, 2, 2], // need to add O
'Я' => [7, 9, 9, 7, 3, 5, 9],
];
private $iSuperSampling = 3;
private $iMarg = 1;
private $iRad = 4;
public function __construct($aRadius = 2, $aMargin = 0.6)
{
$this->iRad = $aRadius;
$this->iMarg = $aMargin;
}
public function SetSupersampling($aSuperSampling = 2)
{
$this->iSuperSampling = $aSuperSampling;
}
public function _GetLED($aLedIdx, $aColor = 0)
{
$width = $this->iLED_X * $this->iRad * 2 + ($this->iLED_X + 1) * $this->iMarg + $this->iRad;
$height = $this->iLED_Y * $this->iRad * 2 + ($this->iLED_Y) * $this->iMarg + $this->iRad * 2;
// Adjust radious for supersampling
$rad = $this->iRad * $this->iSuperSampling;
// Margin in between "Led" dots
$marg = $this->iMarg * $this->iSuperSampling;
$swidth = $width * $this->iSuperSampling;
$sheight = $height * $this->iSuperSampling;
$simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false);
$simg->SetColor($this->iColorSchema[$aColor][2]);
$simg->FilledRectangle(0, 0, $swidth - 1, $sheight - 1);
if (array_key_exists($aLedIdx, $this->iLEDSpec)) {
$d = $this->iLEDSpec[$aLedIdx];
} else {
$d = [0, 0, 0, 0, 0, 0, 0];
}
for ($r = 0; $r < 7; ++$r) {
$dr = $d[$r];
for ($c = 0; $c < 4; ++$c) {
if (($dr & pow(2, 3 - $c)) !== 0) {
$color = $this->iColorSchema[$aColor][0];
} else {
$color = $this->iColorSchema[$aColor][1];
}
$x = 2 * $rad * $c + $rad + ($c + 1) * $marg + $rad;
$y = 2 * $rad * $r + $rad + ($r + 1) * $marg + $rad;
$simg->SetColor($color);
$simg->FilledCircle($x, $y, $rad);
}
}
$img = new Image($width, $height, DEFAULT_GFORMAT, false);
$img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight);
$simg->Destroy();
unset($simg);
return $img;
}
public function Stroke($aValStr, $aColor = 0, $aFileName = '')
{
$this->StrokeNumber($aValStr, $aColor, $aFileName);
}
public function StrokeNumber($aValStr, $aColor = 0, $aFileName = '')
{
if ($aColor < 0 || $aColor >= safe_count($this->iColorSchema)) {
$aColor = 0;
}
if (($n = mb_strlen($aValStr, 'utf8')) == 0) {
$aValStr = ' ';
$n = 1;
}
for ($i = 0; $i < $n; ++$i) {
$d = mb_substr($aValStr, $i, 1, 'utf8');
if (ctype_digit($d)) {
$d = (int) $d;
} else {
$d = strtoupper($d);
}
$digit_img[$i] = $this->_GetLED($d, $aColor);
}
$w = imagesx($digit_img[0]->img);
$h = imagesy($digit_img[0]->img);
$number_img = new Image\Image($w * $n, $h, DEFAULT_GFORMAT, false);
for ($i = 0; $i < $n; ++$i) {
$number_img->Copy($digit_img[$i]->img, $i * $w, 0, 0, 0, $w, $h, $w, $h);
}
if ($aFileName != '') {
$number_img->Stream($aFileName);
} else {
$number_img->Headers();
$number_img->Stream();
}
}
}