Skip to content

Commit

Permalink
Updating the repo with the updated version from a long time ago.
Browse files Browse the repository at this point in the history
  • Loading branch information
rlt3 committed Mar 1, 2017
1 parent 188deca commit bedcbe8
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 269 deletions.
Binary file added FreeSansBold.ttf
Binary file not shown.
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,34 @@ This is a re-working of [php-barcode](http://www.ashberg.de/php-barcode/ "php-ba

Folke did a lot of good work, but it is nigh unreadable, I think, and I wanted to fix that. Because of this, too, it is really hard to add newer barcode types.

I also needed an on-the-fly barcode solution for a freelance job. This code has been in production for several years.

### Requirements

* PHP >= 5.4
* [PHP GD](https://secure.php.net/manual/en/book.image.php)

### How do I use this?

Simply clone the repository and travel to ``/barcode.php``. You will get a random barcode. If you want a specific one, go to ``/barcode.php?code=`` and input a 12 digit number.
The signatures are fairly simple. Simply call `barcode` with the number of the
barcode and the scale of the barcode as an integer. The number needs to be
either 12 or 13 digits. The barcode will always be 13 digits even if only 12
are supplied as the 13th digit is the checksum of the first 12. The barcode's
scale will not go lower than 2 for scaling reasons and no higher than 12 for
memory reasons. A scale of 4 has worked well for my purposes in the past.

$barcode = new Barcode(1349875921348, 4);
$barcode = new Barcode(439457143245, 10);

The key thing to keep up with is the `FreeSansBold.ttf` file. By default the
Barcode class will look into PHP's calling directory for the font file. You can
specify a path as a third parameter.

$barcode = new Barcode(123456789120, 4, "/path/to/FreeSansBold.ttf");

There are only two public methods: `image()` and `display()`. The first
function `image()` returns the PHP created image as a reference. This may be
used to save an image to file, e.g. `imagepng($barcode->image(),
"/path/to/storage/barcode.png")`. The second function `display()` simply calls
the correct headers and displays the barcode in the browser. Useful for
debugging.
242 changes: 224 additions & 18 deletions barcode.php
Original file line number Diff line number Diff line change
@@ -1,38 +1,244 @@
<?php
//autoload
include("ean.php");

/*
* Create an EAN13 Barcode image.
*/

class Barcode
{
public $font;
public $number;
public $encoding;
public $scale;

protected $_encoder;
private $_key;
private $_bars;

private $_image;
private $_width;
private $_height;

public static $PARITY_KEY = array(
0 => "000000", 1 => "001011", 2 => "001101", 3 => "001110",
4 => "010011", 5 => "011001", 6 => "011100", 7 => "010101",
8 => "010110", 9 => "011010"
);

public static $LEFT_PARITY = 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"
)
);

public static $RIGHT_PARITY = array(
0 => "1110010", 1 => "1100110", 2 => "1101100", 3 => "1000010",
4 => "1011100", 5 => "1001110", 6 => "1010000", 7 => "1000100",
8 => "1001000", 9 => "1110100"
);

function __construct($encoding, $number=null, $scale=null)
public static $GUARD = array(
'start' => "101", 'middle' => "01010", 'end' => "101"
);

public static function checksum (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;
}

/**
* Create the barcode. $number is the 12/13 digit barcode to be displayed.
* The $scale is the scale of the image in integers. The scale will not go
* lower than 2 or greater than 12.
*/

public function __construct (string $number, $scale, $fontpath=null)
{
$this->number = ($number==null) ? $this->_random() : $number;
$this->scale = ($scale==null || $scale<4) ? 4 : $scale;
/* Get the parity key, which is based on the first digit. */
$this->_key = self::$PARITY_KEY[substr($number,0,1)];

if (!$fontpath)
$this->font = dirname(__FILE__) . "/" . "FreeSansBold.ttf";
else
$this->font = $fontpath;

// Reflection Class : Method
/* Clamp scale between 2 and 12 */
if ($scale < 2)
$this->scale = 2;
else if ($scale > 12)
$this->scale = 12;
else
$this->scale = $scale;

$this->_encoder = new EAN13($this->number, $this->scale);
$len = strlen($number);
if ($len != 13 && $len != 12)
trigger_error('Barcode expects 12 or 13 digit number', E_USER_ERROR);

/* The checksum (13th digit) can be calculated or supplied */
$this->number = $number;
if ($len === 12)
$this->number .= self::checksum($number);

$this->_bars = $this->_encode();
$this->_createImage();
$this->_drawBars();
$this->_drawText();
}

function __destruct()
public function __destruct()
{
$this->_encoder->display();
imagedestroy($this->_image);
}

private function _random()
/**
* The following incantations use the parity key (based off the
* first digit of the unencoded number) to encode the first six
* digits of the barcode. The last 6 use the same parity.
*
* So, if the key is 010101, the first digit (of the first six
* digits) uses odd parity encoding. The second uses even. The
* third uses odd, and so on.
*/

protected function _encode()
{
return substr(number_format(time() * rand(),0,'',''),0,12);
$barcode[] = self::$GUARD['start'];
for($i=1;$i<=strlen($this->number)-1;$i++)
{
if($i < 7)
$barcode[] = self::$LEFT_PARITY[$this->_key[$i-1]][substr($this->number, $i, 1)];
else
$barcode[] = self::$RIGHT_PARITY[substr($this->number, $i, 1)];
if($i == 6)
$barcode[] = self::$GUARD['middle'];
}
$barcode[] = self::$GUARD['end'];
return $barcode;
}
}

$encoding = (isset($_GET['encoding'])) ? $_GET['encoding'] : 'EAN-13';
$number = (isset($_GET['code'])) ? $_GET['code'] : null;
$scale = (isset($_GET['scale'])) ? $_GET['scale'] : null;
/**
* Create the image.
*
* The Height is 60 times the scale and the width is simply
* 180% of the height.
*/

protected function _createImage()
{
$this->_height = $this->scale * 60;
$this->_width = 1.8 * $this->_height;
$this->_image = imagecreate($this->_width, $this->_height);
ImageColorAllocate($this->_image, 0xFF, 0xFF, 0xFF);
}

/**
* 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.
*
* To draw the bars, we translate a binary string into bars:
*
* 10111001 - bar, empty, bar, bar, bar, empty, empty, bar
*/

protected function _drawBars()
{
$bar_color=ImageColorAllocate($this->_image, 0x00, 0x00, 0x00);

$MAX = $this->_height*0.025;
$FLOOR = $this->_height*0.825;
$WIDTH = $this->scale;

$x = ($this->_height * 0.2) - $WIDTH;

foreach($this->_bars as $bar)
{
$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:
*
* The first digit is left of the first guard. The kerning
* is how much space is in between the individual characters.
*
* 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.
*
* 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
*/

protected function _drawText()
{
$x = $this->_width*0.05;
$y = $this->_height*0.96;

$text_color=ImageColorAllocate($this->_image, 0x00, 0x00, 0x00);

$fontsize = $this->scale*7;
$kerning = $fontsize*1;

new Barcode($encoding, $number, $scale);
for($i=0;$i<strlen($this->number);$i++)
{
imagettftext($this->_image, $fontsize, 0, $x, $y, $text_color, $this->font, $this->number[$i]);
if($i==0 || $i==6)
$x += $kerning*0.5;
$x += $kerning;
}
}

/**
* Return the barcode's image by reference.
*/

public function &image()
{
return $this->_image;
}

/**
* Send the headers and display the barcode.
*/

public function display()
{
header("Content-Type: image/png; name=\"barcode.png\"");
imagepng($this->_image);
}
}
Loading

0 comments on commit bedcbe8

Please sign in to comment.