1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: namespace Mapbender\PrintBundle\Component;
16: use \FPDF_FPDI;
17:
18: class PDF_ImageAlpha extends FPDF_FPDI{
19:
20:
21: var $tmpFiles = array();
22:
23: 24: 25: 26: 27:
28: function Image($file,$x,$y,$w=0,$h=0,$type='',$link='', $isMask=false, $maskImg=0)
29: {
30:
31: if(!isset($this->images[$file]))
32: {
33:
34: if($type=='')
35: {
36: $pos=strrpos($file,'.');
37: if(!$pos)
38: $this->Error('Image file has no extension and no type was specified: '.$file);
39: $type=substr($file,$pos+1);
40: }
41: $type=strtolower($type);
42: $mqr=get_magic_quotes_runtime();
43: set_magic_quotes_runtime(0);
44: if($type=='jpg' || $type=='jpeg')
45: $info=$this->_parsejpg($file);
46: elseif($type=='png'){
47: $info=$this->_parsepng($file);
48: if ($info=='alpha') return $this->ImagePngWithAlpha($file,$x,$y,$w,$h,$link);
49: }
50: else
51: {
52:
53: $mtd='_parse'.$type;
54: if(!method_exists($this,$mtd))
55: $this->Error('Unsupported image type: '.$type);
56: $info=$this->$mtd($file);
57: }
58: set_magic_quotes_runtime($mqr);
59:
60: if ($isMask){
61: $info['cs']="DeviceGray";
62: }
63: $info['i']=count($this->images)+1;
64: if ($maskImg>0) $info['masked'] = $maskImg;
65: $this->images[$file]=$info;
66: }
67: else
68: $info=$this->images[$file];
69:
70: if($w==0 && $h==0)
71: {
72:
73: $w=$info['w']/$this->k;
74: $h=$info['h']/$this->k;
75: }
76: if($w==0)
77: $w=$h*$info['w']/$info['h'];
78: if($h==0)
79: $h=$w*$info['h']/$info['w'];
80:
81:
82: if ((float)FPDF_VERSION>=1.7){
83: if ($isMask) $x = ($this->CurOrientation=='P'?$this->CurPageSize[0]:$this->CurPageSize[1]) + 10;
84: }else{
85: if ($isMask) $x = ($this->CurOrientation=='P'?$this->CurPageFormat[0]:$this->CurPageFormat[1]) + 10;
86: }
87:
88: $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']));
89: if($link)
90: $this->Link($x,$y,$w,$h,$link);
91:
92: return $info['i'];
93: }
94:
95:
96:
97: function ImagePngWithAlpha($file,$x,$y,$w=0,$h=0,$link='')
98: {
99: $tmp_alpha = tempnam('.', 'mska');
100: $this->tmpFiles[] = $tmp_alpha;
101: $tmp_plain = tempnam('.', 'mskp');
102: $this->tmpFiles[] = $tmp_plain;
103:
104: list($wpx, $hpx) = getimagesize($file);
105: $img = imagecreatefrompng($file);
106: $alpha_img = imagecreate( $wpx, $hpx );
107:
108:
109: for($c=0;$c<256;$c++) ImageColorAllocate($alpha_img, $c, $c, $c);
110:
111:
112: $xpx=0;
113: while ($xpx<$wpx){
114: $ypx = 0;
115: while ($ypx<$hpx){
116: $color_index = imagecolorat($img, $xpx, $ypx);
117: $alpha = 255-($color_index>>24)*255/127;
118: imagesetpixel($alpha_img, $xpx, $ypx, $alpha);
119: ++$ypx;
120: }
121: ++$xpx;
122: }
123:
124: imagepng($alpha_img, $tmp_alpha);
125: imagedestroy($alpha_img);
126:
127:
128: $plain_img = imagecreatetruecolor ( $wpx, $hpx );
129: imagecopy ($plain_img, $img, 0, 0, 0, 0, $wpx, $hpx );
130: imagepng($plain_img, $tmp_plain);
131: imagedestroy($plain_img);
132:
133:
134: $maskImg = $this->Image($tmp_alpha, 0,0,0,0, 'PNG', '', true);
135:
136:
137: $this->Image($tmp_plain,$x,$y,$w,$h,'PNG',$link, false, $maskImg);
138: }
139:
140: function Close()
141: {
142: parent::Close();
143:
144: foreach($this->tmpFiles as $tmp) @unlink($tmp);
145: }
146:
147: 148: 149: 150: 151:
152: function _putimages()
153: {
154: $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
155: reset($this->images);
156: while(list($file,$info)=each($this->images))
157: {
158: $this->_newobj();
159: $this->images[$file]['n']=$this->n;
160: $this->_out('<</Type /XObject');
161: $this->_out('/Subtype /Image');
162: $this->_out('/Width '.$info['w']);
163: $this->_out('/Height '.$info['h']);
164:
165: if (isset($info["masked"])) $this->_out('/SMask '.($this->n-1).' 0 R');
166:
167: if($info['cs']=='Indexed')
168: $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
169: else
170: {
171: $this->_out('/ColorSpace /'.$info['cs']);
172: if($info['cs']=='DeviceCMYK')
173: $this->_out('/Decode [1 0 1 0 1 0 1 0]');
174: }
175: $this->_out('/BitsPerComponent '.$info['bpc']);
176: if(isset($info['f']))
177: $this->_out('/Filter /'.$info['f']);
178: if(isset($info['parms']))
179: $this->_out($info['parms']);
180: if(isset($info['trns']) && is_array($info['trns']))
181: {
182: $trns='';
183: for($i=0;$i<count($info['trns']);$i++)
184: $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
185: $this->_out('/Mask ['.$trns.']');
186: }
187: $this->_out('/Length '.strlen($info['data']).'>>');
188: $this->_putstream($info['data']);
189: unset($this->images[$file]['data']);
190: $this->_out('endobj');
191:
192: if($info['cs']=='Indexed')
193: {
194: $this->_newobj();
195: $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
196: $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
197: $this->_putstream($pal);
198: $this->_out('endobj');
199: }
200: }
201: }
202:
203:
204:
205: function _parsepng($file)
206: {
207:
208: $f=fopen($file,'rb');
209: if(!$f)
210: $this->Error('Can\'t open image file: '.$file);
211:
212: if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
213: $this->Error('Not a PNG file: '.$file);
214:
215: fread($f,4);
216: if(fread($f,4)!='IHDR')
217: $this->Error('Incorrect PNG file: '.$file);
218: $w=$this->_readint($f);
219: $h=$this->_readint($f);
220: $bpc=ord(fread($f,1));
221: if($bpc>8)
222: $this->Error('16-bit depth not supported: '.$file);
223: $ct=ord(fread($f,1));
224: if($ct==0)
225: $colspace='DeviceGray';
226: elseif($ct==2)
227: $colspace='DeviceRGB';
228: elseif($ct==3)
229: $colspace='Indexed';
230: else {
231: fclose($f);
232: return 'alpha';
233: }
234: if(ord(fread($f,1))!=0)
235: $this->Error('Unknown compression method: '.$file);
236: if(ord(fread($f,1))!=0)
237: $this->Error('Unknown filter method: '.$file);
238: if(ord(fread($f,1))!=0)
239: $this->Error('Interlacing not supported: '.$file);
240: fread($f,4);
241: $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
242:
243: $pal='';
244: $trns='';
245: $data='';
246: do
247: {
248: $n=$this->_readint($f);
249: $type=fread($f,4);
250: if($type=='PLTE')
251: {
252:
253: $pal=fread($f,$n);
254: fread($f,4);
255: }
256: elseif($type=='tRNS')
257: {
258:
259: $t=fread($f,$n);
260: if($ct==0)
261: $trns=array(ord(substr($t,1,1)));
262: elseif($ct==2)
263: $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
264: else
265: {
266: $pos=strpos($t,chr(0));
267: if($pos!==false)
268: $trns=array($pos);
269: }
270: fread($f,4);
271: }
272: elseif($type=='IDAT')
273: {
274:
275: $data.=fread($f,$n);
276: fread($f,4);
277: }
278: elseif($type=='IEND')
279: break;
280: else
281: fread($f,$n+4);
282: }
283: while($n);
284: if($colspace=='Indexed' && empty($pal))
285: $this->Error('Missing palette in '.$file);
286: fclose($f);
287: return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);
288: }
289:
290: }
291:
292: ?>