Mon code-barres. Code128

Une fois en cours d'activité de production, j'ai eu un besoin de générer un code barre selon la norme code128. Cela est dû au fait que la fonction utilisée (une procédure stockée dans la base de données Oracle) générait un code-barres cool et rayé qui n'était pas lisible dans tous les cas. Les développeurs ont un temps très mal testé cette procédure, mais ils n'allaient plus la recycler. le projet était achevé depuis longtemps, mais le besoin de lecture ne s'est pas fait sentir.





La première pensée est de rechercher des bibliothèques toutes faites. Dès la sortie de la boîte, nous avons défini les critères - nous ne contactons pas pl/sql, que ce soit un service externe : peut-être un morceau de javascript à générer directement sur la page, ou une demande d'image au serveur le plus proche où php est disponible. Une recherche rapide sur Internet a montré que le sujet était piétiné de très près. Il existe à la fois des objets artisanaux à hauteur de genou du niveau d'un laboratoire de programmation, ainsi que de puissantes bibliothèques pour toutes les options de codage, jusqu'aux codes QR. Les options JavaScript ont dû être supprimées car d'une part, ils sont presque tous "obscurcis" (c'est même incompréhensible, soit pour réduire le volume, soit c'est dommage de montrer le code source), et d'autre part, ils génèrent une chaîne pour afficher dans une certaine police, la présence dont ne peut pas toujours être fourni sur le site client et nécessite un traitement supplémentaire échappant aux caractères spéciaux.Une étude minutieuse des bibliothèques et des morceaux de code php a également fait une impression douloureuse - à première vue, tout semble être correct : les cours sont écrits pour toutes les occasions, les commentaires sont disponibles, les décorations telles que le choix des couleurs et des cadres, des exemples ont été préparés . Vous commencerez à approfondir - ils veulent soit le php de la version la plus récente (il n'est pas toujours possible de l'obtenir sur les serveurs de combat), soit la logique interne n'est pas du tout discernable, ou le code-barres de sortie s'avère être plus long que attendu. Voici les derniers hantés et poussés à leur propre réalisation.Vous commencerez à approfondir - ils veulent soit le php de la version la plus récente (il n'est pas toujours possible de l'obtenir sur les serveurs de combat), soit la logique interne n'est pas du tout discernable, ou le code-barres de sortie s'avère être plus long que attendu. Voici les derniers hantés et poussés à leur propre réalisation.Vous commencerez à approfondir - ils veulent soit le php de la version la plus récente (il n'est pas toujours possible de l'obtenir sur les serveurs de combat), soit la logique interne n'est pas du tout discernable, soit le code-barres de sortie s'avère être plus long que attendu. Voici les derniers hantés et poussés à leur propre réalisation.





Il est temps d'avoir une idée de la théorie. Au contraire, nous l'avons rencontrée beaucoup plus tôt, nous ne voulions tout simplement pas nous impliquer dans une programmation supplémentaire jusqu'à récemment. On omettra les faits historiques, mais une très bonne description technique est disponible sur http://code128.narod.ru/ (le fichier Descript.doc est dans l'archive ) ou sur Wikipedia. En principe, c'est tout ce dont nous avons besoin pour comprendre et implémenter notre propre algorithme (ici, je suis un peu rusé - vous devez extraire les tables de largeurs de trait de n'importe quelle bibliothèque prête à l'emploi afin de ne pas les introduire manuellement). Eh bien, nous allons écrire toute cette honte en php, en même temps, nous verrons quelques moments sympas que tout le monde oublie ou est gêné d'utiliser.





, code128 (!) 128 , 3 , . «B» - «» , — 2 . php- — «». .





— , . - . — . , .





. «ABC12DE» , B, - B :





- 1 . , 6 . — , , — ? , , .





, — () . . — , () ( 2- «»). , , ! «B» «C» - :)





, - B , . — , , . , :





<?php

class code128 {
    private $code = '';
    private $leafB = NULL, $leafC = NULL;

    public function __construct($text, $mode = 'B')
    {
			if (strlen($text) == 0) return NULL;

			$this->mode = $mode;

			if ($mode == 'B') {
	    		$this->code = substr($text, 0, 1);
	    		$text = substr($text, 1);
			}
			else if ($mode == 'C') {
	    		if (strlen($text) < 2) return NULL;
	    		if (!is_numeric($text[0])) return NULL;
	    		if (!is_numeric($text[1])) return NULL;

	    		$this->code = substr($text, 0, 2);
	    		$text = substr($text, 2);
			}
			else	
	    		return NULL;

			$this->leafB = new code128($text, 'B');
			$this->leafC = new code128($text, 'C');
    }

    public function draw()
    {
				echo "Code [" . $this->code . "]\n";
				if ($this->leafB != NULL) $this->leafB->draw();
				if ($this->leafC != NULL) $this->leafC->draw();
    }
}

    $n = new code128('s92317lsdfa4324', 'B');
    $n->draw();
?>
      
      



— "" . NULL! , php . - . . :





    public function __construct($text, $mode = 'B')
    {
			$this->mode = $mode;

			if ($mode == 'B') {
	    		$this->code = substr($text, 0, 1);
	    		$text = substr($text, 1);
			}
			else if ($mode == 'C') {
	    		$this->code = substr($text, 0, 2);
	    		$text = substr($text, 2);
			}

			if(strlen($text)>0) $this->leafB = new code128($text, 'B');
			if(strlen($text)>1)
	    		if(is_numeric($text[0]) && is_numeric($text[1])) $this->leafC = new code128($text, 'C');
    }

      
      



, , . - : , , .. . code128? , , , :





	if($mode == 'B') list($this->code, $text) = sscanf($text, '%c%s');
	if($mode == 'C') list($this->code, $text) = sscanf($text, '%2d%s');

	if(strlen($text)>0)
	    if(array_key_exists(substr($text, 0, 1), $symCode)) $this->leafB = new code128($text, 'B', $this);
	if(strlen($text)>1)
	    if(array_key_exists(substr($text, 0, 2), $symCode)) $this->leafC = new code128($text, 'C', $this);
      
      



$symCode - , tables.php require . - => .





$symCode = array(
/*	alphabet B	alphabet C */
	' ' => 0,	'00' => 0,
	'!' => 1,	'01' => 1,
	'"' => 2,	'02' => 2,
	'#' => 3,	'03' => 3,
	'$' => 4,	'04' => 4,
	'%' => 5,	'05' => 5,
	'&' => 6,	'06' => 6,

      
      



, . : - . ( ), . — 1, 1 2 . 2? . . . ? — « » . — . — , , . — , . , - :)





require 'tables.php';

class code128 {
    private $code = NULL;
    private $text = '';
    private $mode = 'Auto';
    private $len = 1;
    private $leafB = NULL, $leafC = NULL, $parent = NULL, $minCode = NULL;

    public function __construct($text, $mode = 'Auto', $parent = NULL)
    {
			global $symCode;
			$this->parent = $parent;
			$this->text = $text;
			$this->mode = $mode;

			if($parent != NULL) {
	    		$this->len = $this->parent->len + 1;
	    		if($this->parent->mode != $mode) $this->len++;
	     }

	    if($mode == 'B') list($this->code, $text) = sscanf($text, '%c%s');
	    if($mode == 'C') list($this->code, $text) = sscanf($text, '%2d%s');

	    if(strlen($text)>0)
	       if(array_key_exists(substr($text, 0, 1), $symCode)) $this->leafB = new code128($text, 'B', $this);
	    if(strlen($text)>1)
	       if(array_key_exists(substr($text, 0, 2), $symCode)) $this->leafC = new code128($text, 'C', $this);

	    if($this->leafB == NULL && $this->leafC == NULL) $this->minCode = $this;
	    else {
	       $this->minCode = ($this->leafB != NULL) ? $this->leafB->minCode : $this->leafC->minCode;
	       if($this->leafC != NULL)
		        if($this->minCode->len > $this->leafC->minCode->len) $this->minCode = $this->leafC->minCode;
	    }

	    return $this;
     }

      
      



, - (). . : . , , (push) . , PHP , .





 private function getCode()
 {
		$stack = array();
		$p = $this->minCode;

		while($p != NULL) {
	    	array_push($stack, $p->code);

	    	if($p->parent != NULL) {
						if($p->parent->mode == 'Auto') { array_push($stack, 'Start'.$p->mode); break;}
						if($p->mode != $p->parent->mode) array_push($stack, 'Code'.$p->mode);
	    	}

	    	$p = $p->parent;
		}

		return $stack;
  }
      
      



— array_pop. , . — // .





- , . . SVG. — , . , , dpi .





  private function printPattern($code, $posX, $res, $height)
  {
		for($i = 0; $i < strlen($code); $i++) {
	    	$w = $res*intval($code[$i]);

	    	if(!($i%2))
						echo "  <rect x='$posX' y='0' width='$w' height='$height' fill='#0'/>\n";

	    	$posX += $w;
			}

			return $posX;
   }

   public function printSVG($resolution=1, $height=50)
   {
			global $symCode;
			global $barPattern;

			$s = $this->getCode();

			$pos = 1;
			$offset = $resolution*11;
			$width = ((count($s) + 4)*11 + 2)*$resolution;

			echo "<svg xmlns='http://www.w3.org/2000/svg' width='$width' height='$height'>\n";

			$start = $symCode[array_pop($s)];
			$checksum = $start;

			$offset = $this->printPattern($barPattern[$start], $offset, $resolution, $height);

			while(!empty($s)) {
	    		$code = $symCode[array_pop($s)];
	    		$offset = $this->printPattern($barPattern[$code], $offset, $resolution, $height);
	    		$checksum += $code*$pos;
	    		$pos++;
			}

			$offset = $this->printPattern($barPattern[$checksum%103], $offset, $resolution, $height);
			$offset = $this->printPattern($barPattern[$symCode['Stop']], $offset, $resolution, $height);

			echo "</svg>\n";
    }

      
      



$barPattern. tables.php $symCode. . - :





$barPattern = array(
	'212222',	/* 0 */
	'222122',	/* 1 */
	'222221',	/* 2 */
	'121223',	/* 3 */
	'121322',	/* 4 */
      
      



? :





    header('Content-Type: image/svg+xml');
    echo "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n\n";

    $n = new code128(html_entity_decode($_SERVER["QUERY_STRING"]));
    $n->printSVG();
      
      



, html- :





<img src="barcode128.php?ad32324adsFAE13413ldsFf">
      
      



Et enfin. Seuls les alphabets "B" et "C" sont implémentés. Conservé dans environ 100 lignes, sans compter les tables de conversion. L'alphabet "A" peut être implémenté de manière similaire, simplement en ajoutant un constructeur et un tableau avec des alphabets, mais il est conseillé de prendre en compte un code délicat qui permet de passer brièvement à un caractère d'un alphabet différent. Je n'ai pas le désir, le temps ou d'autres motivations pour finir d'écrire moi-même. Le projet (semi) fini s'ajoutera probablement au cimetière des codeurs sur le github - si quelqu'un a envie de continuer le projet - n'hésitez pas à écrire.








All Articles