From: <dai...@us...> - 2012-05-26 10:46:14
|
Revision: 5399 http://web-erp.svn.sourceforge.net/web-erp/?rev=5399&view=rev Author: daintree Date: 2012-05-26 10:46:05 +0000 (Sat, 26 May 2012) Log Message: ----------- fix barcode printing in PDFPrintLabel.php Modified Paths: -------------- trunk/PDFPrintLabel.php trunk/PrintCustTrans.php trunk/PrintCustTransPortrait.php trunk/doc/Change.log trunk/includes/class.pdf.php Added Paths: ----------- trunk/includes/barcodepack/ trunk/includes/barcodepack/class.barcode.php trunk/includes/barcodepack/class.code128.php trunk/includes/barcodepack/class.ean13.php trunk/includes/barcodepack/class.i2of5.php trunk/includes/barcodepack/class.linearBarcode.php trunk/includes/barcodepack/class.qrCode.php trunk/includes/barcodepack/class.s2of5.php trunk/includes/barcodepack/class.upc.php trunk/includes/tcpdf/cache/ Modified: trunk/PDFPrintLabel.php =================================================================== --- trunk/PDFPrintLabel.php 2012-05-25 06:22:39 UTC (rev 5398) +++ trunk/PDFPrintLabel.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -2,6 +2,7 @@ /* $Id: PDFPriceLabels.php 5228 2012-04-06 02:48:00Z vvs2012 $*/ include('includes/session.inc'); +include('includes/barcodepack/class.code128.php'); $PtsPerMM = 2.83465; //pdf points per mm @@ -180,27 +181,15 @@ $pdf->addInfo('Title', $LabelDimensions['description'] . ' ' . _('Price Labels') ); $pdf->addInfo('Subject', $LabelDimensions['description'] . ' ' . _('Price Labels') ); + $pdf->setPrintHeader(false); + $pdf->setPrintFooter(false); + + $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); $pdf->setPrintHeader(false); $pdf->setPrintFooter(false); - $style = array( - 'position' => '', - 'align' => 'C', - 'stretch' => false, - 'fitwidth' => true, - 'cellfitalign' => '', - 'border' => true, - 'hpadding' => 'auto', - 'vpadding' => 'auto', - 'fgcolor' => array(0,0,0), - 'bgcolor' => false, //array(255,255,255), - 'text' => false, - 'font' => 'helvetica', - 'fontsize' => 8, - 'stretchtext' => 4 ); - $PageNumber=1; //go down first then accross $YPos = $Page_Height - $Top_Margin; //top of current label @@ -225,15 +214,15 @@ $LeftOvers = $pdf->addTextWrap($XPos+$Field['HPos'],$YPos-$LabelDimensions['label_height']+$Field['VPos'],$LabelDimensions['label_width']-$Field['HPos'],$Field['FontSize'],$_POST['Price' . $i],'center'); } elseif($Field['Barcode']==1) { - /* write1DBarcode($code, $type, $x='', $y='', $w='', $h='', $xres='', $style='', $align='') - * Note that the YPos for this function is based on the opposite origin for the Y axis i.e from the bottom not from the top! - */ - //$BarcodeFileName = $_SERVER['DOCUMENT_ROOT'] . $rootpath . '/' . $_SESSION['reports_dir'] .'/barcode_' . $i . '.jpg'; - //Barcode39(str_replace('_', $Value),$BarcodeFileName, $LabelDimensions['label_width']-$Field['HPos']-$Left_Margin,$Field['FontSize']); - //$pdf->addJpegFromFile($BarcodeFileName, $XPos+$Field['HPos'],$YPos-$LabelDimensions['label_height']+$Field['VPos']); - //$pdf->Image('@' . , $XPos+$Field['HPos'], $Page_Height-($YPos+$LabelDimensions['label_height']-$Field['VPos']), $LabelDimensions['label_width']-$Field['HPos']-$Left_Margin, $Field['FontSize']); + $BarcodeImage = new code128(str_replace('_','',$Value)); - $pdf->write1DBarcode(str_replace('_','',$Value), 'C39E',$XPos+$Field['HPos'],$Page_Height - $YPos+$LabelDimensions['label_height']-$Field['VPos']-$Field['FontSize'],$LabelDimensions['label_width']-$Field['HPos'], 40, 1, $style, 'N'); + ob_start(); + imagepng(imagepng($BarcodeImage->draw())); + $Image_String = ob_get_contents(); + ob_end_clean(); + + $pdf->addJpegFromFile('@' . $Image_String,$XPos+$Field['HPos'],$Field['VPos'],'', $Field['FontSize']); + } else { $LeftOvers = $pdf->addTextWrap($XPos+$Field['HPos'],$YPos-$LabelDimensions['label_height']+$Field['VPos'],$LabelDimensions['label_width']-$Field['HPos']-20,$Field['FontSize'],$Value); } @@ -366,179 +355,4 @@ } /*end of else not PrintPDF */ -function Barcode39 ($barcode, $FileName='',$width=160, $height=80, $text='') { - - /* Generate a Code 3 of 9 barcode */ - - $im = ImageCreate ($width, $height) - or die ("Cannot Initialize new GD image stream"); - $White = ImageColorAllocate ($im, 255, 255, 255); - $Black = ImageColorAllocate ($im, 0, 0, 0); - //ImageColorTransparent ($im, $White); - ImageInterLace ($im, 1); - - $NarrowRatio = 20; - $WideRatio = 55; - $QuietRatio = 35; - - $nChars = (strlen($barcode)+2) * ((6 * $NarrowRatio) + (3 * $WideRatio) + ($QuietRatio)); - $Pixels = $width / $nChars; - $NarrowBar = (int)(20 * $Pixels); - $WideBar = (int)(55 * $Pixels); - $QuietBar = (int)(35 * $Pixels); - - $ActualWidth = (($NarrowBar * 6) + ($WideBar*3) + $QuietBar) * (strlen ($barcode)+2); - - if (($NarrowBar == 0) || ($NarrowBar == $WideBar) || ($NarrowBar == $QuietBar) || ($WideBar == 0) || ($WideBar == $QuietBar) || ($QuietBar == 0)) { - ImageString ($im, 1, 0, 0, "Image is too small!", $Black); - ImageJPEG ($im, $FileName, 100); - exit; - } - - $CurrentBarX = (int)(($width - $ActualWidth) / 2); - $Color = $White; - $BarcodeFull = "*".strtoupper ($barcode)."*"; - settype ($BarcodeFull, "string"); - - $FontNum = 3; - $FontHeight = ImageFontHeight ($FontNum); - $FontWidth = ImageFontWidth ($FontNum); - if ($text != 0) { - $CenterLoc = (int)(($width-1) / 2) - (int)(($FontWidth * strlen($BarcodeFull)) / 2); - ImageString ($im, $FontNum, $CenterLoc, $height-$FontHeight, "$BarcodeFull", $Black); - } else { - $FontHeight=-2; - } - - - for ($i=0; $i<strlen($BarcodeFull); $i++) { - $StripeCode = Code39 ($BarcodeFull[$i]); - - for ($n=0; $n < 9; $n++) { - if ($Color == $White){ - $Color = $Black; - } else { - $Color = $White; - } - - switch ($StripeCode[$n]) { - case '0': - ImageFilledRectangle ($im, $CurrentBarX, 0, $CurrentBarX+$NarrowBar, $height-1-$FontHeight-2, $Color); - $CurrentBarX += $NarrowBar; - break; - - case '1': - ImageFilledRectangle ($im, $CurrentBarX, 0, $CurrentBarX+$WideBar, $height-1-$FontHeight-2, $Color); - $CurrentBarX += $WideBar; - break; - } - } - - $Color = $White; - ImageFilledRectangle ($im, $CurrentBarX, 0, $CurrentBarX+$QuietBar, $height-1-$FontHeight-2, $Color); - $CurrentBarX += $QuietBar; - } //end loop around each character in barcode string - - imagejpeg ($im, $FileName, 100); -}//end Barcode39 - -//----------------------------------------------------------------------------- -// Returns the Code 3 of 9 value for a given ASCII character -//----------------------------------------------------------------------------- -function Code39 ($Asc) { - switch ($Asc) { - case ' ': - return "011000100"; - case '$': - return "010101000"; - case '%': - return "000101010"; - case '*': - return "010010100"; // * Start/Stop - case '+': - return "010001010"; - case '|': - return "010000101"; - case '.': - return "110000100"; - case '/': - return "010100010"; - case '-': - return "010000101"; - case '0': - return "000110100"; - case '1': - return "100100001"; - case '2': - return "001100001"; - case '3': - return "101100000"; - case '4': - return "000110001"; - case '5': - return "100110000"; - case '6': - return "001110000"; - case '7': - return "000100101"; - case '8': - return "100100100"; - case '9': - return "001100100"; - case 'A': - return "100001001"; - case 'B': - return "001001001"; - case 'C': - return "101001000"; - case 'D': - return "000011001"; - case 'E': - return "100011000"; - case 'F': - return "001011000"; - case 'G': - return "000001101"; - case 'H': - return "100001100"; - case 'I': - return "001001100"; - case 'J': - return "000011100"; - case 'K': - return "100000011"; - case 'L': - return "001000011"; - case 'M': - return "101000010"; - case 'N': - return "000010011"; - case 'O': - return "100010010"; - case 'P': - return "001010010"; - case 'Q': - return "000000111"; - case 'R': - return "100000110"; - case 'S': - return "001000110"; - case 'T': - return "000010110"; - case 'U': - return "110000001"; - case 'V': - return "011000001"; - case 'W': - return "111000000"; - case 'X': - return "010010001"; - case 'Y': - return "110010000"; - case 'Z': - return "011010000"; - default: - return "011000100"; - } -} ?> \ No newline at end of file Modified: trunk/PrintCustTrans.php =================================================================== --- trunk/PrintCustTrans.php 2012-05-25 06:22:39 UTC (rev 5398) +++ trunk/PrintCustTrans.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -65,6 +65,7 @@ $pdf->setAutoPageBreak(0); $pdf->setPrintHeader(false); + $pdf->setPrintFooter(false); $pdf->AddPage(); $pdf->cMargin = 0; /* END Brought from class.pdf.php constructor */ Modified: trunk/PrintCustTransPortrait.php =================================================================== --- trunk/PrintCustTransPortrait.php 2012-05-25 06:22:39 UTC (rev 5398) +++ trunk/PrintCustTransPortrait.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -63,6 +63,7 @@ $pdf->setAutoPageBreak(0); $pdf->setPrintHeader(false); + $pdf->setPrintFooter(false); $pdf->AddPage(); $pdf->cMargin = 0; Modified: trunk/doc/Change.log =================================================================== --- trunk/doc/Change.log 2012-05-25 06:22:39 UTC (rev 5398) +++ trunk/doc/Change.log 2012-05-26 10:46:05 UTC (rev 5399) @@ -1,5 +1,6 @@ webERP Change Log +26/5/2012 Phil: Fix barcode printing on PDFPrintLabel.php - barcode functionality is unreliable so used (http://www.barcodepack.com) by Tomáš Horáček very simple and clean 23/5/2012 Klaus: PO_PDFPurchOrders.php print purchase orders with supplier's code where it is available in the purchasing data 23/5/2012 Exson: Revise GLAccounts.php to make more than 10 digits account code is allowed. 2012/05/22 Exson: Modify accountcode to varchar(20) to meet some countries accounting regulation for more digits account code. Added: trunk/includes/barcodepack/class.barcode.php =================================================================== --- trunk/includes/barcodepack/class.barcode.php (rev 0) +++ trunk/includes/barcodepack/class.barcode.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -0,0 +1,76 @@ +<?php + +/** + * This file is part of the BarcodePack - PHP Barcode Library. + * Copyright (c) 2011 Tomáš Horáček (http://www.barcodepack.com) + * BarcodePack by Tomáš Horáček is licensed under + * a Creative Commons Attribution-NoDerivs 3.0 Unported License. + */ + + + +// Error codes + +define('E_EMPTY_TEXT', 100); +define('E_MODULE_SIZE', 101); + + +/** + * barcode + * + * Main class of BarcodePack Library + * + * @author Tomáš Horáček <in...@we...> + * @package BarcodePack + */ +class barcode { + + // Minimal module size + const MIN_MODULE_SIZE = 1; + + // Maximal module size + const MAX_MODULE_SIZE = 10; + + // Default module size + const MODULE_SIZE = 2; + + /** + * Text to be encoded + * @var string + */ + protected $text = ''; + + /** + * Module size in pixels + * @var int + */ + protected $moduleSize = null; + + + /** + * Constructor + * + * @param string $text + * @param int $moduleSize + */ + public function __construct($text, $moduleSize=self::MODULE_SIZE) + { + + // input text check + if(!empty ($text)) { + $this->text = $text; + } else { + throw new Exception('Input text can not be empty.', E_EMPTY_TEXT); + } + + // Module size check + $moduleSize = (int) $moduleSize; + if($moduleSize >= self::MIN_MODULE_SIZE && $moduleSize <= self::MAX_MODULE_SIZE) { + $this->moduleSize = $moduleSize; + } else { + throw new Exception('Module size have to be in range '.self::MIN_MODULE_SIZE.' - '.self::MAX_MODULE_SIZE.'.', E_MODULE_SIZE); + } + + } + +} Property changes on: trunk/includes/barcodepack/class.barcode.php ___________________________________________________________________ Added: svn:executable + * Added: trunk/includes/barcodepack/class.code128.php =================================================================== --- trunk/includes/barcodepack/class.code128.php (rev 0) +++ trunk/includes/barcodepack/class.code128.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -0,0 +1,338 @@ +<?php + +/** + * This file is part of the BarcodePack - PHP Barcode Library. + * Copyright (c) 2011 Tomáš Horáček (http://www.barcodepack.com) + * BarcodePack by Tomáš Horáček is licensed under + * a Creative Commons Attribution-NoDerivs 3.0 Unported License. + */ + + + +require_once 'class.linearBarcode.php'; + +/** + * Code 128 + * Class implements Code 128 barcode + * + * @author Tomáš Horáček <in...@we...> + * @package BarcodePack + */ +class code128 extends linearBarcode { + + // Code sets + const CHARSET_A = 'A'; + const CHARSET_B = 'B'; + const CHARSET_C = 'C'; + + const START_A = 103; + const START_B = 104; + const START_C = 105; + const STOP = 106; + const TERMINATION = 107; + + // Code sets switchers + const CODE_A = 101; + const CODE_B = 100; + const CODE_C = 99; + + + private $setA = array(); + private $setB = array(); + private $setC = array(); + + private $charsA = ''; + private $charsB = ''; + private $charsC = ''; + + /** + * Zero represents white line + * One represents black line + * + * After each character except STOP I will add one white line + * (separating line) + * + * ASCII (dec) => bitecode + * + * @var array + */ + private $codeTable = array( + '11011001100', // 01 + '11001101100', // 02 + '11001100110', // 03 + '10010011000', // 04 + '10010001100', // ... + '10001001100', + '10011001000', + '10011000100', + '10001100100', + '11001001000', + '11001000100', + '11000100100', + '10110011100', + '10011011100', + '10011001110', + '10111001100', + '10011101100', + '10011100110', + '11001110010', + '11001011100', + '11001001110', + '11011100100', + '11001110100', + '11101101110', + '11101001100', + '11100101100', + '11100100110', + '11101100100', + '11100110100', + '11100110010', + '11011011000', + '11011000110', + '11000110110', + '10100011000', + '10001011000', + '10001000110', + '10110001000', + '10001101000', + '10001100010', + '11010001000', + '11000101000', + '11000100010', + '10110111000', + '10110001110', + '10001101110', + '10111011000', + '10111000110', + '10001110110', + '11101110110', + '11010001110', + '11000101110', + '11011101000', + '11011100010', + '11011101110', + '11101011000', + '11101000110', + '11100010110', + '11101101000', + '11101100010', + '11100011010', + '11101111010', + '11001000010', + '11110001010', + '10100110000', + '10100001100', + '10010110000', + '10010000110', + '10000101100', + '10000100110', + '10110010000', + '10110000100', + '10011010000', + '10011000010', + '10000110100', + '10000110010', + '11000010010', + '11001010000', + '11110111010', + '11000010100', + '10001111010', + '10100111100', + '10010111100', + '10010011110', + '10111100100', + '10011110100', + '10011110010', + '11110100100', + '11110010100', + '11110010010', + '11011011110', + '11011110110', + '11110110110', + '10101111000', + '10100011110', + '10001011110', + '10111101000', + '10111100010', + '11110101000', + '11110100010', + '10111011110', + '10111101110', + '11101011110', + '11110101110', + '11010000100', // 103 START A + '11010010000', // 104 START B + '11010011100', // 105 START C + '11000111010', // 106 STOP + '11' // 107 Termination bar + ); + + + /** + * Constructor + * + * @param string $text + * @param int $moduleSize + */ + public function __construct($text, $moduleSize=2) + { + try { + // Fill set A + for($i=32; $i<=95; $i++) { + // chars SPACE - UNDERSPACE + $this->setA[$i] = $i - 32; + $this->charsA .= chr($i); + $allowedChars[] = chr($i); + } + for($i=0; $i<=31; $i++) { + // chars NUL - US (Unit seperator) + $this->setA[$i] = $i + 64; + $this->charsA .= chr($i); + $allowedChars[] = chr($i); + } + + /* Fill set B + * chars SPACE " " - "DEL" + */ + for($i=32; $i<=127; $i++) { + $this->setB[$i] = $i - 32; + $this->charsB .= chr($i); + $allowedChars[] = chr($i); + } + + + parent::__construct($text, $moduleSize, $allowedChars); + + + $this->biteCode = $this->createBiteCode(); + + } catch (Exception $e) { + throw $e; + } + + } + + + /** + * Create Bite Code + * + * + * @return string + */ + private function createBiteCode() + { + $biteCode = array(); + + $characterSet = self::CHARSET_B; // Default code set + + $weightedSum = 0; + $checksumCounter = 1; + + $biteCode['DATA'] = ''; + // Find start character + if(strlen($this->text)>=2 && is_numeric($this->text{0}) && is_numeric($this->text{1})) { + // If the first and second characters are numeric use character set C + // and insert START_C char + $biteCode['DATA'] .= $this->codeTable[self::START_C]; + $characterSet = self::CHARSET_C; + $weightedSum += self::START_C; + } else if (strpos ($this->charsB, $this->text{0})) { + // Character set B + $biteCode['DATA'] .= $this->codeTable[self::START_B]; + $characterSet = self::CHARSET_B; + $weightedSum += self::START_B; + } else if (strpos ($this->charsA, $this->text{0})) { + // Character set A + $biteCode['DATA'] .= $this->codeTable[self::START_A]; + $characterSet = self::CHARSET_A; + $weightedSum += self::START_A; + } else { + throw new Exception(); + } + + + for($i=0;$i<strlen($this->text);$i++) { + switch ($characterSet) { + case 'B': + // Character set B is default, so it is first + $characterValue = $this->setB[ord($this->text{$i})]; + $biteCode['DATA'] .= $this->codeTable[$characterValue]; + break; + + case 'A': + $characterValue = $this->setA[ord($this->text{$i})]; + $biteCode['DATA'] .= $this->codeTable[$characterValue]; + break; + + case 'C': + $characterValue = intval($this->text{$i}.$this->text{$i+1}); + $biteCode['DATA'] .= $this->codeTable[$characterValue]; + $i++; + break; + + default: + break; + } + + $weightedSum += $characterValue*$checksumCounter; + $checksumCounter++; + + // find next char set. + if(strlen($this->text) > ($i+2) && is_numeric($this->text{$i+1}) && is_numeric($this->text{$i+2})) { + if($characterSet!=self::CHARSET_C) { + $characterValue = 99; + $biteCode['DATA'] .= $this->codeTable[$characterValue]; + $weightedSum += $characterValue*$checksumCounter; + $checksumCounter++; + } + $characterSet = 'C'; + } else if(isset($this->text{$i+1})) { + $newCharacterSet = $this->findCharacterSet($this->text{$i+1}); + if($characterSet==self::CHARSET_C) { + if($newCharacterSet==self::CHARSET_A) { + $characterValue = 101; + } + else { + $characterValue = 100; + } + $weightedSum += $characterValue*$checksumCounter; + $checksumCounter++; + $biteCode['DATA'] .= $this->codeTable[$characterValue]; + } + $characterSet = $newCharacterSet; + } + } + + // Count the checksum + $checkSum = (int) $weightedSum%103; + + // Add the checksum + $biteCode['DATA'] .= $this->codeTable[$checkSum]; + + // Add the stop character + $biteCode['DATA'] .= $this->codeTable[self::STOP]; + + // Add the termination bar + $biteCode['DATA'] .= $this->codeTable[self::TERMINATION]; + + return $biteCode; + } + + + /** + * Find Character Set + * Find correct character set depends on imput char + * + * @param char $char + * @return char + */ + private function findCharacterSet($char) { + if(strpos($this->charsB, $char)!==false) { + return self::CHARSET_B; + } + if(strpos($this->charsA, $char)!==false) { + return self::CHARSET_A; + } + } + +} Property changes on: trunk/includes/barcodepack/class.code128.php ___________________________________________________________________ Added: svn:executable + * Added: trunk/includes/barcodepack/class.ean13.php =================================================================== --- trunk/includes/barcodepack/class.ean13.php (rev 0) +++ trunk/includes/barcodepack/class.ean13.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -0,0 +1,209 @@ +<?php + +require_once 'class.linearBarcode.php'; + +// Error Codes +define('E_BAD_EAN_LENGTH', 600); + + + +/** + * EAN 13 + * + * @author Tomáš Horáček <in...@we...> + * @package BarcodePack + */ +class ean13 extends linearBarcode { + + /** @var array */ + private $allowedChars = array( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ); + + /** @var array */ + private $parity = array( + '0' => 'LLLLLLRRRRRR', + '1' => 'LLGLGGRRRRRR', + '2' => 'LLGGLGRRRRRR', + '3' => 'LLGGGLRRRRRR', + '4' => 'LGLLGGRRRRRR', + '5' => 'LGGLLGRRRRRR', + '6' => 'LGGGLLRRRRRR', + '7' => 'LGLGLGRRRRRR', + '8' => 'LGLGGLRRRRRR', + '9' => 'LGGLGLRRRRRR', + ); + + + /** + * Zero represents white line + * One represents black line + * + * After each character except STOP I will add one white line + * (separating line) + * + * @var array + */ + private $codeTable = array( + '0' => array('L'=>'0001101', 'G'=>'0100111', 'R'=>'1110010',), + '1' => array('L'=>'0011001', 'G'=>'0110011', 'R'=>'1100110',), + '2' => array('L'=>'0010011', 'G'=>'0011011', 'R'=>'1101100',), + '3' => array('L'=>'0111101', 'G'=>'0100001', 'R'=>'1000010',), + '4' => array('L'=>'0100011', 'G'=>'0011101', 'R'=>'1011100',), + '5' => array('L'=>'0110001', 'G'=>'0111001', 'R'=>'1001110',), + '6' => array('L'=>'0101111', 'G'=>'0000101', 'R'=>'1010000',), + '7' => array('L'=>'0111011', 'G'=>'0010001', 'R'=>'1000100',), + '8' => array('L'=>'0110111', 'G'=>'0001001', 'R'=>'1001000',), + '9' => array('L'=>'0001011', 'G'=>'0010111', 'R'=>'1110100',), + 'START' => '101', + 'SEPARATOR' => '01010', + 'STOP' => '101', + ); + + + /** + * Constructor + * + * @param string $text + * @param int $modulesize + */ + public function __construct($text, $moduleSize) + { + try { + parent::__construct($text, $moduleSize, $this->allowedChars); + + if(strlen($this->text)!=12) { + throw new Exception('Text length must be 12 characters.', E_BAD_EAN_LENGTH); + } + + $this->biteCode = $this->createBiteCode(); + } + catch(Exception $e) { + throw $e; + } + + } + + + /** + * Create Bite Code + * Create bitecode where 1 represents dark module and 0 white module. + * + * @return string + */ + private function createBiteCode() + { + $biteCode = array(); + + $saveTo = 'DATA'; + + // Parity determine + $parity = $this->parity[$this->text{0}]; + + $biteCode['START'] = $this->codeTable['START']; + + for($i=1;$i<strlen($this->text);$i++) { + $biteCode[$saveTo] .= $this->codeTable[$this->text{$i}][$parity{$i-1}]; + if($i==6) { + $biteCode['SEPARATOR'] = $this->codeTable['SEPARATOR']; + $saveTo = 'DATA2'; + } + + } + + $checksum = (string) $this->checksum($this->text); + + $this->text .= $checksum; + + $biteCode[$saveTo] .= $this->codeTable[$checksum]['R']; + + $biteCode['STOP'] = $this->codeTable['STOP']; + + return $biteCode; + } + + + /** + * Checksum + * Count checksum + * + * @param string $text + * @return int + */ + private function checksum($text) { + + $evensum = 0; + $oddsum = 0; + + for($i=1;$i<=strlen($text);$i++) { + if($i%2==0) { + $evensum += (int) $text{$i-1}; + } else { + $oddsum += (int) $text{$i-1}; + } + } + + $sum = $evensum*3 + $oddsum; + + return ceil($sum/10)*10 - $sum; + } + + + /** + * Draw + * Add text into barcode + * + * @param bool $showText + * @return image resource + */ + public function draw($showText = true) { + $im = parent::draw(false); + + $margin = $this->margin*$this->moduleSize; + + + $white = Imagecolorallocate ($im,255,255,255); + $black = Imagecolorallocate ($im,0,0,0); + + + if($showText) { + + // Increase space between symbol 2x + $im2 = ImageCreate($this->getBarcodeLen()*$this->moduleSize+(2*$margin)+$margin, + $this->height+$this->fontSize+(2*$margin)); + + imagecopy($im2, $im, $margin, 0, 0, 0, $this->getBarcodeLen()*$this->moduleSize+(2*$margin), $this->height+$this->fontSize+(2*$margin)); + + // Divide text into three parts and each insert to the diffrerent place + $charsA = $this->text{0}; // first char + for($i=1;$i<=strlen($this->text);$i++) { + if($i<=6) { + $charsB .= $this->text{$i}; + } else { + $charsC .= $this->text{$i}; + } + } + + // Insert A + $textWidth = ImageFontWidth($this->fontSize)*strlen($charsA); + imagestring ($im2, $this->fontSize, + $margin, + $this->height-$this->fontSize/2+$margin, $charsA, $black); + + // Insert B + $textWidth = ImageFontWidth($this->fontSize)*strlen($charsB); + imagestring ($im2, $this->fontSize, + $this->getBarcodeLen()*$this->moduleSize/4-$textWidth/2+2*$margin, + $this->height-$this->fontSize/2+$margin, $charsB, $black); + + // Insert C + $textWidth = ImageFontWidth($this->fontSize)*strlen($charsC); + imagestring ($im2, $this->fontSize, + $this->getBarcodeLen()*$this->moduleSize-$this->getBarcodeLen()*$this->moduleSize/4-$textWidth/2+2*$margin, + $this->height-$this->fontSize/2+$margin, $charsC, $black); + } + + return $im2; + } + +} Property changes on: trunk/includes/barcodepack/class.ean13.php ___________________________________________________________________ Added: svn:executable + * Added: trunk/includes/barcodepack/class.i2of5.php =================================================================== --- trunk/includes/barcodepack/class.i2of5.php (rev 0) +++ trunk/includes/barcodepack/class.i2of5.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -0,0 +1,135 @@ +<?php + +/** + * This file is part of the BarcodePack - PHP Barcode Library. + * Copyright (c) 2011 Tomáš Horáček (http://www.barcodepack.com) + * BarcodePack by Tomáš Horáček is licensed under + * a Creative Commons Attribution-NoDerivs 3.0 Unported License. + */ + + + +require_once 'class.linearBarcode.php'; + + +// Error codes +define('E_ODD_LENGTH', 500); + + +/** + * i2of5 + * + * Interleaved 2/5 + * + * @author Tomáš Horáček <in...@we...> + * @package BarcodePack + */ +class i2of5 extends linearBarcode { + + /** @var array */ + private $allowedChars = array( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ); + + /** + * Coding table + * + * @var array + */ + private $codeTable = array( + '0' => '1010111011101', + '1' => '1110101010111', + '2' => '1011101010111', + '3' => '1110111010101', + '4' => '1010111010111', + '5' => '1110101110101', + '6' => '1011101110101', + '7' => '1010101110111', + '8' => '1110101011101', + '9' => '1011101011101', + 'START' => '1010', + 'STOP' => '11101', + ); + + + /** + * Constructor + * + * @param string $text + * @param int $modulesize + */ + public function __construct($text, $moduleSize) + { + try { + parent::__construct($text, $moduleSize, $this->allowedChars); + + if((strlen($this->text)%2)!=0) { + throw new Exception('The number of characters must be even', E_ODD_LENGTH); + } + + $this->biteCode = $this->createBiteCode(); + } + catch(Exception $e) { + throw $e; + } + + } + + + /** + * Create Bite Code + * + * @return string + */ + private function createBiteCode() + { + $biteCode = array(); + + // START character + $biteCode['START'] = $this->codeTable['START']; + + $biteCode['DATA'] = ''; + + + for($i=0;$i<strlen($this->text);$i++) { + $firstCounter = 0; // Num of line module + $secondCounter = 0; // Num of space module + + // Each char is encoded to 5 lines or spaces + for($j=0; $j<5; $j++) { + + // Encode first char into lines + $bars = true; + while($bars && $firstCounter<13) { + if($this->codeTable[$this->text{$i}]{$firstCounter}=="1") { + $biteCode['DATA'] .= '1'; // line + } else { + $bars = false; + } + $firstCounter++; // jump to next line + } + + // Second char is encoded to spaces + $spaces = true; + while($spaces && $secondCounter<13) { + if($this->codeTable[$this->text{$i+1}]{$secondCounter}=='1') { + $biteCode['DATA'] .= '0'; // space + $secondCounter++; + } else { + $spaces = false; + $secondCounter++; // jump to next space + } + } + } + + $i++; // jump to next char + } + + // Insert STOP character + $biteCode['STOP'] = $this->codeTable['STOP']; + + return $biteCode; + } + + +} Property changes on: trunk/includes/barcodepack/class.i2of5.php ___________________________________________________________________ Added: svn:executable + * Added: trunk/includes/barcodepack/class.linearBarcode.php =================================================================== --- trunk/includes/barcodepack/class.linearBarcode.php (rev 0) +++ trunk/includes/barcodepack/class.linearBarcode.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -0,0 +1,175 @@ +<?php + +/** + * This file is part of the BarcodePack - PHP Barcode Library. + * Copyright (c) 2011 Tomáš Horáček (http://www.barcodepack.com) + * BarcodePack by Tomáš Horáček is licensed under + * a Creative Commons Attribution-NoDerivs 3.0 Unported License. + */ + + + +require_once 'class.barcode.php'; + +// Error codes +define('E_BAD_CHARS', 200); + + +/** + * Linear Barcode + * Parent class for all linear barcode types + * + * @author Tomáš Horáček <in...@we...> + * @package BarcodePack + */ +class linearBarcode extends barcode { + + /** @var array */ + protected $biteCode = array(); + + /** @var int */ + protected $height = 100; + + /** @var int */ + protected $fontSize = 10; + + /** + * Quiet zone + * Multiple of module size + * @var int */ + protected $margin = 5; + + /** + * Constructor + * + * @param string $text + * @param int $modulesize + */ + public function __construct($text, $moduleSize=2, $allowedChars=null) + { + try { + parent::__construct($text, $moduleSize); + + if($allowedChars) { + $this->checkAllowedChars($text, $allowedChars); + } + + } catch (Exception $e) { + throw $e; + } + } + + + /** + * Check Allowed Chars + * + * @param string $text + * @param array $alloweChars + * @return bool + */ + protected function checkAllowedChars($text, $allowedChars) + { + for($i=0; $i<strlen($text); $i++) { + if(!in_array($text{$i}, $allowedChars)) { + throw new Exception('Input text contains nonallowed characters.', E_BAD_CHARS); + return false; + } + } + return true; + } + + + + /** + * Get Barcode Length + * @return int + */ + protected function getBarcodeLen() { + $len = 0; + foreach ($this->biteCode as $value) { + $len += strlen($value); + } + return $len; + } + + + /** + * Draw + * Create image with barcode + * + * @param bool $showText + * @return image resource + */ + public function draw($showText=true) + { + // Image create + $margin = $this->margin*$this->moduleSize; + $im = ImageCreate($this->getBarcodeLen()*$this->moduleSize+(2*$margin), + $this->height+$this->fontSize+(2*$margin)); + + // Color set + $white = Imagecolorallocate ($im,255,255,255); + $black = Imagecolorallocate ($im,0,0,0); + + + // Draw lines + $pos = 0; + foreach ($this->biteCode as $type => $values) { + switch($type) { + case 'DATA': + case 'DATA2': + // Data + for($i=0;$i<strlen($values);$i++) { + $color = (($values{$i})=='1') ? $black : $white; + imagefilledrectangle($im, $pos*$this->moduleSize+$margin, $margin, + ($pos+1)*$this->moduleSize+$margin, + $this->height-5*$this->moduleSize+$margin, $color); + $pos++; + } + break; + default: + // Special chars + // will be longer + for($i=0;$i<strlen($values);$i++) { + + $color = (($values{$i})=='1') ? $black : $white; + imagefilledrectangle($im, $pos*$this->moduleSize+$margin, $margin, + ($pos+1)*$this->moduleSize+$margin, $this->height+$margin, + $color); + $pos++; + } + + break; + } + } + + // Text + if($showText) { + $textWidth = ImageFontWidth($this->fontSize)*strlen($this->text); + imagestring ($im, $this->fontSize, + $this->getBarcodeLen()*$this->moduleSize/2-$textWidth/2+$margin, + $this->height-$this->fontSize/2+$margin, $this->text, $black); + } + + return $im; + } + + + /** + * Raw Data + * Returns data in text representation + * Black module is represented as 1 and white module as 0 + * + * @return string $output + */ + public function rawData() + { + $ret = ''; + foreach ($this->biteCode as $value) { + $ret .= $value; + } + return $ret; + } + + +} Added: trunk/includes/barcodepack/class.qrCode.php =================================================================== --- trunk/includes/barcodepack/class.qrCode.php (rev 0) +++ trunk/includes/barcodepack/class.qrCode.php 2012-05-26 10:46:05 UTC (rev 5399) @@ -0,0 +1,1266 @@ +<?php + +/** + * This file is part of the BarcodePack - PHP Barcode Library. + * Copyright (c) 2011 Tomáš Horáček (http://www.barcodepack.com) + * BarcodePack by Tomáš Horáček is licensed under + * a Creative Commons Attribution-NoDerivs 3.0 Unported License. + */ + + + +require_once 'class.barcode.php'; + +// Erroe codes +define('E_BAD_QR_LENGTH', 800); +define('E_BAD_VERSION', 801); +define('E_BAD_MASK', 802); + + + +/** + * qrCode + * Class for QR Code generation + * + * @author Tomáš Horáček <in...@we...> + * @package BarcodePack + */ +class qrCode extends barcode { + + // Error correction levels + const ECL_L_CODE = 'L'; + const ECL_M_CODE = 'M'; + const ECL_Q_CODE = 'Q'; + const ECL_H_CODE = 'H'; + + const DEFAULT_ECL = 'M'; + + // Error correction levels numbers + const ECL_L = 1; + const ECL_M = 0; + const ECL_Q = 3; + const ECL_H = 2; + + + // Mode indicators + const MODE_ECI = 7; + const MODE_NUMERIC = 1; + const MODE_ALPHANUMERIC = 2; + const MODE_8BITBYTE = 4; + const MODE_KANJI = 8; + const MODE_STRUCTURED_APPEND = 3; + const MODE_FNC1_FP = 5; // First position + const MODE_FNC1_SP = 9; // Second position + const MODE_TERMINATOR = 0; + + // Quiet zone size + const QUIET_ZONE = 4; + + // Directions + const DIRECTION_UP = 'UP'; + const DIRECTION_DOWN = 'DOWN'; + + /** + * Error correction level + * @var char + */ + private $ecl = self::ECL_L; + + /** + * Version (1-40) + * @var int + */ + private $version = 1; + + /** + * Matrix size (QR code size without quiet zone) + * @var int + */ + private $matrixSize = 0; + + /** + * Symbol size with quiet zone + * @var int + */ + private $symbolSize = 0; + + /** + * Number of imput characters + * @var int + */ + private $charsNum = 0; + + /** + * Mode indicator + * @var int + */ + private $mode; + + /** + * QR code matrix + * @var array + */ + private $matrix; + + /** + * Masked matrix + * @var array + */ + private $maskedMatrix; + + /** + * Coordinates of modules in matrix + * @var array + */ + private $bitsCoordinates; + + /** + * Mask reference (0-7) + * @var int + */ + private $maskReference; + + /** + * ECL conversion table + * @var array + */ + private $eclConvertTable = array( + self::ECL_L_CODE => self::ECL_L, + self::ECL_M_CODE => self::ECL_M, + self::ECL_Q_CODE => self::ECL_Q, + self::ECL_H_CODE => self::ECL_H, + ); + + /** + * Number of bits the num chars indicator is saved + * @var array + */ + private $characterCountIndicatorBits = array( + self::MODE_NUMERIC => array(1=> 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,), + self::MODE_ALPHANUMERIC => array(1=> 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,), + self::MODE_8BITBYTE => array(1=> 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,), + self::MODE_KANJI => array(1=> 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,), + ); + + /** + * Code capacity + * Include mode indicator and num chars indicator without ECL + * @var array + */ + private $numberDataBits = array( + self::ECL_L => array(1 => 152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 2192, 2592, 2960, 3424, 3688, 4184, 4712, 5176, 5768, 6360, 6888, 7456, 8048, 8752, 9392, 10208, 10960, 11744, 12248, 13048, 13880, 14744, 15640, 16568, 17528, 18448, 19472, 20528, 21616, 22496, 23648,), + self::ECL_M => array(1 => 128, 224, 352, 512, 688, 864, 992, 1232, 1456, 1728, 2032, 2320, 2672, 2920, 3320, 3624, 4056, 4504, 5016, 5352, 5712, 6256, 6880, 7312, 8000, 8496, 9024, 9544, 10136, 10984, 11640, 12328, 13048, 13800, 14496, 15312, 15936, 16816, 17728, 18672,), + self::ECL_Q => array(1 => 104, 176, 272, 384, 496, 608, 704, 880, 1056, 1232, 1440, 1648, 1952, 2088, 2360, 2600, 2936, 3176, 3560, 3880, 4096, 4544, 4912, 5312, 5744, 6032, 6464, 6968, 7288, 7880, 8264, 8920, 9368, 9848, 10288, 10832, 11408, 12016, 12656, 13328,), + self::ECL_H => array(1 => 72, 128, 208, 288, 368, 480, 528, 688, 800, 976, 1120, 1264, 1440, 1576, 1784, 2024, 2264, 2504, 2728, 3080, 3248, 3536, 3712, 4112, 4304, 4768, 5024, 5288, 5608, 5960, 6344, 6760, 7208, 7688, 7888, 8432, 8768, 9136, 9776, 10208,), + ); + + /** + * Code capacity in codewords + * @var array + */ + private $codewordsCapacity=array(1 => 26,44,70,100,134,172,196,242, + 292,346,404,466,532,581,655,733,815,901,991,1085,1156, + 1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465, + 2611,2761,2876,3034,3196,3362,3532,3706); + + /** + * Capacity in characters + * @var array + */ + private $dataCapacity = array( + self::ECL_L => array( + self::MODE_NUMERIC => array(1 => 41, 77, 127, 187, 255, 322, 370, 461, 552, 652, 772, 883, 1022, 1101, 1250, 1408, 1548, 1725, 1903, 2061, 2232, 2409, 2620, 2812, 3057, 3283, 3517, 3669, 3909, 4158, 4417, 4686, 4965, 5253, 5529, 5836, 6153, 6479, 6743, 7089,), + self::MODE_ALPHANUMERIC => array(1 => 25, 47, 77, 114, 154, 195, 224, 279, 335, 395, 468, 535, 619, 667, 758, 854, 938, 1046, 1153, 1249, 1352, 1460, 1588, 1704, 1853, 1990, 2132, 2223, 2369, 2520, 2677, 2840, 3009, 3183, 3351, 3537, 3729, 3927, 4087, 4296,), + self::MODE_8BITBYTE => array(1 => 17, 32, 53, 78, 106, 134, 154, 192, 230, 271, 321, 367, 425, 458, 520, 586, 644, 718, 792, 858, 929, 1003, 1091, 1171, 1273, 1367, 1465, 1528, 1628, 1732, 1840, 1952, 2068, 2188, 2303, 2431, 2563, 2699, 2809, 2953,), + self::MODE_KANJI => array(1 => 10, 20, 32, 48, 65, 82, 95, 118, 141, 167, 198, 226, 262, 282, 320, 361, 397, 442, 488, 528, 572, 618, 672, 721, 784, 842, 902, 940, 1002, 1066, 1132, 1201, 1273, 1347, 1417, 1496, 1577, 1661, 1729, 1817,), + ), + self::ECL_M => array( + self::MODE_NUMERIC => array(1 => 34, 63, 101, 149, 202, 255, 293, 365, 432, 513, 604, 691, 796, 871, 991, 1082, 1212, 1346, 1500, 1600, 1708, 1872, 2059, 2188, 2395, 2544, 2701, 2857, 3035, 3289, 3486, 3693, 3909, 4134, 4343, 4588, 4775, 5039, 5313, 5596,), + self::MODE_ALPHANUMERIC => array(1 => 20, 38, 61, 90, 122, 154, 178, 221, 262, 311, 366, 419, 483, 528, 600, 656, 734, 816, 909, 970, 1035, 1134, 1248, 1326, 1451, 1542, 1637, 1732, 1839, 1994, 2113, 2238, 2369, 2506, 2632, 2780, 2894, 3054, 3220, 3391,), + self::MODE_8BITBYTE => array(1 => 14, 26, 42, 62, 84, 106, 122, 152, 180, 213, 251, 287, 331, 362, 412, 450, 504, 560, 624, 666, 711, 779, 857, 911, 997, 1059, 1125, 1190, 1264, 1370, 1452, 1538, 1628, 1722, 1809, 1911, 1989, 2099, 2213, 2331,), + self::MODE_KANJI => array(1 => 8, 16, 26, 38, 52, 65, 75, 93, 111, 131, 155, 177, 204, 223, 254, 277, 310, 345, 384, 410, 438, 480, 528, 561, 614, 652, 692, 732, 778, 843, 894, 947, 1002, 1060, 1113, 1176, 1224, 1292, 1362, 1435,), + ), + self::ECL_Q => array( + self::MODE_NUMERIC => array(1 => 27, 48, 77, 111, 144, 178, 207, 259, 312, 364, 427, 489, 580, 621, 703, 775, 876, 948, 1063, 1159, 1224, 1358, 1468, 1588, 1718, 1804, 1933, 2085, 2181, 2358, 2473, 2670, 2805, 2949, 3081, 3244, 3417, 3599, 3791, 3993,), + self::MODE_ALPHANUMERIC => array(1 => 16, 29, 47, 67, 87, 108, 125, 157, 189, 221, 259, 296, 352, 376, 426, 470, 531, 574, 644, 702, 742, 823, 890, 963, 1041, 1094, 1172, 1263, 1322, 1429, 1499, 1618, 1700, 1787, 1867, 1966, 2071, 2181, 2298, 2420,), + self::MODE_8BITBYTE => array(1 => 11, 20, 32, 46, 60, 74, 86, 108, 130, 151, 177, 203, 241, 258, 292, 322, 364, 394, 442, 482, 509, 565, 611, 661, 715, 751, 805, 868, 908, 982, 1030, 1112, 1168, 1228, 1283, 1351, 1423, 1499, 1579, 1663,), + self::MODE_KANJI => array(1 => 7, 12, 20, 28, 37, 45, 53, 66, 80, 93, 109, 125, 149, 159, 180, 198, 224, 243, 272, 297, 314, 348, 376, 407, 440, 462, 496, 534, 559, 604, 634, 684, 719, 756, 790, 832, 876, 923, 972, 1024,), + ), + self::ECL_H => array( + self::MODE_NUMERIC => array(1 => 17, 34, 58, 82, 106, 139, 154, 202, 235, 288, 331, 374, 427, 468, 530, 602, 674, 746, 813, 919, 969, 1056, 1108, 1228, 1286, 1425, 1501, 1581, 1677, 1782, 1897, 2022, 2157, 2301, 2361, 2524, 2625, 2735, 2927, 3057,), + self::MODE_ALPHANUMERIC => array(1 => 10, 20, 35, 50, 64, 84, 93, 122, 143, 174, 200, 227, 259, 283, 321, 365, 408, 452, 493, 557, 587, 640, 672, 744, 779, 864, 910, 958, 1016, 1080, 1150, 1226, 1307, 1394, 1431, 1530, 1591, 1658, 1774, 1852,), + self::MODE_8BITBYTE => array(1 => 7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155, 177, 194, 220, 250, 280, 310, 338, 382, 403, 439, 461, 511, 535, 593, 625, 658, 698, 742, 790, 842, 898, 958, 983, 1051, 1093, 1139, 1219, 1273,), + self::MODE_KANJI => array(1 => 4, 8, 15, 21, 27, 36, 39, 52, 60, 74, 85, 96, 109, 120, 136, 154, 173, 191, 208, 235, 248, 270, 284, 315, 330, 365, 385, 405, 430, 457, 486, 518, 553, 590, 605, 647, 673, 701, 750, 784,), + ), + ); + + /** + * Position detection pattern + * @var array + */ + private $positionPattern = array( + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + ); + + /** + * Alignment pattern + * @var array + */ + private $alignmentPattern = array( + 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + ); + + /** + * Coordinates of alignment patterns + * @var array + */ + private $alignmentPatternCoordinate = array( + 1 => array(), + array(6, 18), + array(6, 22), + array(6, 26), + array(6, 30), + array(6, 34), + array(6, 22, 38), + array(6, 24, 42), + array(6, 26, 46), + array(6, 28, 50), + array(6, 30, 54), + array(6, 32, 58), + array(6, 34, 62), + array(6, 26, 46, 66,), + array(6, 26, 48, 70,), + array(6, 26, 50, 74,), + array(6, 30, 54, 78,), + array(6, 30, 56, 82,), + array(6, 30, 58, 86,), + array(6, 34, 62, 90,), + array(6, 28, 50, 72, 94), + array(6, 26, 50, 74, 98,), + array(6, 30, 54, 78, 102,), + array(6, 28, 54, 80, 106), + array(6, 32, 58, 84, 110,), + array(6, 30, 58, 86, 114,), + array(6, 34, 62, 90, 118,), + array(6, 26, 50, 74, 98, 122,), + array(6, 30, 54, 78, 102, 126,), + array(6, 26, 52, 78, 104, 130,), + array(6, 30, 56, 82, 108, 134,), + array(6, 34, 60, 86, 112, 138,), + array(6, 30, 58, 86, 114, 142,), + array(6, 34, 62, 90, 118, 146,), + array(6, 30, 54, 78, 102, 126, 150,), + array(6, 24, 50, 76, 102, 128, 154,), + array(6, 28, 54, 80, 106, 132, 158,), + array(6, 32, 58, 84, 110, 136, 162,), + array(6, 26, 54, 82, 110, 138, 166,), + array(6, 30, 58, 86, 114, 142, 170), + ); + + + /** + * Block specification + * @var array + */ + private $blocksSpec = array( + 1 => + array(self::ECL_L => array( 1, 0), self::ECL_M => array( 1, 0), self::ECL_Q => array( 1, 0), self::ECL_H => array( 1, 0)), // 1 + array(self::ECL_L => array( 1, 0), self::ECL_M => array( 1, 0), self::ECL_Q => array( 1, 0), self::ECL_H => array( 1, 0)), + array(self::ECL_L => array( 1, 0), self::ECL_M => array( 1, 0), self::ECL_Q => array( 2, 0), self::ECL_H => array( 2, 0)), + array(self::ECL_L => array( 1, 0), self::ECL_M => array( 2, 0), self::ECL_Q => array( 2, 0), self::ECL_H => array( 4, 0)), + array(self::ECL_L => array( 1, 0), self::ECL_M => array( 2, 0), self::ECL_Q => array( 2, 2), self::ECL_H => array( 2, 2)), // 5 + array(self::ECL_L => array( 2, 0), self::ECL_M => array( 4, 0), self::ECL_Q => array( 4, 0), self::ECL_H => array( 4, 0)), + array(self::ECL_L => array( 2, 0), self::ECL_M => array( 4, 0), self::ECL_Q => array( 2, 4), self::ECL_H => array( 4, 1)), + array(self::ECL_L => array( 2, 0), self::ECL_M => array( 2, 2), self::ECL_Q => array( 4, 2), self::ECL_H => array( 4, 2)), + array(self::ECL_L => array( 2, 0), self::ECL_M => array( 3, 2), self::ECL_Q => array( 4, 4), self::ECL_H => array( 4, 4)), + array(self::ECL_L => array( 2, 2), self::ECL_M => array( 4, 1), self::ECL_Q => array( 6, 2), self::ECL_H => array( 6, 2)), //10 + array(self::ECL_L => array( 4, 0), self::ECL_M => array( 1, 4), self::ECL_Q => array( 4, 4), self::ECL_H => array( 3, 8)), + array(self::ECL_L => array( 2, 2), self::ECL_M => array( 6, 2), self::ECL_Q => array( 4, 6), self::ECL_H => array( 7, 4)), + array(self::ECL_L => array( 4, 0), self::ECL_M => array( 8, 1), self::ECL_Q => array( 8, 4), self::ECL_H => array(12, 4)), + array(self::ECL_L => array( 3, 1), self::ECL_M => array( 4, 5), self::ECL_Q => array(11, 5), self::ECL_H => array(11, 5)), + array(self::ECL_L => array( 5, 1), self::ECL_M => array( 5, 5), self::ECL_Q => array( 5, 7), self::ECL_H => array(11, 7)), //15 + array(self::ECL_L => array( 5, 1), self::ECL_M => array( 7, 3), self::ECL_Q => array(15, 2), self::ECL_H => array( 3, 13)), + array(self::ECL_L => array( 1, 5), self::ECL_M => array(10, 1), self::ECL_Q => array( 1, 15), self::ECL_H => array( 2, 17)), + array(self::ECL_L => array( 5, 1), self::ECL_M => array( 9, 4), self::ECL_Q => array(17, 1), self::ECL_H => array( 2, 19)), + array(self::ECL_L => array( 3, 4), self::ECL_M => array( 3, 11), self::ECL_Q => array(17, 4), self::ECL_H => array( 9, 16)), + array(self::ECL_L => array( 3, 5), self::ECL_M => array( 3, 13), self::ECL_Q => array(15, 5), self::ECL_H => array(15, 10)), //20 + array(self::ECL_L => array( 4, 4), self::ECL_M => array(17, 0), self::ECL_Q => array(17, 6), self::ECL_H => array(19, 6)), + array(self::ECL_L => array( 2, 7), self::ECL_M => array(17, 0), self::ECL_Q => array( 7, 16), self::ECL_H => array(34, 0)), + array(self::ECL_L => array( 4, 5), self::ECL_M => array( 4, 14), self::ECL_Q => array(11, 14), self::ECL_H => array(16, 14)), + array(self::ECL_L => array( 6, 4), self::ECL_M => array( 6, 14), self::ECL_Q => array(11, 16), self::ECL_H => array(30, 2)), + array(self::ECL_L => array( 8, 4), self::ECL_M => array( 8, 13), self::ECL_Q => array( 7, 22), self::ECL_H => array(22, 13)), //25 + array(self::ECL_L => array(10, 2), self::ECL_M => array(19, 4), self::ECL_Q => array(28, 6), self::ECL_H => array(33, 4)), + array(self::ECL_L => array( 8, 4), self::ECL_M => array(22, 3), self::ECL_Q => array( 8, 26), self::ECL_H => array(12, 28)), + array(self::ECL_L => array( 3, 10), self::ECL_M => array( 3, 23), self::ECL_Q => array( 4, 31), self::ECL_H => array(11, 31)), + array(self::ECL_L => array( 7, 7), self::ECL_M => array(21, 7), self::ECL_Q => array( 1, 37), self::ECL_H => array(19, 26)), + array(self::ECL_L => array( 5, 10), self::ECL_M => array(19, 10), self::ECL_Q => array(15, 25), self::ECL_H => array(23, 25)), //30 + array(self::ECL_L => array(13, 3), self::ECL_M => array( 2, 29), self::ECL_Q => array(42, 1), self::ECL_H => array(23, 28)), + array(self::ECL_L => array(17, 0), self::ECL_M => array(10, 23), self::ECL_Q => array(10, 35), self::ECL_H => array(19, 35)), + array(self::ECL_L => array(17, 1), self::ECL_M => array(14, 21), self::ECL_Q => array(29, 19), self::ECL_H => array(11, 46)), + array(self::ECL_L => array(13, 6), self::ECL_M => array(14, 23), self::ECL_Q => array(44, 7), self::ECL_H => array(59, 1)), + array(self::ECL_L => array(12, 7), self::ECL_M => array(12, 26), self::ECL_Q => array(39, 14), self::ECL_H => array(22, 41)), //35 + array(self::ECL_L => array( 6, 14), self::ECL_M => array( 6, 34), self::ECL_Q => array(46, 10), self::ECL_H => array( 2, 64)), + array(self::ECL_L => array(17, 4), self::ECL_M => array(29, 14), self::ECL_Q => array(49, 10), self::ECL_H => array(24, 46)), + array(self::ECL_L => array( 4, 18), self::ECL_M => array(13, 32), self::ECL_Q => array(48, 14), self::ECL_H => array(42, 32)), + array(self::ECL_L => array(20, 4), self::ECL_M => array(40, 7), self::ECL_Q => array(43, 22), self::ECL_H => array(10, 67)), + array(self::ECL_L => array(19, 6), self::ECL_M => array(18, 31), self::ECL_Q => array(34, 34), self::ECL_H => array(20, 61)),//40 + ); + + /** + * Alphanumeric code coding table + * @var array + */ + private $alphanumCodingTable = array( + '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, + '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, + 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, + 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23, + 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29, + 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, 'Z' => 35, + ' ' => 36, '$' => 37, '%' => 38, '*' => 39, '+' => 40, '-' => 41, + '.' => 42, '/' => 43, ':' => 44, + ); + + /** + * Version information + * From ISO/IEC 18004:2000, page 78-79 + * @var array + */ + private $versionInformationStream = array( + 7 => 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, + 0x0e60d, 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, + 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, + 0x1ed75, 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, + 0x26a64, 0x27541, 0x28c69, + ); + + /** + * Galois field + * @var array + */ + private $galoisField; + + /** + * Galois field with changed index and value + * @var array + */ + private $indexGaloisField; + + + /** + * Constructor + * + * @param string $text + * @param int $moduleSize + * @param char $ecl + */ + public function __construct($text, $moduleSize=parent::MODULE_SIZE, $ecl=self::ECL_L_CODE, $version=null) + { + try { + parent::__construct($text, $moduleSize); + + // Convert input text to UTF-8 + $current_encoding = mb_detect_encoding($this->text, 'auto'); + $this->text = iconv($current_encoding, 'UTF-8', $this->text); + + $this->ecl = $this->eclConvertTable[$ecl]; + + // Num of input chars + $this->charsNum = strlen($text); + + $this->mode = $this->getMode($text); + + // Mask reference + $this->maskReference = rand(0,7); + + + // Version + $this->version = $this->getVersion($this->charsNum, $this->ecl, $this->mode, $version); + + // Code size + $this->matrixSize = $this->getMatrixSize($this->version); + + $this->symbolSize = $this->matrixSize + 2 * self::QUIET_ZONE; + + + $this->countGaloisField(); + + // Init matrixes + $this->init(); + + $this->bitsCoordinates = $this->getBitsCoordinates($this->maskedMatrix); + + $this->convertData(); + + // Format info + $formatInformation = $this->formatInformation($this->ecl,$this->maskReference); + $this->matrix = $this->addFormatInformation($this->matrix, $formatInformation); + + // Version info + if($this->version>=7 && $this->version<=40) { + $versionInformation = $this->versionInformation($this->version); + $this->matrix = $this->addVersionInformation($this->matrix, $versionInformation); + } + + + } catch (Exception $e) { + throw $e; + } + } + + + /** + * Get Mode + * Returns mode indicator + * + * @param string $text + * @return int + */ + private function getMode($text) + { + if (preg_match('/[^0-9]/', $text)==0) { + return self::MODE_NUMERIC; + } else if(preg_match('/[^0-9A-Z \$\*\%\+\.\/\:\-]/', $text)==0) { + return self::MODE_ALPHANUMERIC; + } else { + return self::MODE_8BITBYTE; + } + } + + + /** + * Get Version + * + * @param int $charsNum + * @param int $ecl + * @param int $mode + * @return int + */ + private function getVersion($charsNum, $ecl, $mode, $version) + { + $findversion = 1; + while ($findversion<=40) { + if ($this->dataCapacity[$ecl][$mode][$findversion] >= $charsNum) { + break; + } + $findversion++; + } + + if($findversion==41) { + throw new Exception('Input text is too long.', E_BAD_QR_LENGTH); + } + + + if($version) { + if($findversion<=$version && $version <= 40) { + return $version; + } else { + throw new Exception('Selected version can not be choosen.', E_BAD_VERSION); + } + } + + return $findversion; + } + + + /** + * Get Matrix Size + * + * Use bit shift + * x << y = x*(2^y) + * + * @param int $version + * @return int + */ + private function getMatrixSize($version) + { + return 17 + ($version << 2); + } + + + /** + * Init + * + * Matrix init + * prepare matrixes and bits + * + * @return void + */ + private function init() { + for ($y = 0; $y < $this->matrixSize; $y++) { + for ($x = 0; $x < $this->matrixSize; $x++) { + $matrix[$y][$x] = 0; // White as default + + // Vertical synch. + if ($y == 6 && $x % 2 == 0) { + $matrix[$y][$x] = 1; + } + // Hor. synch + if ($x == 6 && $y % 2 == 0) { + $matrix[$y][$x] = 1; + } + + // Mask synch. patterns + if ($y == 6 || $x == 6) { + $maskedMatrix[$y][$x] = 1; + } + + + // Format and version mask + // all versions + if($x==8 && ($y<=8 || $y>=($this->matrixSize-8))) { + $maskedMatrix[$y][$x] = 1; + } + if($y==8 && ($x<=8 || $x>=($this->matrixSize-8))) { + $maskedMatrix[$y][$x] = 1; + } + // Version >= 7 + if($this->version >= 7) { + if($y<=5 && $x>=$this->matrixSize-11 && $x<=$this->matrixSize-9) { + $maskedMatrix[$y][$x] = 1; + } + if($x<=5 && $y>=$this->matrixSize-11 && $y<=$this->matrixSize-9) { + $maskedMatrix[$y][$x] = 1; + } + } + + + // left top position pattern + if ($y <= 6 && $x <= 6) { + $shift = $y * 7 + $x; + $matrix[$y][$x] = $this->positionPattern[$shift]; + + $maskedMatrix[$y][$x] = 1; + $maskedMatrix[$y+1][$x+1] = 1; // mask. separatoru + } + // left bottom position pattern + if ($y < 7 && $x < $this->matrixSize && $x > ($this->matrixSize - 8)) { + $shift = $y * 7 + ($this->matrixSize - $x - 1); + $matrix[$y][$x] = $this->positionPattern[$shift]; + + $maskedMatrix[$y][$x] = 1; + $maskedMatrix[$y+1][$x-1] = 1; + } + // right top position pattern + if ($x < 7 && $y < $this->matrixSize && $y > ($this->matrixSize - 8)) { + $shift = $x + ($this->matrixSize - $y - 1) * 7; + $matrix[$y][$x] = $this->positionPattern[$shift]; + + $maskedMatrix[$y][$x] = 1; + $maskedMatrix[$y-1][$x+1] = 1; + } + } + } + + // Alignment patterns + if (count($this->alignmentPatternCoordinate[$this->version]) > 0) { + foreach ($this->alignmentPatternCoordinate[$this->version] as $y) { + foreach ($this->alignmentPatternCoordinate[$this->version] as $x) { + if (!(($x < 7 && $y < 7) || ($y > ($this->matrixSize - 8) && $x < 7) || ($x > ($this->matrixSize - 8) && $y < 7))) { + for ($i = 0; $i < 5; $i++) { + for ($j = 0; $j < 5; $j++) { + $xCoor = $x - $i + 2; + $yCoor = $y - $j + 2; + $matrix[$xCoor][$yCoor] = $this->alignmentPattern[$i * 5 + $j]; + $maskedMatrix[$xCoor][$yCoor] = 1; // Mask alignment patterns + } + } + } + } + } + } + + // Module around detection patterns + $maskedMatrix[0][7] = 1; + $maskedMatrix[0][$this->matrixSize-8] = 1; + $maskedMatrix[7][0] = 1; + $maskedMatrix[7][$this->matrixSize-1] = 1; + $maskedMatrix[$this->matrixSize-8][0] = 1; + $maskedMatrix[$this->matrixSize-1][7] = 1; + + + $this->matrix = $matrix; + $this->maskedMatrix = $maskedMatrix; + } + + + /** + * Get Bits Coordinates + * + * @param array $maskedMatrix + * @return array + */ + private function getBitsCoordinates($maskedMatrix) { + + + // start at right bottom corner + $y = $this->matrixSize-1; + $x = $this->matrixSize-1; + + // top + $direction = self::DIRECTION_UP; + + // and go left + $goLeft = 1; + + $biteCounter = 0; + while($biteCounter < $this->codewordsCapacity[$this->version]*8) { + + // jump over timing pattern + if($x==6) { + $x=5; + } + + switch($direction) { + case self::DIRECTION_UP: + if(!$this->maskedMatrix[$y][$x]) { + $bitesCoordinates[$biteCounter] = array($y,$x); + $biteCounter++; + } + + // next coordinate + if($goLeft==1) { + // Jdi doleva + $x = $x-1; + $y = $y; + $goLeft = 0; + } else { + // top right + $x = $x+1; + $y = $y-1; + + if($y<0) { + // direction change + $direction = self::DIRECTION_DOWN; + $y = 0; + $x = $x-2; + } + + $goLeft = 1; + } + + + break; + case self::DIRECTION_DOWN: + if(!$this->maskedMatrix[$y][$x]) { + $bitesCoordinates[$biteCounter] = array($y,$x); + $biteCounter++; + } + + // next coordinate + if($goLeft==1) { + // Doleva + $x = $x-1; + $y = $y; + $goLeft = 0; + } else { + // down and right + $x = $x+1; + $y = $y+1; + + if($y>=$this->matrixSize) { + // direction change + $direction = self::DIRECTION_UP; + $y = $y-1; + $x = $x-2; + } + + $goLeft = 1; + } + + break; + } + } + + return $bitesCoordinates; + } + + + + /** + * Convert Data + * + * @return void + */ + private function convertData() + { + $text = $this->text; + + + /* DATA CODING ********************************************************/ + + $dataCounter = 0; + // Mode indicator 4b + $data[$dataCounter] = array( + 4, + $this->mode, + ); + $totalDataBits = 4; + $dataCounter++; + + // Num chars indicator + $data[$dataCounter] = array( + // length indicator in bits + $this->characterCountIndicatorBits[$this->mode][$this->version], + $this->charsNum, + ); + $totalDataBits += $this->characterCountIndicatorBits[$this->mode][$this->version]; + $dataCounter++; + + switch($this->mode) { + case self::MODE_NUMERIC: + + // divide ... [truncated message content] |