<?php
/***************************************************
 *             Kody kreskowe - RSS-14              *
 ***************************************************
 * Ostatnia modyfikacja: 01.11.2012 (wersja 1.0)   *
 * Autor: Jacek Kowalski (http://jacekk.info)      *
 *                                                 *
 * Strona WWW: http://jacekk.info/scripts/barcodes *
 *                                                 *
 * Utwór rozprowadzany na licencji                 *
 * http://creativecommons.org/licenses/by-nc/2.5/  *
 ***************************************************/

/* Kodowanie znaków UTF-8 */

function combins($n$r) {
    if(
$n-$r $r) {
        
$minDenom $r;
        
$maxDenom $n-$r;
    }
    else
    {
        
$minDenom $n-$r;
        
$maxDenom $r;
    }
    
$val 1;
    
$j 1;
    for(
$i $n$i $maxDenom$i--) {
        
$val *= $i;
        if(
$j <= $minDenom) {
            
$val /= $j;
            
$j++;
        }
    }
    for(; 
$j <= $minDenom$j++) {
        
$val /= $j;
    }
    return 
$val;
}


/* Zgodnie z załącznikiem B do PN-ISO/IEC 24724:2009 */
// $val - wartość do zakodowania,  $n - szerokość grupy, $elements - ilość modułów,
// $maxWidth - max. szerokość modułu, $noNarrow - dozwolone elementy bez modułu dł. "1"?
function getRSSwidths($val$n$elements$maxWidth$noNarrow=TRUE)
{
    
$narrowMask 0;
    for(
$bar 0$bar $elements-1$bar++) {
        for(
$elmWidth 1$narrowMask |= (1<<$bar); ; $elmWidth++, $narrowMask &= ~(1<<$bar)) {
            
/* get all combinations */
            
$subVal combins($n-$elmWidth-1$elements-$bar-2);
            
/* less combinations with no single-module element */
            
if((!$noNarrow) && ($narrowMask == 0) && ($n-$elmWidth-($elements-$bar-1) >= $elements-$bar-1)) {
                
$subVal -= combins($n-$elmWidth-($elements-$bar), $elements-$bar-2);
            }
            
/* less combinations with elements > maxVal */
            
if($elements-$bar-1) {
                
$lessVal 0;
                for(
$mxwElement $n-$elmWidth-($elements-$bar-2); $mxwElement $maxWidth$mxwElement--) {
                    
$lessVal += combins($n-$elmWidth-$mxwElement-1$elements-$bar-3);
                }
                
$subVal -= $lessVal * ($elements-1-$bar);
            }
            elseif(
$n-$elmWidth $maxWidth) {
                
$subVal--;
            }
            
$val -= $subVal;
            if(
$val 0) break;
        }
        
$val += $subVal;
        
$n -= $elmWidth;
        
$widths[$bar] = $elmWidth;
    }
    
$widths[$bar] = $n;
    return 
$widths;
}

/* Zwraca kod jaki trzeba przekazać do funkcji getRSSwidths,
 * by uzyskać szerokości elementów zewnętrznych słów kodowych */
function getOuterEncodingValue($val) {
    
$table = array(
        
// group_max, Gsum, Todd, Teven, odd_modules, even_modules, odd_widest, even_widest
        
array(    160,    0,    161,    1,    12,    4,    8,    1),
        array(    
960,    161,    80,    10,    10,    6,    6,    3),
        array(    
2014,    961,    31,    34,    8,    8,    4,    5),
        array(    
2714,    2015,    10,    70,    6,    10,    3,    6),
        array(    
2840,    2715,    1,    126,    4,    12,    1,    8),
    );
    
    foreach(
$table as $key) {
        if(
$key[0]<$val) continue;
        
        return array(
            
// (val - Gsum) div Teven
            
'odd' => (int)bcdiv(($val-$key[1]), $key[3]),
            
'odd_modules' => $key[4],
            
'odd_widest' => $key[6],
            
// (val - Gsum) mod Teven
            
'even' => (int)bcmod(($val-$key[1]), $key[3]),
            
'even_modules' => $key[5],
            
'even_widest' => $key[7],
        );
    }
    
    die(
'Błąd w funkcji getOuterEncodingValue - OutOfBound');
}

/* Zwraca kod jaki trzeba przekazać do funkcji getRSSwidths,
 * by uzyskać szerokości elementów wewnętrznych słów kodowych */
function getInnerEncodingValue($val) {
    
$table = array(
        
// group_max, Gsum, Todd, Teven, odd_modules, even_modules, odd_widest, even_widest
        
array(    335,    0,    4,    84,    5,    10,    2,    7),
        array(    
1035,    336,    20,    35,    7,    8,    4,    5),
        array(    
1515,    1036,    48,    10,    9,    6,    6,    3),
        array(    
1596,    1516,    81,    1,    11,    4,    8,    1),
    );
    
    foreach(
$table as $key) {
        if(
$key[0]<$val) continue;
        
        return array(
            
// (val - Gsum) div Todd
            
'even' => (int)bcdiv(($val-$key[1]), $key[2]),
            
'even_modules' => $key[5],
            
'even_widest' => $key[7],
            
// (val - Gsum) mod Todd
            
'odd' => (int)bcmod(($val-$key[1]), $key[2]),
            
'odd_modules' => $key[4],
            
'odd_widest' => $key[6],
        );
    }
    
    die(
'Błąd w funkcji getInnerEncodingValue - OutOfBound');
}

$kod $_GET['kod'];
if(!
ctype_digit($kod) || strlen($kod)>13) {
    die(
'Kod musi mieć 13 cyfr (bez cyfry kontrolnej)');
}

$code = array(
    
=> array(),
    
=> array(),
    
=> array(),
    
=> array(),
);

$L bcdiv($kod4537077);
$R bcmod($kod4537077);

/* Pierwszy moduł, zewnętrzny */
$d getOuterEncodingValue(bcdiv($L1597));
$d_odd getRSSwidths($d['odd'], $d['odd_modules'], 4$d['odd_widest']);
$d_even getRSSwidths($d['even'], $d['even_modules'], 4$d['even_widest']);

for(
$i=0$i<4$i++) {
    
$code[1][] = $d_odd[$i];
    
$code[1][] = $d_even[$i];
}

/* Drugi moduł, wewnętrzny */
$d getInnerEncodingValue(bcmod($L1597));
$d_odd getRSSwidths($d['odd'], $d['odd_modules'], 4$d['odd_widest']);
$d_even getRSSwidths($d['even'], $d['even_modules'], 4$d['even_widest']);

for(
$i=0$i<4$i++) {
    
$code[2][] = $d_odd[$i];
    
$code[2][] = $d_even[$i];
}

/* Trzeci moduł, zewnętrzny */
$d getOuterEncodingValue(bcdiv($R1597));
$d_odd getRSSwidths($d['odd'], $d['odd_modules'], 4$d['odd_widest']);
$d_even getRSSwidths($d['even'], $d['even_modules'], 4$d['even_widest']);

for(
$i=0$i<4$i++) {
    
$code[3][] = $d_odd[$i];
    
$code[3][] = $d_even[$i];
}

/* Czwarty moduł, wewnętrzny */
$d getInnerEncodingValue(bcmod($R1597));
$d_odd getRSSwidths($d['odd'], $d['odd_modules'], 4$d['odd_widest']);
$d_even getRSSwidths($d['even'], $d['even_modules'], 4$d['even_widest']);

for(
$i=0$i<4$i++) {
    
$code[4][] = $d_odd[$i];
    
$code[4][] = $d_even[$i];
}

function 
controlCharacter($c) {
    
$wagi = array(
        
=> array( 1,  3,  927,  2,  61854),
        
=> array( 4123629,  8247258),
        
=> array(1648653732175174),
        
=> array(6434236949684659),
    );
    
    
$sum 0;
    for(
$i=1$i<=4$i++) {
        foreach(
$c[$i] as $k => $n) {
            
$sum += $wagi[$i][$k]*$n;
            
$sum %= 79;
        }
    }
    
    if(
$sum >= 8$sum++;
    if(
$sum >= 72$sum++;
    
    return 
$sum;
}

$controlCharTable = array(
    array(
38211),
    array(
35511),
    array(
33711),
    array(
31911),
    array(
27411),
    array(
25611),
    array(
23811),
    array(
15711),
    array(
13911),
);

$control controlCharacter($code);
$code['c1'] = $controlCharTable[bcdiv($control9)];
$code['c2'] = $controlCharTable[bcmod($control9)];

unset(
$d$d_odd$d_even$controlCharTable$control);

$code array_merge(array(11), $code[1], $code['c1'], array_reverse($code[2]), $code[4], array_reverse($code['c2']), array_reverse($code[3]), array(11));

$code_bin '';
$now FALSE;
foreach(
$code as $len) {
    if(
$now) {
        
$code_bin .= str_repeat('1'$len);
    }
    else
    {
        
$code_bin .= str_repeat('0'$len);
    }
    
    
$now = !$now;
}

unset(
$code$now$len);

$code_bin str_split($code_bin);

$img imagecreate(9630);
$wht imagecolorallocate($img255255255);
$blc imagecolorallocate($img000);

foreach(
$code_bin as $n => $el) {
    if(
$el == '1') {
        
imageline($img$n1$n30$blc);
    }
}

header('Content-Type: image/png');
imagepng($img);
?>