diff --git a/barcode.php b/barcode.php index 2797149..e4ed30a 100644 --- a/barcode.php +++ b/barcode.php @@ -1,23 +1,38 @@ code = (isset($code)) ? $code : self::randomCode(); + $this->number = ($number==null) ? $this->_random() : $number; + $this->scale = ($scale==null || $scale<4) ? 4 : $scale; + + // Reflection Class : Method + + $this->_encoder = new EAN13($this->number, $this->scale); + } - encode($this->code); + function __destruct() + { + $this->_encoder->display(); } - private static function randomCode() + private function _random() { return substr(number_format(time() * rand(),0,'',''),0,12); } } -$number = (isset($_GET['code'])) ? $_GET['code'] : null; -new Barcode($number); +$encoding = (isset($_GET['encoding'])) ? $_GET['encoding'] : 'EAN-13'; +$number = (isset($_GET['code'])) ? $_GET['code'] : null; +$scale = (isset($_GET['scale'])) ? $_GET['scale'] : null; + +new Barcode($encoding, $number, $scale); diff --git a/ean.php b/ean.php index be96bfd..6b83b7a 100644 --- a/ean.php +++ b/ean.php @@ -1,66 +1,36 @@ "000000", - 1 => "001011", - 2 => "001101", - 3 => "001110", - 4 => "010011", - 5 => "011001", - 6 => "011100", - 7 => "010101", - 8 => "010110", - 9 => "011010" - ); - - $left = array( - // Odd Encoding - 0 => array ( - 0 => "0001101", - 1 => "0011001", - 2 => "0010011", - 3 => "0111101", - 4 => "0100011", - 5 => "0110001", - 6 => "0101111", - 7 => "0111011", - 8 => "0110111", - 9 => "0001011" - ), - // Even Encoding - 1 => array ( - 0 => "0100111", - 1 => "0110011", - 2 => "0011011", - 3 => "0100001", - 4 => "0011101", - 5 => "0111001", - 6 => "0000101", - 7 => "0010001", - 8 => "0001001", - 9 => "0010111" - ) - ); - - $right = array( - 0 => "1110010", - 1 => "1100110", - 2 => "1101100", - 3 => "1000010", - 4 => "1011100", - 5 => "1001110", - 6 => "1010000", - 7 => "1000100", - 8 => "1001000", - 9 => "1110100" - ); - - $guard = array( - 'start' => "101", - 'middle' => "01010", - 'end' => "101", - ); + private $_key; + private $_checksum; + private $_bars; + + private $_image; + private $_width; + private $_height; + + public function __construct($number, $scale) + { + global $PARITY_KEY; + + // if $number.length() < 12 || >= 13 error + + // Get the parity key, which is based on the first digit. + $this->_key = $PARITY_KEY[substr($number,0,1)]; + + // The checksum is appended to the 12 digit string + $this->_checksum = ean_checksum($number); + $this->number = $number.$this->_checksum; + + $this->scale = $scale; + + $this->_bars = $this->_encode(); + $this->_createImage(); + $this->_drawBars(); + $this->_drawText(); + } /** * The following incantations use the parity key (based off the @@ -72,99 +42,132 @@ function encode($number) * third uses odd, and so on. */ - $key = $parity[substr($number, 0, 1)]; - $number .= ean_checksum($number); - - $barcode[] = $guard['start']; - - for($i=1;$i<=strlen($number)-1;$i++) + protected function _encode() { - if($i<7) - $barcode[] = $left[$key[$i-1]][substr($number, $i, 1)]; - else - $barcode[] = $right[substr($number, $i, 1)]; - if($i==6) - $barcode[] = $guard['middle']; - } - - $barcode[] = $guard['end']; + global $LEFT_PARITY, $RIGHT_PARITY, $GUARD; - $scale = 6; - - $height = $scale*60; - $width = 1.8*$height; + $barcode[] = $GUARD['start']; + for($i=1;$i<=strlen($this->number)-1;$i++) + { + if($i<7) + $barcode[] = $LEFT_PARITY[$this->_key[$i-1]][substr($this->number, $i, 1)]; + else + $barcode[] = $RIGHT_PARITY[substr($this->number, $i, 1)]; + if($i==6) + $barcode[] = $GUARD['middle']; + } + $barcode[] = $GUARD['end']; - $image = imagecreate($width, $height); + return $barcode; + } - $bg_color=ImageColorAllocate($image, 0xFF, 0xFF, 0xFF); - $bar_color=ImageColorAllocate($image, 0x00, 0x00, 0x00); - $text_color=ImageColorAllocate($image, 0x00, 0x00, 0x00); + /** + * Create the image. + * + * The Height is 60 times the scale and the width is simply + * 180% of the height. + */ - define("MAX", $height*0.025); - define("FLOOR", $height*0.825); - define("WIDTH", $scale); + protected function _createImage() + { + $this->_height = $this->scale*60; + $this->_width = 1.8*$this->_height; - $x = ($height*0.2)-WIDTH; - $y = 100; + $this->_image = imagecreate($this->_width, $this->_height); + $bg_color=ImageColorAllocate($this->_image, 0xFF, 0xFF, 0xFF); + } /** - * For each encoded number (a binary number, e.g. 6 => "0000101") - * draw a bar for '1', leave blank for 0; + * Draw the actual bars themselves. + * + * We have defined some constants. MAX is the y-value for the maximum + * height a bar should go. FLOOR is the y-value for the minimum height. + * + * The differences in margin for MAX and FLOOR are because most of the + * barcode doesn't extend to the bottom, only the guards do. + * + * WIDTH is the actual width of the bars. + * + * X is the starting position of the bars, which is a fifth of the way + * into the image. * - * For the guards, draw a taller bar. + * To draw the bars, we translate a binary string into bars: + * + * 10111001 - bar, empty, bar, bar, bar, empty, empty, bar */ - foreach($barcode as $bar) + protected function _drawBars() { - $tall = 0; + $bar_color=ImageColorAllocate($this->_image, 0x00, 0x00, 0x00); - if(strlen($bar)==3 || strlen($bar)==5) - $tall = ($height*0.15); + define("MAX", $this->_height*0.025); + define("FLOOR", $this->_height*0.825); + define("WIDTH", $this->scale); + + $x = ($this->_height*0.2)-WIDTH; - for($i=1;$i<=strlen($bar);$i++) + foreach($this->_bars as $bar) { - if(substr($bar, $i-1, 1)==='1') - imagefilledrectangle($image, $x, MAX, $x+WIDTH, FLOOR+$tall, $bar_color); - $x += WIDTH; + $tall = 0; + + if(strlen($bar)==3 || strlen($bar)==5) + $tall = ($this->_height*0.15); + + for($i=1;$i<=strlen($bar);$i++) + { + if(substr($bar, $i-1, 1)==='1') + imagefilledrectangle($this->_image, $x, MAX, $x+WIDTH, FLOOR+$tall, $bar_color); + $x += WIDTH; + } } } /** - * Draw the text + * Draw the text: * - * For the 1st digit, needs to be on the left of the first guard. + * The first digit is left of the first guard. The kerning + * is how much space is in between the individual characters. * - * Next 6 digits are in the first area. Next 6 in the next; + * We add kerning after the first character to skip over the + * first guard. Then we do it again after the 6th character + * to skip over the second guard. * - * if $i%6 == 0, add some width + * We don't need to skip over the last guard. + * + * The fontsize is 7 times the scale. + * X is the start point, which is .05 a way into the image */ - $x = $width*0.05; - $y = $height*0.96; + protected function _drawText() + { + $x = $this->_width*0.05; + $y = $this->_height*0.96; - $font=dirname(__FILE__)."/"."FreeSansBold.ttf"; - $fontsize = $scale*(7); - $kerning = $fontsize*1; + $text_color=ImageColorAllocate($this->_image, 0x00, 0x00, 0x00); - for($i=0;$iscale*(7); + $kerning = $fontsize*1; + + for($i=0;$inumber);$i++) + { + imagettftext($this->_image, $fontsize, 0, $x, $y, $text_color, $font, $this->number[$i]); + if($i==0 || $i==6) + $x += $kerning*0.5; + $x += $kerning; + } } - header("Content-Type: image/png; name=\"barcode.png\""); - imagepng($image); - imagedestroy($image); -} + /** + * Send the headers and display the barcode. + * + * Destroy the image afterwards because we're firing and forgetting + */ -function ean_checksum($ean){ - $ean=(string)$ean; - $even=true; $esum=0; $osum=0; - for ($i=strlen($ean)-1;$i>=0;$i--){ - if ($even) $esum+=$ean[$i]; else $osum+=$ean[$i]; - $even=!$even; - } - return (10-((3*$esum+$osum)%10))%10; + public function display() + { + header("Content-Type: image/png; name=\"barcode.png\""); + imagepng($this->_image); + imagedestroy($this->_image); + } } diff --git a/ean_parity.php b/ean_parity.php new file mode 100644 index 0000000..eb854dc --- /dev/null +++ b/ean_parity.php @@ -0,0 +1,77 @@ + "000000", + 1 => "001011", + 2 => "001101", + 3 => "001110", + 4 => "010011", + 5 => "011001", + 6 => "011100", + 7 => "010101", + 8 => "010110", + 9 => "011010" + ))); + +define ("LEFT_PARITY", serialize (array( + // Odd Encoding + 0 => array ( + 0 => "0001101", + 1 => "0011001", + 2 => "0010011", + 3 => "0111101", + 4 => "0100011", + 5 => "0110001", + 6 => "0101111", + 7 => "0111011", + 8 => "0110111", + 9 => "0001011" + ), + // Even Encoding + 1 => array ( + 0 => "0100111", + 1 => "0110011", + 2 => "0011011", + 3 => "0100001", + 4 => "0011101", + 5 => "0111001", + 6 => "0000101", + 7 => "0010001", + 8 => "0001001", + 9 => "0010111" + ) + ))); + +define ("RIGHT_PARITY", serialize (array( + 0 => "1110010", + 1 => "1100110", + 2 => "1101100", + 3 => "1000010", + 4 => "1011100", + 5 => "1001110", + 6 => "1010000", + 7 => "1000100", + 8 => "1001000", + 9 => "1110100" + ))); + +define ("GUARDS", serialize (array( + 'start' => "101", + 'middle' => "01010", + 'end' => "101", + ))); + +$PARITY_KEY = unserialize(PARITY_KEY); +$LEFT_PARITY = unserialize(LEFT_PARITY); +$RIGHT_PARITY = unserialize(RIGHT_PARITY); +$GUARD = unserialize(GUARDS); + +function ean_checksum($ean){ + $ean=(string)$ean; + $even=true; $esum=0; $osum=0; + for ($i=strlen($ean)-1;$i>=0;$i--){ + if ($even) $esum+=$ean[$i]; else $osum+=$ean[$i]; + $even=!$even; + } + return (10-((3*$esum+$osum)%10))%10; +}