Overview

Namespaces

  • Mapbender
    • Component
      • HTTP
    • CoreBundle
      • Command
      • Component
        • Exception
      • Controller
      • DataFixtures
        • ORM
      • DependencyInjection
      • Element
        • Type
      • Entity
      • EventListener
      • Extension
      • Form
        • DataTransformer
        • EventListener
        • Type
      • Security
      • Template
    • KmlBundle
      • Element
    • ManagerBundle
      • Controller
      • Form
        • DataTransformer
        • Type
    • MonitoringBundle
      • Command
      • Component
      • Controller
      • DependencyInjection
      • Entity
      • EventListener
      • Form
    • PrintBundle
      • Component
      • Controller
    • WmcBundle
      • Component
        • Exception
      • Element
        • Type
      • Entity
      • Form
        • Type
    • WmsBundle
      • Component
        • Exception
      • Controller
      • DependencyInjection
      • Element
        • Type
      • Entity
      • Event
      • Form
        • EventListener
        • Type
    • WmtsBundle
      • Component
        • Exception
      • Controller
      • Entity
      • Form
        • Type
  • None
  • PHP

Classes

  • OdgParser
  • PDF_ImageAlpha
  • PrintService
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  • Download
  1: <?php
  2: /*******************************************************************************
  3: * Software: PDF_ImageAlpha
  4: * Version:  1.4
  5: * Date:     2009-12-28
  6: * Author:   Valentin Schmidt 
  7: *
  8: * Requirements: FPDF 1.6
  9: *
 10: * This script allows to use images (PNGs or JPGs) with alpha-channels. 
 11: * The alpha-channel can be either supplied as separate 8-bit PNG ("mask"), 
 12: * or, for PNGs, also an internal alpha-channel can be used. 
 13: * For the latter the GD 2.x extension is required.
 14: *******************************************************************************/ 
 15: namespace Mapbender\PrintBundle\Component;
 16: use \FPDF_FPDI;
 17: 
 18: class PDF_ImageAlpha extends FPDF_FPDI{
 19: 
 20: //Private properties
 21: var $tmpFiles = array(); 
 22: 
 23: /*******************************************************************************
 24: *                                                                              *
 25: *                               Public methods                                 *
 26: *                                                                              *
 27: *******************************************************************************/
 28: function Image($file,$x,$y,$w=0,$h=0,$type='',$link='', $isMask=false, $maskImg=0)
 29: {
 30:     //Put an image on the page
 31:     if(!isset($this->images[$file]))
 32:     {
 33:         //First use of image, get info
 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:             //Allow for additional formats
 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"; // try to force grayscale (instead of indexed)
 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:     //Automatic width and height calculation if needed
 70:     if($w==0 && $h==0)
 71:     {
 72:         //Put image at 72 dpi
 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:     // embed hidden, ouside the canvas
 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: // needs GD 2.x extension
 96: // pixel-wise operation, not very fast
 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:     // generate gray scale pallete
109:     for($c=0;$c<256;$c++) ImageColorAllocate($alpha_img, $c, $c, $c);
110:     
111:     // extract alpha channel
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; // GD alpha component: 7 bit only, 0..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:     // extract image without alpha channel
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:     //first embed mask image (w, h, x, will be ignored)
134:     $maskImg = $this->Image($tmp_alpha, 0,0,0,0, 'PNG', '', true); 
135:     
136:     //embed image, masked with previously embedded mask
137:     $this->Image($tmp_plain,$x,$y,$w,$h,'PNG',$link, false, $maskImg);
138: }
139: 
140: function Close()
141: {
142:     parent::Close();
143:     // clean up tmp files
144:     foreach($this->tmpFiles as $tmp) @unlink($tmp);
145: }
146: 
147: /*******************************************************************************
148: *                                                                              *
149: *                               Private methods                                *
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:         //Palette
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: // this method overwriing the original version is only needed to make the Image method support PNGs with alpha channels.
204: // if you only use the ImagePngWithAlpha method for such PNGs, you can remove it from this script.
205: function _parsepng($file)
206: {
207:     //Extract info from a PNG file
208:     $f=fopen($file,'rb');
209:     if(!$f)
210:         $this->Error('Can\'t open image file: '.$file);
211:     //Check signature
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:     //Read header chunk
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);      // the only changes are 
232:         return 'alpha';  // made in those 2 lines
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:     //Scan chunks looking for palette, transparency and image data
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:             //Read palette
253:             $pal=fread($f,$n);
254:             fread($f,4);
255:         }
256:         elseif($type=='tRNS')
257:         {
258:             //Read transparency info
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:             //Read image data block
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: ?>
Mapbender3 API documenation API documentation generated by ApiGen 2.8.0