网上有js生成DM码的库:
 
 
PHP版本的找了一些,都太重了,功能太多。
所以利用豆包根据这个js库生成了PHP版本的。
效果如下:
PHP代码如下:
<?php // 系统入口 date_default_timezone_set('PRC'); error_reporting(E_ALL^E_WARNING^E_NOTICE); set_time_limit(10); header('Content-Type: image/svg+xml'); /** * DataMatrix PHP Implementation * Based on datamatrix.js by Constantine (https://github.com/datalog/datamatrix-svg) * under MIT license */ class DATAMatrix { private $M = []; // Matrix to hold the datamatrix bits private $xx = 0; // Width of the matrix private $yy = 0; // Height of the matrix private $q = []; // Configuration array /** * Constructor * @param mixed $Q Optional string message or configuration array */ public function __construct($Q = '') { $this->q = []; // Initialize empty configuration $this->M = []; // Initialize empty matrix // If Q is provided, encode it if ($Q !== '') { $this->encodeMsg($Q); } } /** * Set a bit in the matrix * @param int $x X coordinate * @param int $y Y coordinate */ private function bit($x, $y) { if (!isset($this->M[$y])) { $this->M[$y] = []; } $this->M[$y][$x] = 1; } /** * Convert text to ASCII encoding * @param string $t Text to encode * @return array Encoded data */ private function toAscii($t) { $r = []; $l = strlen($t); for ($i = 0; $i < $l; $i++) { $c = ord($t[$i]); $c1 = ($i + 1 < $l) ? ord($t[$i + 1]) : 0; if ($c > 47 && $c < 58 && $c1 > 47 && $c1 < 58) { /* 2 digits */ $r[] = ($c - 48) * 10 + $c1 + 82; /* - 48 + 130 = 82 */ $i++; } else if ($c > 127) { /* extended char */ $r[] = 235; $r[] = ($c - 127) & 255; } else { $r[] = $c + 1; /* char */ } } return $r; } /** * Convert text to Base256 encoding * @param string $t Text to encode * @return array Encoded data */ private function toBase($t) { $r = [231]; /* switch to Base 256 */ $l = strlen($t); if (250 < $l) { $r[] = 37 + intval($l / 250) & 255; /* length high byte (in 255 state algo) */ } $r[] = ($l % 250 + 149 * (count($r) + 1) % 255 + 1) & 255; /* length low byte (in 255 state algo) */ for ($i = 0; $i < $l; $i++) { $r[] = (ord($t[$i]) + 149 * (count($r) + 1) % 255 + 1) & 255; /* data in 255 state algo */ } return $r; } /** * Convert text to Edifact encoding * @param string $t Text to encode * @return array Encoded data */ private function toEdifact($t) { $n = strlen($t); $l = ($n + 1) & -4; $cw = 0; $ch = 0; $r = ($l > 0) ? [240] : []; /* switch to Edifact */ for ($i = 0; $i < $l; $i++) { if ($i < $l - 1) { /* encode char */ $ch = ord($t[$i]); if ($ch < 32 || $ch > 94) return []; /* not in set */ } else { $ch = 31; /* return to ASCII */ } $cw = $cw * 64 + ($ch & 63); if (($i & 3) == 3) { /* 4 data in 3 words */ $r[] = $cw >> 16; $r[] = ($cw >> 8) & 255; $r[] = $cw & 255; $cw = 0; } } return $l > $n ? $r : array_merge($r, $this->toAscii(substr($t, $l == 0 ? 0 : $l - 1))); /* last chars*/ } /** * Convert text to C40/TEXT/X12 encoding * @param string $t Text to encode * @param array $s Character set definition * @return array Encoded data */ private function toText($t, $s) { $i = 0; $j = 0; $cc = 0; $cw = 0; $l = strlen($t); $r = [$s[0]]; /* start switch */ $push = function ($v) use (&$cc, &$cw, &$r, $s) { /* pack 3 chars in 2 codes */ $cw = 40 * $cw + $v; /* add code */ if ($cc++ == 2) { $r[] = ++$cw >> 8; $r[] = $cw & 255; $cc = $cw = 0; } }; for ($i = 0; $i < $l; $i++) { /* last char in ASCII is shorter */ if (0 == $cc && $i == $l - 1) break; $ch = ord($t[$i]); if ($ch > 127 && 238 != $r[0]) { /* extended char */ $push(1); $push(30); $ch -= 128; /* hi bit in C40 & TEXT */ } for ($j = 1; $ch > $s[$j]; $j += 3) { } /* select char set */ $x = $s[$j + 1]; /* shift */ if (8 == $x || (9 == $x && 0 == $cc && $i == $l - 1)) return []; /* char not in set or padding fails */ if ($x < 5 && $cc == 2 && $i == $l - 1) break; /* last char in ASCII */ if ($x < 5) $push($x); /* shift */ $push($ch - $s[$j + 2]); /* char offset */ } if (2 == $cc && 238 !== $r[0]) { /* add pad */ $push(0); } $r[] = 254; /* return to ASCII */ if ($cc > 0 || $i < $l) { $r = array_merge($r, $this->toAscii(substr($t, $i - $cc))); /* last chars */ } return $r; } /** * Encode message and generate matrix * @param mixed $Q String message or configuration array */ private function encodeMsg($Q) { // Store the original configuration for later use in getSVG if (is_string($Q)) { $this->q = ['msg' => $Q]; } else { // Ensure q is always an array $this->q = is_array($Q) ? $Q : []; } $q = $this->q; $text = rawurldecode(urlencode($q['msg'] ?? '')); $M = []; $enc = $this->toAscii($text); $el = count($enc); // Try C40 encoding $k = $this->toText($text, [ 230, 31, 0, 0, 32, 9, 29, 47, 1, 33, 57, 9, 44, 64, 1, 43, 90, 9, 51, 95, 1, 69, 127, 2, 96, 255, 1, 0 ]); $l = count($k); if ($l > 0 && $l < $el) { $enc = $k; $el = $l; } // Try TEXT encoding $k = $this->toText($text, [ 239, 31, 0, 0, 32, 9, 29, 47, 1, 33, 57, 9, 44, 64, 1, 43, 90, 2, 64, 95, 1, 69, 122, 9, 83, 127, 2, 96, 255, 1, 0 ]); $l = count($k); if ($l > 0 && $l < $el) { $enc = $k; $el = $l; } // Try X12 encoding $k = $this->toText($text, [ 238, 12, 8, 0, 13, 9, 13, 31, 8, 0, 32, 9, 29, 41, 8, 0, 42, 9, 41, 47, 8, 0, 57, 9, 44, 64, 8, 0, 90, 9, 51, 255, 8, 0 ]); $l = count($k); if ($l > 0 && $l < $el) { $enc = $k; $el = $l; } // Try Edifact encoding $k = $this->toEdifact($text); $l = count($k); if ($l > 0 && $l < $el) { $enc = $k; $el = $l; } // Try Base256 encoding $k = $this->toBase($text); $l = count($k); if ($l > 0 && $l < $el) { $enc = $k; $el = $l; } // Symbol size, regions, region size $h = 0; $w = 0; $nc = 1; $nr = 1; $fw = 0; $fh = 0; // Compute symbol size $i = 0; $j = -1; $c = 0; $r = 0; $s = 0; $b = 1; // Reed / solomon code $rs = array_fill(0, 70, 0); $rc = array_fill(0, 70, 0); // Log / exp table for multiplication $lg = array_fill(0, 256, 0); $ex = array_fill(0, 255, 0); $rct = isset($q['rct']) ? $q['rct'] : false; if ($rct && $el < 50) { // Rectangular symbols $k = [ 16, 7, 28, 11, 24, 14, 32, 18, 32, 24, 44, 28 ]; do { $w = $k[++$j]; /* width */ $h = 6 + ($j & 12); /* height */ $l = $w * $h / 8; /* bytes count in symbol */ } while ($l - $k[++$j] < $el); /* could we fill the rect? */ // Column regions if ($w > 25) { $nc = 2; } } else { // Square symbols $w = $h = 6; $i = 2; /* size increment */ $k = [5, 7, 10, 12, 14, 18, 20, 24, 28, 36, 42, 48, 56, 68, 84, 112, 144, 192, 224, 272, 336, 408, 496, 620]; /* rs checkwords */ do { if (++$j == count($k)) return [0, 0]; /* msg is too long */ if ($w > 11 * $i) { $i = 4 + $i & 12; /* advance increment */ } $w = $h += $i; $l = ($w * $h) >> 3; } while ($l - $k[$j] < $el); if ($w > 27) { $nr = $nc = 2 * intval($w / 54) + 2; /* regions */ } if ($l > 255) { $b = 2 * intval($l >> 9) + 2; /* blocks */ } } $s = $k[$j]; /* rs checkwords */ $fw = $w / $nc; /* region size */ $fh = $h / $nr; // First padding if ($el < $l - $s) { $enc[$el++] = 129; } // More padding while ($el < $l - $s) { $enc[$el++] = ((149 * $el) % 253 + 130) % 254; } // Reed Solomon error detection and correction $s /= $b; // Log / exp table of Galois field for ($j = 1, $i = 0; $i < 255; $i++) { $ex[$i] = $j; $lg[$j] = $i; $j += $j; if ($j > 255) { $j ^= 301; /* 301 == a^8 + a^5 + a^3 + a^2 + 1 */ } } // RS generator polynomial for ($rs[$s] = 0, $i = 1; $i <= $s; $i++) { for ($j = $s - $i, $rs[$j] = 1; $j < $s; $j++) { $rs[$j] = $rs[$j + 1] ^ $ex[($lg[$rs[$j]] + $i) % 255]; } } // RS correction data for each block for ($c = 0; $c < $b; $c++) { for ($i = 0; $i <= $s; $i++) { $rc[$i] = 0; } for ($i = $c; $i < $el; $i += $b) { for ($j = 0, $x = $rc[0] ^ $enc[$i]; $j < $s; $j++) { $rc[$j] = $rc[$j + 1] ^ ($x ? $ex[($lg[$rs[$j]] + $lg[$x]) % 255] : 0); } } // Interleaved correction data for ($i = 0; $i < $s; $i++) { $enc[$el + $c + $i * $b] = $rc[$i]; } } // Layout perimeter finder pattern // Horizontal for ($i = 0; $i < $h + 2 * $nr; $i += $fh + 2) { for ($j = 0; $j < $w + 2 * $nc; $j++) { $this->bit($j, $i + $fh + 1); if (($j & 1) == 0) { $this->bit($j, $i); } } } // Vertical for ($i = 0; $i < $w + 2 * $nc; $i += $fw + 2) { for ($j = 0; $j < $h; $j++) { $this->bit($i, $j + intval($j / $fh) * 2 + 1); if (($j & 1) == 1) { $this->bit($i + $fw + 1, $j + intval($j / $fh) * 2); } } } $s = 2; /* step */ $c = 0; /* column */ $r = 4; /* row */ $b = [ /* nominal byte layout */ 0, 0, -1, 0, -2, 0, 0, -1, -1, -1, -2, -1, -1, -2, -2, -2 ]; // Diagonal steps for ($i = 0; $i < $l; $r -= $s, $c += $s) { if ($r == $h - 3 && $c == -1) { $k = [ /* corner A layout */ $w, 6 - $h, $w, 5 - $h, $w, 4 - $h, $w, 3 - $h, $w - 1, 3 - $h, 3, 2, 2, 2, 1, 2 ]; } else if ($r == $h + 1 && $c == 1 && ($w & 7) == 0 && ($h & 7) == 6) { $k = [ /* corner D layout */ $w - 2, -$h, $w - 3, -$h, $w - 4, -$h, $w - 2, -1 - $h, $w - 3, -1 - $h, $w - 4, -1 - $h, $w - 2, -2, -1, -2 ]; } else { if ($r == 0 && $c == $w - 2 && ($w & 3)) continue; /* corner B: omit upper left */ if ($r < 0 || $c >= $w || $r >= $h || $c < 0) { /* outside */ $s = -$s; /* turn around */ $r += 2 + $s / 2; $c += 2 - $s / 2; while ($r < 0 || $c >= $w || $r >= $h || $c < 0) { $r -= $s; $c += $s; } } if ($r == $h - 2 && $c == 0 && ($w & 3)) { $k = [ /* corner B layout */ $w - 1, 3 - $h, $w - 1, 2 - $h, $w - 2, 2 - $h, $w - 3, 2 - $h, $w - 4, 2 - $h, 0, 1, 0, 0, 0, -1 ]; } else if ($r == $h - 2 && $c == 0 && ($w & 7) == 4) { $k = [ /* corner C layout */ $w - 1, 5 - $h, $w - 1, 4 - $h, $w - 1, 3 - $h, $w - 1, 2 - $h, $w - 2, 2 - $h, 0, 1, 0, 0, 0, -1 ]; } else if ($r == 1 && $c == $w - 1 && ($w & 7) == 0 && ($h & 7) == 6) { continue; /* omit corner D */ } else { $k = $b; /* nominal L - shape layout */ } } // Layout each bit for ($el_val = $enc[$i++], $j = 0; $el_val > 0; $j += 2, $el_val >>= 1) { if ($el_val & 1) { $x = $c + $k[$j]; $y = $r + $k[$j + 1]; // Wrap around if ($x < 0) { $x += $w; $y += 4 - (($w + 4) & 7); } if ($y < 0) { $y += $h; $x += 4 - (($h + 4) & 7); } // Region gap $this->bit($x + 2 * intval($x / $fw) + 1, $y + 2 * intval($y / $fh) + 1); } } } // Unfilled corner for ($i = $w; $i & 3; $i--) { $this->bit($i, $i); } $this->xx = $w + 2 * $nc; $this->yy = $h + 2 * $nr; } /** * Check if a color is a valid hex color * @param string $c Color string * @return bool True if valid hex color */ private function isHex($c) { return preg_match('/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i', $c) === 1; } /** * Generate SVG representation of the datamatrix * @param array $options Optional additional options to override instance configuration * @return string SVG string */ public function getSVG($options = []) { $q = array_merge($this->q, $options); $p = $q['pal'] ?? ['#000']; $dm = abs($q['dim'] ?? 0) ?: 256; // Use padding from options if provided, otherwise from q config or default to 2 $pd = isset($q['pad']) ? abs($q['pad']) : 2; $mx = [1, 0, 0, 1, $pd, $pd]; $fg = $p[0]; $fg = $this->isHex($fg) ? $fg : '#000'; // 处理背景色,支持透明背景 $bg = isset($p[1]) ? $p[1] : ''; // 如果背景色是'transparent'或者不是有效的十六进制颜色,则设置为透明(不添加背景矩形) $transparentBg = $bg === 'transparent' || !$this->isHex($bg); $bgColor = $this->isHex($bg) ? $bg : ''; // Render optimized or verbose svg $optimized = empty($q['vrb']) ? 1 : 0; $sx = $this->xx + $pd * 2; $sy = $this->yy + $pd * 2; $path = ''; $y = $this->yy; while ($y--) { $d = 0; $x = $this->xx; while ($x--) { if (isset($this->M[$y][$x]) && $this->M[$y][$x]) { if ($optimized) { $d++; if (!isset($this->M[$y][$x - 1]) || !$this->M[$y][$x - 1]) { $path .= 'M' . $x . ',' . $y . 'h' . $d . 'v1h-' . $d . 'v-1z'; $d = 0; } } else { $path .= 'M' . $x . ',' . $y . 'h1v1h-1v-1z'; } } } } $svg = '<svg viewBox="0 0 ' . $sx . ' ' . $sy . '" width="' . (int)($dm / $sy * $sx) . '" height="' . $dm . '" fill="' . $fg . '" shape-rendering="crispEdges" xmlns="http://www.w3.org/2000/svg" version="1.1">'; // 只有当不是透明背景且有有效的背景色时才添加背景矩形 if (!$transparentBg && $bgColor) { $svg .= '<path fill="' . $bgColor . '" d="M0,0v' . $sy . 'h' . $sx . 'V0H0Z"/>'; } $svg .= '<path transform="matrix(' . implode(',', $mx) . ')" d="' . $path . '"/>'; $svg .= '</svg>'; return $svg; } /** * Static method to create a DataMatrix * @param mixed $Q String message or configuration array * @return string SVG string */ public static function create($Q) { // Create a new instance with the configuration $dm = new self(); // Explicitly encode the message with the configuration $dm->encodeMsg($Q); // If Q is an array, pass it directly to getSVG to ensure all parameters are used if (is_array($Q)) { return $dm->getSVG($Q); } return $dm->getSVG(); } } // 调用示例 echo '<?xml version="1.0" encoding="UTF-8"?>'; $config = array( 'msg' => $_GET['content'] ?? 'NULL', // 内容 'dim' => $_GET['size'] ?? 256, // 尺寸(高度) 'pad' => $_GET['padding'] ?? 2, // 内边距 //'pal' => array('#000000', '#ffffff'), // 颜色调色板(前景色、背景色) 'rct' => $_GET['rect'] ?? 0 // 是否使用矩形格式(默认正方形) ); $color = $_GET['color'] ?? ''; if (!empty($color)){ $color = explode(',', $color); $color = array_map(function($c) { return '#' . $c; }, $color); $config['pal'] = $color; } $svg_custom = DATAMatrix::create($config); echo $svg_custom;
欢迎转载,转载请注明:转载自[ http://www.cnblogs.com/zjfree/ ]
 
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号