QRCODE_MAX_VERSION ) { $v = 0; }
$n = isset($n) ? intval($n):0;
if ( $n <= 0 && $n > QRCODE_MAX_SPLIT ) { $n = 0; }
$e = htmlspecialchars(isset($e)?$e:'');
// if no string, no display.
if (empty($d)) return FALSE;
// thx, nao-pon
$d = str_replace("
","\r\n",$d);
$d = strip_tags($d);
// docomo is s-jis encoding
$d = mb_convert_encoding($d,QRCODE_ENCODING,SOURCE_ENCODING);
$addsize = '';
$addparam = '';
if ($s > 0) { $addsize .= "&s=$s"; }
if ($v > 0 && $v <= QRCODE_MAX_VERSION) { $addparam .= "&v=$v"; }
if ($e != '') { $addparam .= "&e=$e"; }
if ($n < 2 || $n > 16) {
$d = rawurlencode($d);
if (!defined('UA_PROFILE') || UA_PROFILE == 'default') {
$result = "
";
} else {
$result = "
";
}
} else {
// パリティを計算
$l=strlen($d);
if ($l>1){
$p=0;
$i=0;
while ($i<$l){
$p=($p ^ ord(substr($d,$i,1)));
$i++;
}
}
// 並べる(本来ならPNGを合成するのがきれいでしょうけどね)
$result = "";
$i=0;
for ($j=1;$j<=$n;$j++) {
$splitdata = substr($d,$i,ceil($l/$n));
$i += ceil($l/$n);
$splitdata = rawurlencode($splitdata);
$result .= "
";
}
$result .= "\n";
}
return $result;
}
// アクションでは、実際の画像を作成
function plugin_qrcode_action()
{
global $vars;
if (!plugin_qrcode_issupported()) {
return FALSE;
}
if (empty($vars['d'])) {
return FALSE;
}
$qr['data'] = rawurldecode($vars['d']);
$qr['size'] = (empty($vars['s'])) ? 1 : $vars['s'];
$qr['ver'] = (empty($vars['v'])) ? 0 : $vars['v'];
$qr['ecc'] = (empty($vars['e'])) ? 'M' : $vars['e'];
$qr['split'] = (empty($vars['m'])) ? 1 : $vars['m'];
$qr['total'] = (empty($vars['n'])) ? 1 : $vars['n'];
$qr['parity'] = (empty($vars['p'])) ? 0 : $vars['p'];
/* Thanks nanashi */
echo QRcode($qr);
exit;
}
// 画像をサポートしているか?
function plugin_qrcode_issupported()
{
$issupported = FALSE;
if (function_exists("gd_info")) {
$gdinfo = gd_info();
if (isset($gdinfo['PNG Support']) && $gdinfo['PNG Support'] === TRUE) {
$issupported = TRUE;
}
}
return $issupported;
}
// 実際にQRコードの画像の中身を作成する
function QRcode($qr)
{
$qrcode_data_string = $qr['data'];
$qrcode_module_size = $qr['size'];
$qrcode_error_correct = $qr['ecc'];
$qrcode_version = $qr['ver'];
$qrcode_structureappend_m = $qr['split'];
$qrcode_structureappend_n = $qr['total'];
$qrcode_structureappend_parity = $qr['parity'];
$data_length = strlen($qrcode_data_string);
if ($data_length<=0) {
trigger_error("QRcode : Data do not exist.", E_USER_ERROR);
return '';
}
$data_counter = 0;
if ($qrcode_structureappend_n>1 && $qrcode_structureappend_n<=16
&& $qrcode_structureappend_m>0 && $qrcode_structureqppend_m<=16)
{
$data_value[0]=3;
$data_bits[0]=4;
$data_value[1]=$qrcode_structureappend_m-1;
$data_bits[1]=4;
$data_value[2]=$qrcode_structureappend_n-1;
$data_bits[2]=4;
$originaldata_length=strlen($qrcode_structureappend_originaldata);
if ($originaldata_length>1){
$qrcode_structureappend_parity=0;
$i=0;
while ($i<$originaldata_length){
$qrcode_structureappend_parity=($qrcode_structureappend_parity ^ ord(substr($qrcode_structureappend_originaldata,$i,1)));
$i++;
}
}
$data_value[3]=$qrcode_structureappend_parity;
$data_bits[3]=8;
$data_counter=4;
}
$data_bits[$data_counter] = 4;
if (!ereg("[^0-9]",$qrcode_data_string))
{
// numeric mode
$codeword_num_plus = array('',
0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
);
$data_value[$datacounter]=1;
$data_counter++;
$data_value[$data_counter]=$data_length;
$data_bits[$data_counter]=10; /* #version 1-9 */
$codeword_num_counter_value=$data_counter;
$i=0;
$data_counter++;
while ($i<$data_length)
{
if (($i % 3)==0)
{
$data_value[$data_counter]=substr($qrcode_data_string,$i,1);
$data_bits[$data_counter]=4;
}
else
{
$data_value[$data_counter]=$data_value[$data_counter]*10+substr($qrcode_data_string,$i,1);
if (($i % 3)==1)
{
$data_bits[$data_counter]=7;
}
else
{
$data_bits[$data_counter]=10;
$data_counter++;
}
}
$i++;
}
}
else if (!ereg("[^0-9A-Z \$\*\%\+\-\.\/\:]",$qrcode_data_string))
{
// alphanum mode
$codeword_num_plus = array('',
0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
);
$data_value[$data_counter]=2;
$data_counter++;
$data_value[$data_counter]=$data_length;
$data_bits[$data_counter]=9; /* #version 1-9 */
$codeword_num_counter_value=$data_counter;
$alphanumeric_character_hash = array(
'0'=> 0,'1'=> 1,'2'=> 2,'3'=> 3,'4'=> 4,'5'=> 5,'6'=> 6,'7'=> 7,'8'=> 8, '9'=>9,
'A'=>10,'B'=>11,'C'=>12,'D'=>13,'E'=>14,'F'=>15,'G'=>16,'H'=>17,'I'=>18,'J'=>19,
'K'=>20,'L'=>21,'M'=>22,'N'=>23,'O'=>24,'P'=>25,'Q'=>26,'R'=>27,'S'=>28,'T'=>29,
'U'=>30,'V'=>31,'W'=>32,'X'=>33,'Y'=>34,'Z'=>35,' '=>36,'$'=>37,'%'=>38,'*'=>39,
'+'=>40,'-'=>41,'.'=>42,'/'=>43,':'=>44
);
$i=0;
$data_counter++;
while ($i<$data_length)
{
if (($i %2)==0)
{
$data_value[$data_counter]=$alphanumeric_character_hash[substr($qrcode_data_string,$i,1)];
$data_bits[$data_counter]=6;
}
else
{
$data_value[$data_counter]=$data_value[$data_counter]*45+$alphanumeric_character_hash[substr($qrcode_data_string,$i,1)];
$data_bits[$data_counter]=11;
$data_counter++;
}
$i++;
}
}
else
{
// binary(8bit) mode
$codeword_num_plus = array('',
0,0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
);
$data_value[$data_counter]=4;
$data_counter++;
$data_value[$data_counter]=$data_length;
$data_bits[$data_counter]=8; /* #version 1-9 */
$codeword_num_counter_value=$data_counter;
$data_counter++;
$i=0;
while ($i<$data_length)
{
$data_value[$data_counter]=ord(substr($qrcode_data_string,$i,1));
$data_bits[$data_counter]=8;
$data_counter++;
$i++;
}
}
if (@$data_bits[$data_counter]>0)
{
$data_counter++;
}
$i=0;
$total_data_bits=0;
while($i<$data_counter)
{
$total_data_bits+=$data_bits[$i];
$i++;
}
$ecc_character_hash=array(
'L'=>'1',
'l'=>'1',
'M'=>'0',
'm'=>'0',
'Q'=>'3',
'q'=>'3',
'H'=>'2',
'h'=>'2'
);
$ec = @$ecc_character_hash[$qrcode_error_correct];
if (!$ec){ $ec=0; }
$max_data_bits_array = array(0,
128, 224, 352, 512, 688, 864, 992, 1232, 1456, 1728,
152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 2192,
72, 128, 208, 288, 368, 480, 528, 688, 800, 976,
104, 176, 272, 384, 496, 608, 704, 880, 1056, 1232,
);
if (!is_numeric($qrcode_version)) {
$qrcode_version=0;
}
// バージョンを設定していないときは、自動的に設定
if (!$qrcode_version)
{
$i= 1 + (QRCODE_MAX_VERSION * $ec);
$j= $i + (QRCODE_MAX_VERSION - 1);
$qrcode_version=1;
while ($i<=$j)
{
if (($max_data_bits_array[$i])>=$total_data_bits+$codeword_num_plus[$qrcode_version])
{
$max_data_bits=$max_data_bits_array[$i];
break;
}
$i++;
$qrcode_version++;
}
}
else
{
$max_data_bits=$max_data_bits_array[$qrcode_version+(QRCODE_MAX_VERSION * $ec)];
}
if ($qrcode_version > QRCODE_MAX_VERSION) {
trigger_error("QRcode : too large version.", E_USER_ERROR);
return '';
}
$total_data_bits+=$codeword_num_plus[$qrcode_version];
$data_bits[$codeword_num_counter_value]+=$codeword_num_plus[$qrcode_version];
$max_codewords_array = array(0,
26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
404, 466, 532, 581, 655, 733, 815, 901, 991,1085,
1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,
2323,2465,2611,2761,2876,3034,3196,3362,3532,3706
);
$max_codewords=$max_codewords_array[$qrcode_version];
$max_modules_1side=17+($qrcode_version <<2);
$matrix_remain_bit = array(0,
0,7,7,7,7,7,0,0,0,0,
0,0,0,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,3,3,3,
3,3,3,3,0,0,0,0,0,0
);
/* read version ECC data file */
$byte_num=$matrix_remain_bit[$qrcode_version]+($max_codewords << 3);
$filename=QRCODE_DATA_DIR ."/qrv".$qrcode_version."_".$ec.".dat";
$fp1=fopen($filename,"rb");
$matx=fread($fp1,$byte_num);
$maty=fread($fp1,$byte_num);
$masks=fread($fp1,$byte_num);
$fi_x=fread($fp1,15);
$fi_y=fread($fp1,15);
$rs_ecc_codewords=ord(fread($fp1,1));
$rso=fread($fp1,128);
fclose($fp1);
$matrix_x_array=unpack("C*",$matx);
$matrix_y_array=unpack("C*",$maty);
$mask_array=unpack("C*",$masks);
$rs_block_order=unpack("C*",$rso);
$format_information_x2=unpack("C*",$fi_x);
$format_information_y2=unpack("C*",$fi_y);
$format_information_x1=array(0,1,2,3,4,5,7,8,8,8,8,8,8,8,8);
$format_information_y1=array(8,8,8,8,8,8,8,8,7,5,4,3,2,1,0);
$max_data_codewords=($max_data_bits >>3);
$filename = QRCODE_DATA_DIR ."/rsc".$rs_ecc_codewords.".dat";
$fp0 = fopen($filename,"rb");
$i=0;
while ($i<256)
{
$rs_cal_table_array[$i]=fread($fp0,$rs_ecc_codewords);
$i++;
}
fclose ($fp0);
/* --- set terminator */
if ($total_data_bits<=$max_data_bits-4)
{
$data_value[$data_counter]=0;
$data_bits[$data_counter]=4;
} else {
if ($total_data_bits<$max_data_bits) {
$data_value[$data_counter]=0;
$data_bits[$data_counter]=$max_data_bits-$total_data_bits;
} else {
if ($total_data_bits>$max_data_bits) {
trigger_error("QRcode : Overflow error",E_USER_ERROR);
return '';
}
}
}
/* ----divide data by 8bit */
$i=0;
$codewords_counter=0;
$codewords[0]=0;
$remaining_bits=8;
while ($i<=$data_counter) {
$buffer=@$data_value[$i];
$buffer_bits=@$data_bits[$i];
$flag=1;
while ($flag) {
if ($remaining_bits>$buffer_bits){
$codewords[$codewords_counter]=((@$codewords[$codewords_counter]<<$buffer_bits) | $buffer);
$remaining_bits-=$buffer_bits;
$flag=0;
} else {
$buffer_bits-=$remaining_bits;
$codewords[$codewords_counter]=(($codewords[$codewords_counter] << $remaining_bits) | ($buffer >> $buffer_bits));
if ($buffer_bits==0) {
$flag=0;
} else {
$buffer= ($buffer & ((1 << $buffer_bits)-1) );
$flag=1;
}
$codewords_counter++;
if ($codewords_counter<$max_data_codewords-1){
$codewords[$codewords_counter]=0;
}
$remaining_bits=8;
}
}
$i++;
}
if ($remaining_bits!=8) {
$codewords[$codewords_counter]=$codewords[$codewords_counter] << $remaining_bits;
} else {
$codewords_counter--;
}
/* ---- set padding character */
if ($codewords_counter<$max_data_codewords-1){
$flag=1;
while ($codewords_counter<$max_data_codewords-1){
$codewords_counter++;
if ($flag==1) {
$codewords[$codewords_counter]=236;
} else {
$codewords[$codewords_counter]=17;
}
$flag=$flag*(-1);
}
}
/* ---- RS-ECC prepare */
$i=0;
$j=0;
$rs_block_number=0;
$rs_temp[0]="";
while($i<$max_data_codewords){
$rs_temp[$rs_block_number].=chr($codewords[$i]);
$j++;
if ($j>=$rs_block_order[$rs_block_number+1]-$rs_ecc_codewords){
$j=0;
$rs_block_number++;
$rs_temp[$rs_block_number]="";
}
$i++;
}
/*
#
# RS-ECC main
#
*/
$rs_block_number=0;
$rs_block_order_num=count($rs_block_order);
while ($rs_block_number<$rs_block_order_num){
$rs_codewords=$rs_block_order[$rs_block_number+1];
$rs_data_codewords=$rs_codewords-$rs_ecc_codewords;
$rstemp=$rs_temp[$rs_block_number].str_repeat(chr(0),$rs_ecc_codewords);
$padding_data=str_repeat(chr(0),$rs_data_codewords);
$j=$rs_data_codewords;
while($j>0){
$first=ord(substr($rstemp,0,1));
if ($first){
$left_chr=substr($rstemp,1);
$cal=$rs_cal_table_array[$first].$padding_data;
$rstemp=$left_chr ^ $cal;
} else {
$rstemp=substr($rstemp,1);
}
$j--;
}
$codewords=array_merge($codewords,unpack("C*",$rstemp));
$rs_block_number++;
}
// マトリックスの初期化
// for ($i=0;$i<$max_modules_1side;$i++) {
// for ($j=0;$j<$max_modules_1side;$j++) {
// $matrix_content[$j][$i]=0;
// }
// }
$matrix_content = array(array());
// データの埋め込み
$i=0;
while ($i<$max_codewords)
{
$codeword_i=$codewords[$i];
$j=8;
while ($j>=1) {
$codeword_bits_number=($i << 3) + $j;
$matrix_content[ $matrix_x_array[$codeword_bits_number] ][ $matrix_y_array[$codeword_bits_number] ]=((255*($codeword_i & 1)) ^ $mask_array[$codeword_bits_number] );
$codeword_i= $codeword_i >> 1;
$j--;
}
$i++;
}
$matrix_remain=$matrix_remain_bit[$qrcode_version];
while ($matrix_remain)
{
$remain_bit_temp = $matrix_remain + ( $max_codewords <<3);
$matrix_content[ $matrix_x_array[$remain_bit_temp] ][ $matrix_y_array[$remain_bit_temp] ] = ( 255 ^ $mask_array[$remain_bit_temp] );
$matrix_remain--;
}
#--- mask select
$min_demerit_score=0;
$hor_master="";
$ver_master="";
$k=0;
while($k<$max_modules_1side){
$l=0;
while($l<$max_modules_1side){
$hor_master=$hor_master.chr(isset($matrix_content[$l][$k])?$matrix_content[$l][$k]:0);
$ver_master=$ver_master.chr(isset($matrix_content[$k][$l])?$matrix_content[$k][$l]:0);
$l++;
}
$k++;
}
$i=0;
$all_matrix=$max_modules_1side * $max_modules_1side;
while ($i<8){
$demerit_n1=0;
$ptn_temp=array();
$bit= 1<< $i;
$bit_r=(~$bit)&255;
$bit_mask=str_repeat(chr($bit),$all_matrix);
$hor = $hor_master & $bit_mask;
$ver = $ver_master & $bit_mask;
$ver_shift1=$ver.str_repeat(chr(170),$max_modules_1side);
$ver_shift2=str_repeat(chr(170),$max_modules_1side).$ver;
$ver_shift1_0=$ver.str_repeat(chr(0),$max_modules_1side);
$ver_shift2_0=str_repeat(chr(0),$max_modules_1side).$ver;
$ver_or=chunk_split(~($ver_shift1 | $ver_shift2),$max_modules_1side,chr(170));
$ver_and=chunk_split(~($ver_shift1 & $ver_shift2),$max_modules_1side,chr(170));
$hor=chunk_split(~$hor,$max_modules_1side,chr(170));
$ver=chunk_split(~$ver,$max_modules_1side,chr(170));
$hor=$hor.chr(170).$ver;
$n1_search="/".str_repeat(chr(255),5)."+|".str_repeat(chr($bit_r),5)."+/";
$n3_search=chr($bit_r).chr(255).chr($bit_r).chr($bit_r).chr($bit_r).chr(255).chr($bit_r);
$demerit_n3=substr_count($hor,$n3_search)*40;
$demerit_n4=floor(abs(( (100* (substr_count($ver,chr($bit_r))/($byte_num)) )-50)/5))*10;
$n2_search1="/".chr($bit_r).chr($bit_r)."+/";
$n2_search2="/".chr(255).chr(255)."+/";
$demerit_n2=0;
preg_match_all($n2_search1,$ver_and,$ptn_temp);
foreach($ptn_temp[0] as $str_temp){
$demerit_n2+=(strlen($str_temp)-1);
}
$ptn_temp=array();
preg_match_all($n2_search2,$ver_or,$ptn_temp);
foreach($ptn_temp[0] as $str_temp){
$demerit_n2+=(strlen($str_temp)-1);
}
$demerit_n2*=3;
$ptn_temp=array();
preg_match_all($n1_search,$hor,$ptn_temp);
foreach($ptn_temp[0] as $str_temp){
$demerit_n1+=(strlen($str_temp)-2);
}
$demerit_score=$demerit_n1+$demerit_n2+$demerit_n3+$demerit_n4;
if ($demerit_score<=$min_demerit_score || $i==0){
$mask_number=$i;
$min_demerit_score=$demerit_score;
}
$i++;
}
$mask_content=1 << $mask_number;
# --- format information
$format_information_value=(($ec << 3) | $mask_number);
$format_information_array=array(
"101010000010010","101000100100101","101111001111100","101101101001011",
"100010111111001","100000011001110","100111110010111","100101010100000",
"111011111000100","111001011110011","111110110101010","111100010011101",
"110011000101111","110001100011000","110110001000001","110100101110110",
"001011010001001","001001110111110","001110011100111","001100111010000",
"000011101100010","000001001010101","000110100001100","000100000111011",
"011010101011111","011000001101000","011111100110001","011101000000110",
"010010010110100","010000110000011","010111011011010","010101111101101"
);
$i=0;
while ($i<15){
$content=substr($format_information_array[$format_information_value],$i,1);
$matrix_content[$format_information_x1[$i]][$format_information_y1[$i]]=$content * 255;
$matrix_content[$format_information_x2[$i+1]][$format_information_y2[$i+1]]=$content * 255;
$i++;
}
$mib = $max_modules_1side + 8;
$qrcode_image_size = $mib * $qrcode_module_size;
if ($qrcode_image_size>1480){
trigger_error("QRcode : Too large image size",E_USER_ERROR);
return '';
}
$output_image = ImageCreateTrueColor($qrcode_image_size,$qrcode_image_size);
$base_image = ImageCreateFromPNG(QRCODE_IMAGE_DIR ."/qrv".$qrcode_version.".png");
$col[1]=ImageColorAllocate($base_image, 0, 0, 0);
$col[0]=ImageColorAllocate($base_image,255,255,255);
// 4 is white-pixel margin
$i = 4;
$mxe = 4 + $max_modules_1side;
$ii = 0;
while ($i<$mxe) {
$j=4;
$jj=0;
while ($j<$mxe) {
if (isset($matrix_content[$ii][$jj]) && ($matrix_content[$ii][$jj] & $mask_content)) {
ImageSetPixel($base_image,$i,$j,$col[1]);
}
$j++;
$jj++;
}
$i++;
$ii++;
}
/* Output Images(Thanks nanashi) */
if (ImageTypes() & IMG_GIF) {
header("Content-type: image/gif");
} else {
header("Content-type: image/png");
}
ImageCopyResized($output_image,$base_image,0,0,0,0,$qrcode_image_size,$qrcode_image_size,$mib,$mib);
ImageTrueColorToPalette($output_image,false,2);
if (ImageTypes() & IMG_GIF) {
ImageGif($output_image);
} else {
ImagePng($output_image);
}
}
?>