├── FreeSansBold.ttf ├── LICENSE ├── README.md ├── barcode.php └── composer.json /FreeSansBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayfarerdb/php-barcode/6890e6a3b7269f44481a3cdf373636f3848cb360/FreeSansBold.ttf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Leroy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | php-barcode 2 | ================ 3 | 4 | ### About 5 | 6 | This is a re-working of [php-barcode](http://www.ashberg.de/php-barcode/ "php-barcode") by Folke Ashberg. Currently, my version only creates EAN-13 barcodes, however I plan to make the source modular to allow for additions of ISBN, Code 12, and others. 7 | 8 | ### Why 9 | 10 | 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. 11 | 12 | I also needed an on-the-fly barcode solution for a freelance job. This code has been in production for several years. 13 | 14 | ### Requirements 15 | 16 | * PHP >= 5.4 17 | * [PHP GD](https://secure.php.net/manual/en/book.image.php) 18 | 19 | ### How do I use this? 20 | 21 | The signatures are fairly simple. Simply call `barcode` with the number of the 22 | barcode and the scale of the barcode as an integer. The number needs to be 23 | either 12 or 13 digits. The barcode will always be 13 digits even if only 12 24 | are supplied as the 13th digit is the checksum of the first 12. The barcode's 25 | scale will not go lower than 2 for scaling reasons and no higher than 12 for 26 | memory reasons. A scale of 4 has worked well for my purposes in the past. 27 | 28 | $barcode = new Barcode(1349875921348, 4); 29 | $barcode = new Barcode(439457143245, 10); 30 | 31 | The key thing to keep up with is the `FreeSansBold.ttf` file. By default the 32 | Barcode class will look into PHP's calling directory for the font file. You can 33 | specify a path as a third parameter. 34 | 35 | $barcode = new Barcode(123456789120, 4, "/path/to/FreeSansBold.ttf"); 36 | 37 | There are only two public methods: `image()` and `display()`. The first 38 | function `image()` returns the PHP created image as a reference. This may be 39 | used to save an image to file, e.g. `imagepng($barcode->image(), 40 | "/path/to/storage/barcode.png")`. The second function `display()` simply calls 41 | the correct headers and displays the barcode in the browser. Useful for 42 | debugging. 43 | -------------------------------------------------------------------------------- /barcode.php: -------------------------------------------------------------------------------- 1 | "000000", 1 => "001011", 2 => "001101", 3 => "001110", 22 | 4 => "010011", 5 => "011001", 6 => "011100", 7 => "010101", 23 | 8 => "010110", 9 => "011010" 24 | ); 25 | 26 | public static $LEFT_PARITY = array( 27 | // Odd Encoding 28 | 0 => array( 29 | 0 => "0001101", 1 => "0011001", 2 => "0010011", 3 => "0111101", 30 | 4 => "0100011", 5 => "0110001", 6 => "0101111", 7 => "0111011", 31 | 8 => "0110111", 9 => "0001011" 32 | ), 33 | // Even Encoding 34 | 1 => array ( 35 | 0 => "0100111", 1 => "0110011", 2 => "0011011", 3 => "0100001", 36 | 4 => "0011101", 5 => "0111001", 6 => "0000101", 7 => "0010001", 37 | 8 => "0001001", 9 => "0010111" 38 | ) 39 | ); 40 | 41 | public static $RIGHT_PARITY = array( 42 | 0 => "1110010", 1 => "1100110", 2 => "1101100", 3 => "1000010", 43 | 4 => "1011100", 5 => "1001110", 6 => "1010000", 7 => "1000100", 44 | 8 => "1001000", 9 => "1110100" 45 | ); 46 | 47 | public static $GUARD = array( 48 | 'start' => "101", 'middle' => "01010", 'end' => "101" 49 | ); 50 | 51 | public static function checksum (string $ean) { 52 | $even=true; $esum=0; $osum=0; 53 | for ($i = strlen($ean)-1; $i >= 0; $i--) { 54 | if ($even) $esum+=$ean[$i]; else $osum+=$ean[$i]; 55 | $even=!$even; 56 | } 57 | return (10-((3*$esum+$osum)%10))%10; 58 | } 59 | 60 | /** 61 | * Create the barcode. $number is the 12/13 digit barcode to be displayed. 62 | * The $scale is the scale of the image in integers. The scale will not go 63 | * lower than 2 or greater than 12. 64 | */ 65 | 66 | public function __construct (string $number, $scale, $fontpath=null) 67 | { 68 | /* Get the parity key, which is based on the first digit. */ 69 | $this->_key = self::$PARITY_KEY[substr($number,0,1)]; 70 | 71 | if (!$fontpath) 72 | $this->font = dirname(__FILE__) . "/" . "FreeSansBold.ttf"; 73 | else 74 | $this->font = $fontpath; 75 | 76 | /* Clamp scale between 2 and 12 */ 77 | if ($scale < 2) 78 | $this->scale = 2; 79 | else if ($scale > 12) 80 | $this->scale = 12; 81 | else 82 | $this->scale = $scale; 83 | 84 | $len = strlen($number); 85 | if ($len != 13 && $len != 12) 86 | trigger_error('Barcode expects 12 or 13 digit number', E_USER_ERROR); 87 | 88 | /* The checksum (13th digit) can be calculated or supplied */ 89 | $this->number = $number; 90 | if ($len === 12) 91 | $this->number .= self::checksum($number); 92 | 93 | $this->_bars = $this->_encode(); 94 | $this->_createImage(); 95 | $this->_drawBars(); 96 | $this->_drawText(); 97 | } 98 | 99 | public function __destruct() 100 | { 101 | imagedestroy($this->_image); 102 | } 103 | 104 | /** 105 | * The following incantations use the parity key (based off the 106 | * first digit of the unencoded number) to encode the first six 107 | * digits of the barcode. The last 6 use the same parity. 108 | * 109 | * So, if the key is 010101, the first digit (of the first six 110 | * digits) uses odd parity encoding. The second uses even. The 111 | * third uses odd, and so on. 112 | */ 113 | 114 | protected function _encode() 115 | { 116 | $barcode[] = self::$GUARD['start']; 117 | for($i=1;$i<=strlen($this->number)-1;$i++) 118 | { 119 | if($i < 7) 120 | $barcode[] = self::$LEFT_PARITY[$this->_key[$i-1]][substr($this->number, $i, 1)]; 121 | else 122 | $barcode[] = self::$RIGHT_PARITY[substr($this->number, $i, 1)]; 123 | if($i == 6) 124 | $barcode[] = self::$GUARD['middle']; 125 | } 126 | $barcode[] = self::$GUARD['end']; 127 | return $barcode; 128 | } 129 | 130 | /** 131 | * Create the image. 132 | * 133 | * The Height is 60 times the scale and the width is simply 134 | * 180% of the height. 135 | */ 136 | 137 | protected function _createImage() 138 | { 139 | $this->_height = $this->scale * 60; 140 | $this->_width = 1.8 * $this->_height; 141 | $this->_image = imagecreate($this->_width, $this->_height); 142 | ImageColorAllocate($this->_image, 0xFF, 0xFF, 0xFF); 143 | } 144 | 145 | /** 146 | * Draw the actual bars themselves. 147 | * 148 | * We have defined some constants. MAX is the y-value for the maximum 149 | * height a bar should go. FLOOR is the y-value for the minimum height. 150 | * 151 | * The differences in margin for MAX and FLOOR are because most of the 152 | * barcode doesn't extend to the bottom, only the guards do. 153 | * 154 | * WIDTH is the actual width of the bars. 155 | * 156 | * X is the starting position of the bars, which is a fifth of the way 157 | * into the image. 158 | * 159 | * To draw the bars, we translate a binary string into bars: 160 | * 161 | * 10111001 - bar, empty, bar, bar, bar, empty, empty, bar 162 | */ 163 | 164 | protected function _drawBars() 165 | { 166 | $bar_color=ImageColorAllocate($this->_image, 0x00, 0x00, 0x00); 167 | 168 | $MAX = $this->_height*0.025; 169 | $FLOOR = $this->_height*0.825; 170 | $WIDTH = $this->scale; 171 | 172 | $x = ($this->_height * 0.2) - $WIDTH; 173 | 174 | foreach($this->_bars as $bar) 175 | { 176 | $tall = 0; 177 | 178 | if(strlen($bar)==3 || strlen($bar)==5) 179 | $tall = ($this->_height * 0.15); 180 | 181 | for($i = 1; $i <= strlen($bar); $i++) 182 | { 183 | if(substr($bar, $i-1, 1)==='1') 184 | imagefilledrectangle($this->_image, $x, $MAX, $x + $WIDTH, 185 | $FLOOR + $tall, $bar_color); 186 | $x += $WIDTH; 187 | } 188 | } 189 | } 190 | 191 | /** 192 | * Draw the text: 193 | * 194 | * The first digit is left of the first guard. The kerning 195 | * is how much space is in between the individual characters. 196 | * 197 | * We add kerning after the first character to skip over the 198 | * first guard. Then we do it again after the 6th character 199 | * to skip over the second guard. 200 | * 201 | * We don't need to skip over the last guard. 202 | * 203 | * The fontsize is 7 times the scale. 204 | * X is the start point, which is .05 a way into the image 205 | */ 206 | 207 | protected function _drawText() 208 | { 209 | $x = $this->_width*0.05; 210 | $y = $this->_height*0.96; 211 | 212 | $text_color=ImageColorAllocate($this->_image, 0x00, 0x00, 0x00); 213 | 214 | $fontsize = $this->scale*7; 215 | $kerning = $fontsize*1; 216 | 217 | for($i=0;$inumber);$i++) 218 | { 219 | imagettftext($this->_image, $fontsize, 0, $x, $y, $text_color, $this->font, $this->number[$i]); 220 | if($i==0 || $i==6) 221 | $x += $kerning*0.5; 222 | $x += $kerning; 223 | } 224 | } 225 | 226 | /** 227 | * Return the barcode's image by reference. 228 | */ 229 | 230 | public function &image() 231 | { 232 | return $this->_image; 233 | } 234 | 235 | /** 236 | * Send the headers and display the barcode. 237 | */ 238 | 239 | public function display() 240 | { 241 | header("Content-Type: image/png; name=\"barcode.png\""); 242 | imagepng($this->_image); 243 | } 244 | 245 | /** 246 | * save image 247 | * If it does not exist, the directory creates it with the appropriate permissions: 248 | * RW-R--R-- 249 | */ 250 | public function save($path = 'barcode.png') 251 | { 252 | $dir = dirname($path); 253 | if (!file_exists($dir)) { 254 | mkdir($dir, 0644, true); 255 | } 256 | imagepng($this->_image, $path); 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rlt3/php-barcode", 3 | "type": "library", 4 | "description": "This is a re-working of php-barcode by Folke Ashberg, for creating EAN-13 barcodes.", 5 | "require": { 6 | "php": ">=5.4.0" 7 | }, 8 | "autoload": { 9 | "psr-4": { 10 | "rlt3\\Barcode\\": "" 11 | } 12 | } 13 | } --------------------------------------------------------------------------------