Skip to content

Commit

Permalink
EAN-13 has its own class. Will probably add some Reflection Class met…
Browse files Browse the repository at this point in the history
…hods to load this object dynamically. Whole thing needs refactoring.
  • Loading branch information
rlt3 committed Oct 30, 2012
1 parent 9086aa4 commit 6ea7c5f
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 135 deletions.
31 changes: 23 additions & 8 deletions barcode.php
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
<?php
//autoload
include("ean.php");

class Barcode
{
public $code;
public $type;
public $number;
public $encoding;
public $scale;

function __construct($code=null, $type='EAN-13')
protected $_encoder;

function __construct($encoding, $number=null, $scale=null)
{
$this->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);
257 changes: 130 additions & 127 deletions ean.php
Original file line number Diff line number Diff line change
@@ -1,66 +1,36 @@
<?php
function encode($number)
include("ean_parity.php");

class EAN13 extends Barcode
{
$parity = array(
0 => "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
Expand All @@ -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;$i<strlen($number);$i++)
{
imagettftext($image, $fontsize, 0, $x, $y, $text_color, $font, $number[$i]);
if($i==0 || $i==6)
$x += $kerning*0.5;
$x += $kerning;
$font=dirname(__FILE__)."/"."FreeSansBold.ttf";
$fontsize = $this->scale*(7);
$kerning = $fontsize*1;

for($i=0;$i<strlen($this->number);$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);
}
}
Loading

0 comments on commit 6ea7c5f

Please sign in to comment.