PageRenderTime 70ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/library/html2pdf/_mypdf/03_fpdf_alpha.class.php

https://bitbucket.org/astawiarski/openemr
PHP | 327 lines | 246 code | 29 blank | 52 comment | 47 complexity | 8ea98ac3549289604908d1f22581be3b MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0, MPL-2.0
  1. <?php
  2. /*************************************************************************
  3. * http://staff.dasdeck.de/valentin/fpdf/fpdf_alpha/
  4. *
  5. * @author Valentin Schmidt
  6. *
  7. * This script allows to use images (PNGs or JPGs) with alpha-channels.
  8. * The alpha-channel can be either supplied as separate 8-bit PNG ("mask"),
  9. * or, for PNGs, also an internal alpha-channel can be used.
  10. * For the latter, the GD 2.x extension is required.
  11. ************************************************************************/
  12. if (!defined('__CLASS_FPDF_ALPHA__'))
  13. {
  14. define('__CLASS_FPDF_ALPHA__', true);
  15. require_once(dirname(__FILE__).'/02_fpdf_formulaire.class.php');
  16. class FPDF_Alpha extends FPDF_Formulaire
  17. {
  18. var $tmpFiles = array();
  19. function FPDF_Alpha($orientation='P',$unit='mm',$format='A4')
  20. {
  21. $this->FPDF_Formulaire($orientation,$unit,$format);
  22. }
  23. /* Public methods */
  24. function Image($file,$x,$y,$w=0,$h=0,$type='',$link='', $isMask=false, $maskImg=0)
  25. {
  26. //Put an image on the page
  27. if(!isset($this->images[$file]))
  28. {
  29. //First use of image, get info
  30. if($type=='')
  31. {
  32. /* MODIFICATION HTML2PDF pour le support des images générées */
  33. $type = explode('?', $file);
  34. $type = pathinfo($type[0]);
  35. if (!isset($type['extension']) || !$type['extension'])
  36. $type['extension'] = 'php';
  37. // $this->Error('Image file has no extension and no type was specified: '.$file);
  38. $type = $type['extension'];
  39. /* FIN MODIFICATION */
  40. /*
  41. $pos=strrpos($file,'.');
  42. if(!$pos)
  43. $this->Error('Image file has no extension and no type was specified: '.$file);
  44. $type=substr($file,$pos+1);
  45. */
  46. }
  47. $type=strtolower($type);
  48. /* MODIFICATION HTML2PDF pour le support des images générées */
  49. if ($type=='php' || $type=='cgi')
  50. {
  51. // identification des infos
  52. $infos=@GetImageSize($file);
  53. if (!$infos) $this->Error('Unsupported image : '.$file);
  54. // identification du type
  55. $type = explode('/', $infos['mime']);
  56. if ($type[0]!='image') $this->Error('Unsupported image : '.$file);
  57. $type = $type[1];
  58. }
  59. /* FIN MODIFICATION */
  60. // $mqr=get_magic_quotes_runtime();
  61. // set_magic_quotes_runtime(0);
  62. if($type=='jpg' || $type=='jpeg')
  63. $info=$this->_parsejpg($file);
  64. elseif($type=='png')
  65. {
  66. $info=$this->_parsepng($file);
  67. if ($info=='alpha')
  68. return $this->ImagePngWithAlpha($file,$x,$y,$w,$h,$link);
  69. }
  70. else
  71. {
  72. //Allow for additional formats
  73. $mtd='_parse'.$type;
  74. if(!method_exists($this,$mtd))
  75. $this->Error('Unsupported image type: '.$type);
  76. $info=$this->$mtd($file);
  77. }
  78. // set_magic_quotes_runtime($mqr);
  79. if ($isMask)
  80. {
  81. $info['cs']="DeviceGray"; // try to force grayscale (instead of indexed)
  82. }
  83. $info['i']=count($this->images)+1;
  84. if ($maskImg>0) $info['masked'] = $maskImg;###
  85. $this->images[$file]=$info;
  86. }
  87. else
  88. $info=$this->images[$file];
  89. //Automatic width and height calculation if needed
  90. if($w==0 && $h==0)
  91. {
  92. //Put image at 72 dpi
  93. $w=$info['w']/$this->k;
  94. $h=$info['h']/$this->k;
  95. }
  96. if($w==0)
  97. $w=$h*$info['w']/$info['h'];
  98. if($h==0)
  99. $h=$w*$info['h']/$info['w'];
  100. if ($isMask) // embed hidden, ouside the canvas
  101. {
  102. $x = ($this->CurOrientation=='P'?$this->CurPageFormat[0]*2:$this->CurPageFormat[1]*2) + 10;
  103. }
  104. else // modification by spipu :) pas besoin de tracer l'image si c'est pour faire un mask !!!!
  105. {
  106. $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i']));
  107. if($link) $this->Link($x,$y,$w,$h,$link);
  108. }
  109. return $info['i'];
  110. }
  111. // needs GD 2.x extension
  112. // pixel-wise operation, not very fast
  113. function ImagePngWithAlpha($file,$x,$y,$w=0,$h=0,$link='')
  114. {
  115. $tmp_alpha = tempnam(null, 'mska');
  116. $this->tmpFiles[] = $tmp_alpha;
  117. $tmp_plain = tempnam(null, 'mskp');
  118. $this->tmpFiles[] = $tmp_plain;
  119. list($wpx, $hpx) = @getimagesize($file);
  120. $img = imagecreatefrompng($file);
  121. $alpha_img = imagecreate( $wpx, $hpx );
  122. // generate gray scale pallete
  123. for($c=0;$c<256;$c++) ImageColorAllocate($alpha_img, $c, $c, $c);
  124. // extract alpha channel
  125. $xpx=0;
  126. while ($xpx<$wpx)
  127. {
  128. $ypx = 0;
  129. while ($ypx<$hpx)
  130. {
  131. $color_index = imagecolorat($img, $xpx, $ypx);
  132. $col = imagecolorsforindex($img, $color_index);
  133. imagesetpixel($alpha_img, $xpx, $ypx, $this->_gamma( (127-$col['alpha'])*255/127) );
  134. ++$ypx;
  135. }
  136. ++$xpx;
  137. }
  138. imagepng($alpha_img, $tmp_alpha);
  139. imagedestroy($alpha_img);
  140. // extract image without alpha channel
  141. $plain_img = imagecreatetruecolor ( $wpx, $hpx );
  142. imagecopy ($plain_img, $img, 0, 0, 0, 0, $wpx, $hpx );
  143. imagepng($plain_img, $tmp_plain);
  144. imagedestroy($plain_img);
  145. //first embed mask image (w, h, x, will be ignored)
  146. $maskImg = $this->Image($tmp_alpha, 0,0,0,0, 'PNG', '', true);
  147. //embed image, masked with previously embedded mask
  148. $this->Image($tmp_plain,$x,$y,$w,$h,'PNG',$link, false, $maskImg);
  149. }
  150. function Close()
  151. {
  152. parent::Close();
  153. // clean up tmp files
  154. foreach($this->tmpFiles as $tmp) @unlink($tmp);
  155. }
  156. /* Private methods */
  157. function _putimages()
  158. {
  159. $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
  160. reset($this->images);
  161. while(list($file,$info)=each($this->images))
  162. {
  163. $this->_newobj();
  164. $this->images[$file]['n']=$this->n;
  165. $this->_out('<</Type /XObject');
  166. $this->_out('/Subtype /Image');
  167. $this->_out('/Width '.$info['w']);
  168. $this->_out('/Height '.$info['h']);
  169. if (isset($info["masked"])) $this->_out('/SMask '.($this->n-1).' 0 R'); ###
  170. if($info['cs']=='Indexed')
  171. $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
  172. else
  173. {
  174. $this->_out('/ColorSpace /'.$info['cs']);
  175. if($info['cs']=='DeviceCMYK')
  176. $this->_out('/Decode [1 0 1 0 1 0 1 0]');
  177. }
  178. $this->_out('/BitsPerComponent '.$info['bpc']);
  179. if(isset($info['f']))
  180. $this->_out('/Filter /'.$info['f']);
  181. if(isset($info['parms']))
  182. $this->_out($info['parms']);
  183. if(isset($info['trns']) && is_array($info['trns']))
  184. {
  185. $trns='';
  186. for($i=0;$i<count($info['trns']);$i++)
  187. $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
  188. $this->_out('/Mask ['.$trns.']');
  189. }
  190. $this->_out('/Length '.strlen($info['data']).'>>');
  191. $this->_putstream($info['data']);
  192. unset($this->images[$file]['data']);
  193. $this->_out('endobj');
  194. //Palette
  195. if($info['cs']=='Indexed')
  196. {
  197. $this->_newobj();
  198. $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
  199. $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
  200. $this->_putstream($pal);
  201. $this->_out('endobj');
  202. }
  203. }
  204. }
  205. // GD seems to use a different gamma, this method is used to correct it again
  206. function _gamma($v)
  207. {
  208. return pow ($v/255, 2.2) * 255;
  209. }
  210. // this method overwriing the original version is only needed to make the Image method support PNGs with alpha channels.
  211. // if you only use the ImagePngWithAlpha method for such PNGs, you can remove it from this script.
  212. function _parsepng($file)
  213. {
  214. //Extract info from a PNG file
  215. $f=fopen($file,'rb');
  216. if(!$f)
  217. $this->Error('Can\'t open image file: '.$file);
  218. //Check signature
  219. if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
  220. $this->Error('Not a PNG file: '.$file);
  221. //Read header chunk
  222. fread($f,4);
  223. if(fread($f,4)!='IHDR')
  224. $this->Error('Incorrect PNG file: '.$file);
  225. $w=$this->_readint($f);
  226. $h=$this->_readint($f);
  227. $bpc=ord(fread($f,1));
  228. if($bpc>8)
  229. $this->Error('16-bit depth not supported: '.$file);
  230. $ct=ord(fread($f,1));
  231. if($ct==0)
  232. $colspace='DeviceGray';
  233. elseif($ct==2)
  234. $colspace='DeviceRGB';
  235. elseif($ct==3)
  236. $colspace='Indexed';
  237. else
  238. {
  239. fclose($f); // the only changes are
  240. return 'alpha'; // made in those 2 lines
  241. }
  242. if(ord(fread($f,1))!=0)
  243. $this->Error('Unknown compression method: '.$file);
  244. if(ord(fread($f,1))!=0)
  245. $this->Error('Unknown filter method: '.$file);
  246. if(ord(fread($f,1))!=0)
  247. $this->Error('Interlacing not supported: '.$file);
  248. fread($f,4);
  249. $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
  250. //Scan chunks looking for palette, transparency and image data
  251. $pal='';
  252. $trns='';
  253. $data='';
  254. do
  255. {
  256. $n=$this->_readint($f);
  257. $type=fread($f,4);
  258. if($type=='PLTE')
  259. {
  260. //Read palette
  261. $pal=fread($f,$n);
  262. fread($f,4);
  263. }
  264. elseif($type=='tRNS')
  265. {
  266. //Read transparency info
  267. $t=fread($f,$n);
  268. if($ct==0)
  269. $trns=array(ord(substr($t,1,1)));
  270. elseif($ct==2)
  271. $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
  272. else
  273. {
  274. $pos=strpos($t,chr(0));
  275. if($pos!==false)
  276. $trns=array($pos);
  277. }
  278. fread($f,4);
  279. }
  280. elseif($type=='IDAT')
  281. {
  282. //Read image data block
  283. $data.=fread($f,$n);
  284. fread($f,4);
  285. }
  286. elseif($type=='IEND')
  287. break;
  288. else
  289. fread($f,$n+4);
  290. }
  291. while($n);
  292. if($colspace=='Indexed' && empty($pal))
  293. $this->Error('Missing palette in '.$file);
  294. fclose($f);
  295. return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);
  296. }
  297. }
  298. }