<?php

/* EAN13 barcode renderer
 * Copyright 2012 Joel Yliluoma - http://iki.fi/bisqwit/
 */

class EAN13render
{
  
// These are the different barcode patterns for each digit (7 bit each).
  // '1' represents a black line, '0' represents white (no line).
  
static $Rcodes = Array('1110010','1100110','1101100','1000010','1011100',
                         
'1001110','1010000','1000100','1001000','1110100');

  
// The EAN13 defines three groups of bit patterns.
  // The 'R' pattern group, as above.
  // The 'G' group, which is a mirror of R (bits scanned in opposite order).
  // And the 'L' group, which is an inverse of R (0 becomes 1, 1 becomes 0).
  // Rather than defining them as arrays, we'll synthesize them at runtime.
  
  // This array describes which group to use for each digit,
  // depending on the first digit of the EAN code.
  
static $groups = Array('LLLLLL','LLGLGG','LLGGLG','LLGGGL','LGLLGG',
                         
'LGGLLG','LGGGLL','LGLGLG','LGLGGL','LGGLGL');

  public static function 
Render($barcode)
  {
    
$w 123$h 78// Size of our barcode image.
    
$im ImageCreateTrueColor($w,$h);
    
ImageFilledRectangle($im0,0$w,$h0xFFFFFF); // Fill the image with white
    
$xpos 19;

    
// This function renders bit patterns.
    
$synth = function($pattern$transformation$height) use(&$im,&$xpos)
    {
      
$b strlen($pattern);
      for(
$a=0$a<$b; ++$a)
      {
        
$index $a;
        
        
// If the group is 'G', mirror the code.
        
if($transformation == 'G'$index = ($b-1) - $index;

        
// Choose the bit from the pattern.
        
$bit = (int) $pattern[$index];
        
        
// Oh. For anyone wondering, this editor is actually
        // Joe. It is not the same editor I have used for many
        // of my videos. That's because now I'm making a Linux program.
        // Anyway.
        
        // If the group is 'L', invert the bit.
        
if($transformation == 'L'$bit 1-$bit;
        
        
// If the bit is '1', draw a vertical line in black color.
        
if($bit == 1)
          
ImageLine($im$xpos,0$xpos,$height0x000000);
        ++
$xpos;
      }
    };
    
    
// Define the lengths of the barcode lines.
    
$normal_height    $h-12;
    
$separator_height $h-7;
    
    
$font './arial.ttf';
    
    
// First, produce a begin separator (two thin bars).
    
$synth('101''R'$separator_height);
    
    
$charlimit=strlen($barcode);
    
$midpos $charlimit >> 1;
    
    for(
$n=0$n<$charlimit; ++$n)
    {
      
$digit = (int) $barcode[$n];
      
      if(
$n == 0)
      {
        
// Print the first digit separately (in black color)
        // Unless 0, which stands for UPC
        
if($digit != 0)
          
ImageTTFtext($im8,0$xpos-10,$h-10x000000$font$digit);
      }
      else
      {
        
// Print the digit (in black color)
        
ImageTTFtext($im8,0$xpos,$h-10x000000$font$digit);
        
        
// Produce the pattern.
        
$code   EAN13render::$Rcodes[$digit];
        
$select 'R';
        if(
$n <= $midpos)
        {
          
// Choose the patterns for the left side digits based
          // on the first digit of the barcode.
          
$select EAN13render::$groups[ (int)$barcode[0] ][ $n-];
        }
        
        
$synth($code$select$normal_height);
        
        if(
$n == $midpos)
        {
          
// Produce the middle separator. Two thin bars, again.
          
$synth('01010''R'$separator_height);
        }
      }
    }
    
    
// Last, produce the end separator.
    // Which looks the same as the begin separator.
    
$synth('101''R'$separator_height);
    
    return 
$im;
  }
};

// This is my sample EAN-13 barcode (6425081281317):
#$barcode = sprintf('64%s', base_convert('BISQWIT',36,10));
#$barcode = '9780201633719';
$barcode '0''332960073452';
#$barcode = '020296124';

$im EAN13render::Render($barcode);
ImagePNG($im'test.png');