Added HTML2PDF and FPDI to the project.
[openemr.git] / library / html2pdf / _mypdf / 03_fpdf_alpha.class.php
blob28323979df28af17af330f4f12fecd134f0c19b4
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 ************************************************************************/
14 if (!defined('__CLASS_FPDF_ALPHA__'))
16 define('__CLASS_FPDF_ALPHA__', true);
18 require_once(dirname(__FILE__).'/02_fpdf_formulaire.class.php');
20 class FPDF_Alpha extends FPDF_Formulaire
22 var $tmpFiles = array();
24 function FPDF_Alpha($orientation='P',$unit='mm',$format='A4')
26 $this->FPDF_Formulaire($orientation,$unit,$format);
29 /* Public methods */
30 function Image($file,$x,$y,$w=0,$h=0,$type='',$link='', $isMask=false, $maskImg=0)
32 //Put an image on the page
33 if(!isset($this->images[$file]))
35 //First use of image, get info
36 if($type=='')
38 /* MODIFICATION HTML2PDF pour le support des images générées */
39 $type = explode('?', $file);
40 $type = pathinfo($type[0]);
41 if (!isset($type['extension']) || !$type['extension'])
42 $type['extension'] = 'php';
43 // $this->Error('Image file has no extension and no type was specified: '.$file);
45 $type = $type['extension'];
46 /* FIN MODIFICATION */
48 $pos=strrpos($file,'.');
49 if(!$pos)
50 $this->Error('Image file has no extension and no type was specified: '.$file);
51 $type=substr($file,$pos+1);
54 $type=strtolower($type);
56 /* MODIFICATION HTML2PDF pour le support des images générées */
57 if ($type=='php' || $type=='cgi')
59 // identification des infos
60 $infos=@GetImageSize($file);
61 if (!$infos) $this->Error('Unsupported image : '.$file);
63 // identification du type
64 $type = explode('/', $infos['mime']);
65 if ($type[0]!='image') $this->Error('Unsupported image : '.$file);
66 $type = $type[1];
68 /* FIN MODIFICATION */
70 // $mqr=get_magic_quotes_runtime();
71 // set_magic_quotes_runtime(0);
72 if($type=='jpg' || $type=='jpeg')
73 $info=$this->_parsejpg($file);
74 elseif($type=='png')
76 $info=$this->_parsepng($file);
77 if ($info=='alpha')
78 return $this->ImagePngWithAlpha($file,$x,$y,$w,$h,$link);
80 else
82 //Allow for additional formats
83 $mtd='_parse'.$type;
84 if(!method_exists($this,$mtd))
85 $this->Error('Unsupported image type: '.$type);
86 $info=$this->$mtd($file);
88 // set_magic_quotes_runtime($mqr);
90 if ($isMask)
92 $info['cs']="DeviceGray"; // try to force grayscale (instead of indexed)
94 $info['i']=count($this->images)+1;
95 if ($maskImg>0) $info['masked'] = $maskImg;###
96 $this->images[$file]=$info;
98 else
99 $info=$this->images[$file];
101 //Automatic width and height calculation if needed
102 if($w==0 && $h==0)
104 //Put image at 72 dpi
105 $w=$info['w']/$this->k;
106 $h=$info['h']/$this->k;
108 if($w==0)
109 $w=$h*$info['w']/$info['h'];
110 if($h==0)
111 $h=$w*$info['h']/$info['w'];
113 if ($isMask) // embed hidden, ouside the canvas
115 $x = ($this->CurOrientation=='P'?$this->CurPageFormat[0]*2:$this->CurPageFormat[1]*2) + 10;
117 else // modification by spipu :) pas besoin de tracer l'image si c'est pour faire un mask !!!!
119 $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']));
120 if($link) $this->Link($x,$y,$w,$h,$link);
123 return $info['i'];
126 // needs GD 2.x extension
127 // pixel-wise operation, not very fast
128 function ImagePngWithAlpha($file,$x,$y,$w=0,$h=0,$link='')
130 $tmp_alpha = tempnam(null, 'mska');
131 $this->tmpFiles[] = $tmp_alpha;
132 $tmp_plain = tempnam(null, 'mskp');
133 $this->tmpFiles[] = $tmp_plain;
135 list($wpx, $hpx) = @getimagesize($file);
136 $img = imagecreatefrompng($file);
137 $alpha_img = imagecreate( $wpx, $hpx );
139 // generate gray scale pallete
140 for($c=0;$c<256;$c++) ImageColorAllocate($alpha_img, $c, $c, $c);
142 // extract alpha channel
143 $xpx=0;
144 while ($xpx<$wpx)
146 $ypx = 0;
147 while ($ypx<$hpx)
149 $color_index = imagecolorat($img, $xpx, $ypx);
150 $col = imagecolorsforindex($img, $color_index);
151 imagesetpixel($alpha_img, $xpx, $ypx, $this->_gamma( (127-$col['alpha'])*255/127) );
152 ++$ypx;
154 ++$xpx;
157 imagepng($alpha_img, $tmp_alpha);
158 imagedestroy($alpha_img);
160 // extract image without alpha channel
161 $plain_img = imagecreatetruecolor ( $wpx, $hpx );
162 imagecopy ($plain_img, $img, 0, 0, 0, 0, $wpx, $hpx );
163 imagepng($plain_img, $tmp_plain);
164 imagedestroy($plain_img);
166 //first embed mask image (w, h, x, will be ignored)
167 $maskImg = $this->Image($tmp_alpha, 0,0,0,0, 'PNG', '', true);
169 //embed image, masked with previously embedded mask
170 $this->Image($tmp_plain,$x,$y,$w,$h,'PNG',$link, false, $maskImg);
173 function Close()
175 parent::Close();
176 // clean up tmp files
177 foreach($this->tmpFiles as $tmp) @unlink($tmp);
180 /* Private methods */
181 function _putimages()
183 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
184 reset($this->images);
185 while(list($file,$info)=each($this->images))
187 $this->_newobj();
188 $this->images[$file]['n']=$this->n;
189 $this->_out('<</Type /XObject');
190 $this->_out('/Subtype /Image');
191 $this->_out('/Width '.$info['w']);
192 $this->_out('/Height '.$info['h']);
194 if (isset($info["masked"])) $this->_out('/SMask '.($this->n-1).' 0 R'); ###
196 if($info['cs']=='Indexed')
197 $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
198 else
200 $this->_out('/ColorSpace /'.$info['cs']);
201 if($info['cs']=='DeviceCMYK')
202 $this->_out('/Decode [1 0 1 0 1 0 1 0]');
204 $this->_out('/BitsPerComponent '.$info['bpc']);
205 if(isset($info['f']))
206 $this->_out('/Filter /'.$info['f']);
207 if(isset($info['parms']))
208 $this->_out($info['parms']);
209 if(isset($info['trns']) && is_array($info['trns']))
211 $trns='';
212 for($i=0;$i<count($info['trns']);$i++)
213 $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
214 $this->_out('/Mask ['.$trns.']');
216 $this->_out('/Length '.strlen($info['data']).'>>');
217 $this->_putstream($info['data']);
218 unset($this->images[$file]['data']);
219 $this->_out('endobj');
220 //Palette
221 if($info['cs']=='Indexed')
223 $this->_newobj();
224 $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
225 $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
226 $this->_putstream($pal);
227 $this->_out('endobj');
232 // GD seems to use a different gamma, this method is used to correct it again
233 function _gamma($v)
235 return pow ($v/255, 2.2) * 255;
238 // this method overwriing the original version is only needed to make the Image method support PNGs with alpha channels.
239 // if you only use the ImagePngWithAlpha method for such PNGs, you can remove it from this script.
240 function _parsepng($file)
242 //Extract info from a PNG file
243 $f=fopen($file,'rb');
244 if(!$f)
245 $this->Error('Can\'t open image file: '.$file);
246 //Check signature
247 if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
248 $this->Error('Not a PNG file: '.$file);
249 //Read header chunk
250 fread($f,4);
251 if(fread($f,4)!='IHDR')
252 $this->Error('Incorrect PNG file: '.$file);
253 $w=$this->_readint($f);
254 $h=$this->_readint($f);
255 $bpc=ord(fread($f,1));
256 if($bpc>8)
257 $this->Error('16-bit depth not supported: '.$file);
258 $ct=ord(fread($f,1));
259 if($ct==0)
260 $colspace='DeviceGray';
261 elseif($ct==2)
262 $colspace='DeviceRGB';
263 elseif($ct==3)
264 $colspace='Indexed';
265 else
267 fclose($f); // the only changes are
268 return 'alpha'; // made in those 2 lines
270 if(ord(fread($f,1))!=0)
271 $this->Error('Unknown compression method: '.$file);
272 if(ord(fread($f,1))!=0)
273 $this->Error('Unknown filter method: '.$file);
274 if(ord(fread($f,1))!=0)
275 $this->Error('Interlacing not supported: '.$file);
276 fread($f,4);
277 $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
278 //Scan chunks looking for palette, transparency and image data
279 $pal='';
280 $trns='';
281 $data='';
284 $n=$this->_readint($f);
285 $type=fread($f,4);
286 if($type=='PLTE')
288 //Read palette
289 $pal=fread($f,$n);
290 fread($f,4);
292 elseif($type=='tRNS')
294 //Read transparency info
295 $t=fread($f,$n);
296 if($ct==0)
297 $trns=array(ord(substr($t,1,1)));
298 elseif($ct==2)
299 $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
300 else
302 $pos=strpos($t,chr(0));
303 if($pos!==false)
304 $trns=array($pos);
306 fread($f,4);
308 elseif($type=='IDAT')
310 //Read image data block
311 $data.=fread($f,$n);
312 fread($f,4);
314 elseif($type=='IEND')
315 break;
316 else
317 fread($f,$n+4);
319 while($n);
320 if($colspace=='Indexed' && empty($pal))
321 $this->Error('Missing palette in '.$file);
322 fclose($f);
323 return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);