<?php/* * PHP QR Code encoder * * Main encoder classes. * * Based on libqrencode C library distributed under LGPL 2.1 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> * * PHP QR Code is distributed under LGPL 3 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */classQRrsblock{public$dataLength;public$data=array();public$eccLength;public$ecc=array();publicfunction__construct($dl,$data,$el,&$ecc,QRrsItem$rs){$rs->encode_rs_char($data,$ecc);$this->dataLength=$dl;$this->data=$data;$this->eccLength=$el;$this->ecc=$ecc;}};//##########################################################################classQRrawcode{public$version;public$datacode=array();public$ecccode=array();public$blocks;public$rsblocks=array();//of RSblockpublic$count;public$dataLength;public$eccLength;public$b1;//----------------------------------------------------------------------publicfunction__construct(QRinput$input){$spec=array(0,0,0,0,0);$this->datacode=$input->getByteStream();if(is_null($this->datacode)){thrownewException('null imput string');}QRspec::getEccSpec($input->getVersion(),$input->getErrorCorrectionLevel(),$spec);$this->version=$input->getVersion();$this->b1=QRspec::rsBlockNum1($spec);$this->dataLength=QRspec::rsDataLength($spec);$this->eccLength=QRspec::rsEccLength($spec);$this->ecccode=array_fill(0,$this->eccLength,0);$this->blocks=QRspec::rsBlockNum($spec);$ret=$this->init($spec);if($ret<0){thrownewException('block alloc error');returnnull;}$this->count=0;}//----------------------------------------------------------------------publicfunctioninit(array$spec){$dl=QRspec::rsDataCodes1($spec);$el=QRspec::rsEccCodes1($spec);$rs=QRrs::init_rs(8,0x11d,0,1,$el,255-$dl-$el);$blockNo=0;$dataPos=0;$eccPos=0;for($i=0;$i<QRspec::rsBlockNum1($spec);$i++){$ecc=array_slice($this->ecccode,$eccPos);$this->rsblocks[$blockNo]=newQRrsblock($dl,array_slice($this->datacode,$dataPos),$el,$ecc,$rs);$this->ecccode=array_merge(array_slice($this->ecccode,0,$eccPos),$ecc);$dataPos+=$dl;$eccPos+=$el;$blockNo++;}if(QRspec::rsBlockNum2($spec)==0)return0;$dl=QRspec::rsDataCodes2($spec);$el=QRspec::rsEccCodes2($spec);$rs=QRrs::init_rs(8,0x11d,0,1,$el,255-$dl-$el);if($rs==NULL)return-1;for($i=0;$i<QRspec::rsBlockNum2($spec);$i++){$ecc=array_slice($this->ecccode,$eccPos);$this->rsblocks[$blockNo]=newQRrsblock($dl,array_slice($this->datacode,$dataPos),$el,$ecc,$rs);$this->ecccode=array_merge(array_slice($this->ecccode,0,$eccPos),$ecc);$dataPos+=$dl;$eccPos+=$el;$blockNo++;}return0;}//----------------------------------------------------------------------publicfunctiongetCode(){$ret;if($this->count<$this->dataLength){$row=$this->count%$this->blocks;$col=$this->count/$this->blocks;if($col>=$this->rsblocks[0]->dataLength){$row+=$this->b1;}$ret=$this->rsblocks[$row]->data[$col];}elseif($this->count<$this->dataLength+$this->eccLength){$row=($this->count-$this->dataLength)%$this->blocks;$col=($this->count-$this->dataLength)/$this->blocks;$ret=$this->rsblocks[$row]->ecc[$col];}else{return0;}$this->count++;return$ret;}}//##########################################################################classQRcode{public$version;public$width;public$data;//----------------------------------------------------------------------publicfunctionencodeMask(QRinput$input,$mask){if($input->getVersion()<0||$input->getVersion()>QRSPEC_VERSION_MAX){thrownewException('wrong version');}if($input->getErrorCorrectionLevel()>QR_ECLEVEL_H){thrownewException('wrong level');}$raw=newQRrawcode($input);QRtools::markTime('after_raw');$version=$raw->version;$width=QRspec::getWidth($version);$frame=QRspec::newFrame($version);$filler=newFrameFiller($width,$frame);if(is_null($filler)){returnNULL;}// inteleaved data and ecc codesfor($i=0;$i<$raw->dataLength+$raw->eccLength;$i++){$code=$raw->getCode();$bit=0x80;for($j=0;$j<8;$j++){$addr=$filler->next();$filler->setFrameAt($addr,0x02|(($bit&$code)!=0));$bit=$bit>>1;}}QRtools::markTime('after_filler');unset($raw);// remainder bits$j=QRspec::getRemainder($version);for($i=0;$i<$j;$i++){$addr=$filler->next();$filler->setFrameAt($addr,0x02);}$frame=$filler->frame;unset($filler);// masking$maskObj=newQRmask();if($mask<0){if(QR_FIND_BEST_MASK){$masked=$maskObj->mask($width,$frame,$input->getErrorCorrectionLevel());}else{$masked=$maskObj->makeMask($width,$frame,(intval(QR_DEFAULT_MASK)%8),$input->getErrorCorrectionLevel());}}else{$masked=$maskObj->makeMask($width,$frame,$mask,$input->getErrorCorrectionLevel());}if($masked==NULL){returnNULL;}QRtools::markTime('after_mask');$this->version=$version;$this->width=$width;$this->data=$masked;return$this;}//----------------------------------------------------------------------publicfunctionencodeInput(QRinput$input){return$this->encodeMask($input,-1);}//----------------------------------------------------------------------publicfunctionencodeString8bit($string,$version,$level){if(string==NULL){thrownewException('empty string!');returnNULL;}$input=newQRinput($version,$level);if($input==NULL)returnNULL;$ret=$input->append($input,QR_MODE_8,strlen($string),str_split($string));if($ret<0){unset($input);returnNULL;}return$this->encodeInput($input);}//----------------------------------------------------------------------publicfunctionencodeString($string,$version,$level,$hint,$casesensitive){if($hint!=QR_MODE_8&&$hint!=QR_MODE_KANJI){thrownewException('bad hint');returnNULL;}$input=newQRinput($version,$level);if($input==NULL)returnNULL;$ret=QRsplit::splitStringToQRinput($string,$input,$hint,$casesensitive);if($ret<0){returnNULL;}return$this->encodeInput($input);}//----------------------------------------------------------------------publicstaticfunctionpng($text,$outfile=false,$level=QR_ECLEVEL_L,$size=3,$margin=4,$saveandprint=false){$enc=QRencode::factory($level,$size,$margin);return$enc->encodePNG($text,$outfile,$saveandprint=false);}//----------------------------------------------------------------------publicstaticfunctionjpg($text,$outfile=false,$level=QR_ECLEVEL_L,$size=3,$margin=4,$saveandprint=false){$enc=QRencode::factory($level,$size,$margin);return$enc->encodeJPG($text,$outfile,$saveandprint=false);}//----------------------------------------------------------------------publicstaticfunctionsvg($text,$outfile=false,$level=QR_ECLEVEL_L,$margin=4){$enc=QRencode::factory($level,1,$margin);return$enc->encodeSVG($text,$outfile,$saveandprint=false);}//----------------------------------------------------------------------publicstaticfunctiontext($text,$outfile=false,$level=QR_ECLEVEL_L,$size=3,$margin=4){$enc=QRencode::factory($level,$size,$margin);return$enc->encode($text,$outfile);}//----------------------------------------------------------------------publicstaticfunctionraw($text,$outfile=false,$level=QR_ECLEVEL_L,$size=3,$margin=4){$enc=QRencode::factory($level,$size,$margin);return$enc->encodeRAW($text,$outfile);}}//##########################################################################classFrameFiller{public$width;public$frame;public$x;public$y;public$dir;public$bit;//----------------------------------------------------------------------publicfunction__construct($width,&$frame){$this->width=$width;$this->frame=$frame;$this->x=$width-1;$this->y=$width-1;$this->dir=-1;$this->bit=-1;}//----------------------------------------------------------------------publicfunctionsetFrameAt($at,$val){$this->frame[$at['y']][$at['x']]=chr($val);}//----------------------------------------------------------------------publicfunctiongetFrameAt($at){returnord($this->frame[$at['y']][$at['x']]);}//----------------------------------------------------------------------publicfunctionnext(){do{if($this->bit==-1){$this->bit=0;returnarray('x'=>$this->x,'y'=>$this->y);}$x=$this->x;$y=$this->y;$w=$this->width;if($this->bit==0){$x--;$this->bit++;}else{$x++;$y+=$this->dir;$this->bit--;}if($this->dir<0){if($y<0){$y=0;$x-=2;$this->dir=1;if($x==6){$x--;$y=9;}}}else{if($y==$w){$y=$w-1;$x-=2;$this->dir=-1;if($x==6){$x--;$y-=8;}}}if($x<0||$y<0)returnnull;$this->x=$x;$this->y=$y;}while(ord($this->frame[$y][$x])&0x80);returnarray('x'=>$x,'y'=>$y);}};//########################################################################## classQRencode{public$casesensitive=true;public$eightbit=false;public$version=0;public$size=3;public$margin=4;public$structured=0;// not supported yetpublic$level=QR_ECLEVEL_L;public$hint=QR_MODE_8;//----------------------------------------------------------------------publicstaticfunctionfactory($level=QR_ECLEVEL_L,$size=3,$margin=4){$enc=newQRencode();$enc->size=$size;$enc->margin=$margin;switch($level.''){case'0':case'1':case'2':case'3':$enc->level=$level;break;case'l':case'L':$enc->level=QR_ECLEVEL_L;break;case'm':case'M':$enc->level=QR_ECLEVEL_M;break;case'q':case'Q':$enc->level=QR_ECLEVEL_Q;break;case'h':case'H':$enc->level=QR_ECLEVEL_H;break;}return$enc;}//----------------------------------------------------------------------publicfunctionencodeRAW($intext,$outfile=false){$code=newQRcode();if($this->eightbit){$code->encodeString8bit($intext,$this->version,$this->level);}else{$code->encodeString($intext,$this->version,$this->level,$this->hint,$this->casesensitive);}return$code->data;}//----------------------------------------------------------------------publicfunctionencode($intext,$outfile=false){$code=newQRcode();if($this->eightbit){$code->encodeString8bit($intext,$this->version,$this->level);}else{$code->encodeString($intext,$this->version,$this->level,$this->hint,$this->casesensitive);}QRtools::markTime('after_encode');if($outfile!==false){file_put_contents($outfile,join("\n",QRtools::binarize($code->data)));}else{returnQRtools::binarize($code->data);}}//----------------------------------------------------------------------publicfunctionencodePNG($intext,$outfile=false,$saveandprint=false){try{ob_start();$tab=$this->encode($intext);$err=ob_get_contents();ob_end_clean();if($err!='')QRtools::log($outfile,$err);$maxSize=(int)(QR_PNG_MAXIMUM_SIZE/(count($tab)+2*$this->margin));QRimage::png($tab,$outfile,min(max(1,$this->size),$maxSize),$this->margin,$saveandprint);}catch(Exception$e){QRtools::log($outfile,$e->getMessage());}}//----------------------------------------------------------------------publicfunctionencodeSVG($intext,$outfile=false,$saveandprint=false){try{ob_start();$tab=$this->encode($intext);$err=ob_get_contents();ob_end_clean();if($err!='')QRtools::log($outfile,$err);QRimage::svg($tab,$outfile,$this->margin,$saveandprint);}catch(Exception$e){QRtools::log($outfile,$e->getMessage());}}//----------------------------------------------------------------------publicfunctionencodeJPG($intext,$outfile=false,$saveandprint=false){try{ob_start();$tab=$this->encode($intext);$err=ob_get_contents();ob_end_clean();if($err!='')QRtools::log($outfile,$err);$maxSize=(int)(QR_PNG_MAXIMUM_SIZE/(count($tab)+2*$this->margin));QRimage::jpg($tab,$outfile,min(max(1,$this->size),$maxSize),$this->margin,$saveandprint);}catch(Exception$e){QRtools::log($outfile,$e->getMessage());}}}
qrimage.php
<?php/* * PHP QR Code encoder * * Image output of code using GD2 * * PHP QR Code is distributed under LGPL 3 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */define('QR_IMAGE',true);classQRimage{//----------------------------------------------------------------------publicstaticfunctionpng($frame,$filename=false,$pixelPerPoint=4,$outerFrame=4,$saveandprint=FALSE){$image=self::image($frame,$pixelPerPoint,$outerFrame);if($filename===false){Header("Content-type: image/png");ImagePng($image);}else{if($saveandprint===TRUE){ImagePng($image,$filename);header("Content-type: image/png");ImagePng($image);}else{ImagePng($image,$filename);}}ImageDestroy($image);}//----------------------------------------------------------------------publicstaticfunctionjpg($frame,$filename=false,$pixelPerPoint=4,$outerFrame=4,$saveandprint=FALSE){$image=self::image($frame,$pixelPerPoint,$outerFrame);if($filename===false){Header("Content-type: image/jpeg");ImageJpeg($image);}else{if($saveandprint===TRUE){ImageJpeg($image,$filename,100);header("Content-type: image/jpeg");ImageJpeg($image,NULL,100);}else{ImageJpeg($image,$filename,100);}}ImageDestroy($image);}//----------------------------------------------------------------------publicstaticfunctionsvg($frame,$filename=false,$outerFrame=4){$file=self::imageSVG($frame,$outerFrame);if($filename!==false){$fhandle=fopen($filename,'w+');fwrite($fhandle,$file);fclose($fhandle);}unset($file);}//----------------------------------------------------------------------privatestaticfunctionimage($frame,$pixelPerPoint=4,$outerFrame=4){$h=count($frame);$w=strlen($frame[0]);$imgW=$w+2*$outerFrame;$imgH=$h+2*$outerFrame;$base_image=ImageCreateTrueColor($imgW,$imgH);$col[0]=ImageColorAllocate($base_image,255,255,255);$col[1]=ImageColorAllocate($base_image,0,0,0);imagefill($base_image,0,0,$col[0]);for($y=0;$y<$h;$y++){for($x=0;$x<$w;$x++){if($frame[$y][$x]=='1'){ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);}}}$target_image=ImageCreate($imgW*$pixelPerPoint,$imgH*$pixelPerPoint);ImageCopyResampled($target_image,$base_image,0,0,0,0,$imgW*$pixelPerPoint,$imgH*$pixelPerPoint,$imgW,$imgH);ImageDestroy($base_image);return$target_image;}//----------------------------------------------------------------------privatestaticfunctionimageSVG($frame,$outerFrame=4){$h=count($frame);$w=strlen($frame[0]);$imgW=$w+2*$outerFrame;$imgH=$h+2*$outerFrame;$eps_string="<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\r <rect x=\"0\" y=\"0\" width=\"".$imgW."\" height=\"".$imgH."\" style=\"fill:white\"/>\r";for($y=0;$y<$h;$y++){for($x=0;$x<$w;$x++){if($frame[$y][$x]=='1'){$eps_string.=" <rect x=\"".($x+$outerFrame)."\" y=\"".($y+$outerFrame)."\" width=\"1\" height=\"1\" style=\"fill:black\"/>\r";}}}$eps_string.="</svg>";return$eps_string;}}
Now you can generate SVG and JPG formatted QR Codes with:
QRcode::svg($_REQUEST, $filename, $errorCorrectionLevel, 2);
QRcode::jpg($_REQUEST, $filename, $errorCorrectionLevel, $matrixPointSize, 2);
I hope this is helpfull…
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2011-11-26
I tried this and it created the JPG ok, but when I used it to craete an SVG, the file was created but when I try to open it in various programs, I get errors saying it is an invalid format.
Any ideas what could be wrong?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2012-03-28
There's an error in the imageSVG method in the QRImage class in qrimage.php
In the SVG's XML the root element is created like so:
@repox82 Can you just give me the ready-made version?
I used to be good at CFML but recently I moved to PHP and I'm kinda a newbie here… I gave a try to "fixing" the code by myself based on your comments but just cannot make it work!
Would you help a college in need?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Replace the following files with the ones below
qrencode.php
qrimage.php
Now you can generate SVG and JPG formatted QR Codes with:
QRcode::svg($_REQUEST, $filename, $errorCorrectionLevel, 2);
QRcode::jpg($_REQUEST, $filename, $errorCorrectionLevel, $matrixPointSize, 2);
I hope this is helpfull…
I tried this and it created the JPG ok, but when I used it to craete an SVG, the file was created but when I try to open it in various programs, I get errors saying it is an invalid format.
Any ideas what could be wrong?
There's an error in the imageSVG method in the QRImage class in qrimage.php
In the SVG's XML the root element is created like so:
The semicolon after the xmlns attribute 'breaks' the SVG image.
Replace the line:
With this:
Now the SVG image works (althoug small, but works).
Uhm, I see the problem is with the code tag on this site… :/
Well, the problem is the semicolon in the XML root element - I hope you see the point…
@repox82 Can you just give me the ready-made version?
I used to be good at CFML but recently I moved to PHP and I'm kinda a newbie here… I gave a try to "fixing" the code by myself based on your comments but just cannot make it work!
Would you help a college in need?