[Mapbender-commits] r3371 - branches/print_dev/http/extensions/fpdf

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Fri Dec 19 12:39:49 EST 2008


Author: mschulz
Date: 2008-12-19 12:39:49 -0500 (Fri, 19 Dec 2008)
New Revision: 3371

Added:
   branches/print_dev/http/extensions/fpdf/mb_fpdi.php
Log:
first sketches to new pdf template printing

Added: branches/print_dev/http/extensions/fpdf/mb_fpdi.php
===================================================================
--- branches/print_dev/http/extensions/fpdf/mb_fpdi.php	                        (rev 0)
+++ branches/print_dev/http/extensions/fpdf/mb_fpdi.php	2008-12-19 17:39:49 UTC (rev 3371)
@@ -0,0 +1,379 @@
+<?php
+
+require_once(dirname(__FILE__)."/fpdi.php");
+
+class mb_fpdi extends FPDI {
+
+    function mb_fpdi($orientation='L',$unit='mm',$format='A4') {
+        parent::FPDI($orientation,$unit,$format);
+    }	
+
+    // ====================================
+	// Image with png alpha extension
+	// ====================================
+    
+	//Private properties
+	var $tmpFiles = array();
+	
+	/*******************************************************************************
+	*                                                                              *
+	*                               Public methods                                 *
+	*                                                                              *
+	*******************************************************************************/
+	function Image($file,$x,$y,$w=0,$h=0,$type='',$link='', $isMask=false, $maskImg=0)
+	{
+	    //Put an image on the page
+	    if(!isset($this->images[$file]))
+	    {
+	        //First use of image, get info
+	        if($type=='')
+	        {
+	            $pos=strrpos($file,'.');
+	            if(!$pos)
+	                $this->Error('Image file has no extension and no type was specified: '.$file);
+	            $type=substr($file,$pos+1);
+	        }
+	        $type=strtolower($type);
+	        $mqr=get_magic_quotes_runtime();
+	        set_magic_quotes_runtime(0);
+	        if($type=='jpg' || $type=='jpeg')
+	            $info=$this->_parsejpg($file);
+	        elseif($type=='png'){
+	            $info=$this->_parsepng($file);
+	            if ($info=='alpha') return $this->ImagePngWithAlpha($file,$x,$y,$w,$h,$link);
+	        }
+	        else
+	        {
+	            //Allow for additional formats
+	            $mtd='_parse'.$type;
+	            if(!method_exists($this,$mtd))
+	                $this->Error('Unsupported image type: '.$type);
+	            $info=$this->$mtd($file);
+	        }
+	        set_magic_quotes_runtime($mqr);
+	        
+	        if ($isMask){
+	      $info['cs']="DeviceGray"; // try to force grayscale (instead of indexed)
+	    }
+	        $info['i']=count($this->images)+1;
+	        if ($maskImg>0) $info['masked'] = $maskImg;###
+	        $this->images[$file]=$info;
+	    }
+	    else
+	        $info=$this->images[$file];
+	    //Automatic width and height calculation if needed
+	    if($w==0 && $h==0)
+	    {
+	        //Put image at 72 dpi
+	        $w=$info['w']/$this->k;
+	        $h=$info['h']/$this->k;
+	    }
+	    if($w==0)
+	        $w=$h*$info['w']/$info['h'];
+	    if($h==0)
+	        $h=$w*$info['h']/$info['w'];
+	        
+	    if ($isMask) $x = $this->fwPt + 10; // embed hidden, ouside the canvas  
+	    $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']));
+	    if($link)
+	        $this->Link($x,$y,$w,$h,$link);
+	        
+	    return $info['i'];
+	}
+	
+	// needs GD 2.x extension
+	// pixel-wise operation, not very fast
+	function ImagePngWithAlpha($file,$x,$y,$w=0,$h=0,$link='')
+	{
+	    $tmp_alpha = tempnam('.', 'mska');
+	    $this->tmpFiles[] = $tmp_alpha;
+	    $tmp_plain = tempnam('.', 'mskp');
+	    $this->tmpFiles[] = $tmp_plain;
+	    
+	    list($wpx, $hpx) = getimagesize($file);
+	    $img = imagecreatefrompng($file);
+	    $alpha_img = imagecreate( $wpx, $hpx );
+	    
+	    // generate gray scale pallete
+	    for($c=0;$c<256;$c++) ImageColorAllocate($alpha_img, $c, $c, $c);
+	    
+	    // extract alpha channel
+	    $xpx=0;
+	    while ($xpx<$wpx){
+	        $ypx = 0;
+	        while ($ypx<$hpx){
+	            $color_index = imagecolorat($img, $xpx, $ypx);
+	            $col = imagecolorsforindex($img, $color_index);
+	            imagesetpixel($alpha_img, $xpx, $ypx, $this->_gamma( (127-$col['alpha'])*255/127)  );
+	        ++$ypx;
+	        }
+	        ++$xpx;
+	    }
+	
+	    imagepng($alpha_img, $tmp_alpha);
+	    imagedestroy($alpha_img);
+	    
+	    // extract image without alpha channel
+	    $plain_img = imagecreatetruecolor ( $wpx, $hpx );
+	    imagecopy ($plain_img, $img, 0, 0, 0, 0, $wpx, $hpx );
+	    imagepng($plain_img, $tmp_plain);
+	    imagedestroy($plain_img);
+	    
+	    //first embed mask image (w, h, x, will be ignored)
+	    $maskImg = $this->Image($tmp_alpha, 0,0,0,0, 'PNG', '', true);
+	    
+	    //embed image, masked with previously embedded mask
+	    $this->Image($tmp_plain,$x,$y,$w,$h,'PNG',$link, false, $maskImg);
+	}
+	
+	function Close()
+	{
+	    parent::Close();
+	    // clean up tmp files
+	    foreach($this->tmpFiles as $tmp) @unlink($tmp);
+	}
+	
+	/*******************************************************************************
+	*                                                                              *
+	*                               Private methods                                *
+	*                                                                              *
+	*******************************************************************************/
+	function _putimages()
+	{
+	    $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
+	    reset($this->images);
+	    while(list($file,$info)=each($this->images))
+	    {
+	        $this->_newobj();
+	        $this->images[$file]['n']=$this->n;
+	        $this->_out('<</Type /XObject');
+	        $this->_out('/Subtype /Image');
+	        $this->_out('/Width '.$info['w']);
+	        $this->_out('/Height '.$info['h']);
+	        
+	        if (isset($info["masked"])) $this->_out('/SMask '.($this->n-1).' 0 R'); ###
+	        
+	        if($info['cs']=='Indexed')
+	            $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
+	        else
+	        {
+	            $this->_out('/ColorSpace /'.$info['cs']);
+	            if($info['cs']=='DeviceCMYK')
+	                $this->_out('/Decode [1 0 1 0 1 0 1 0]');
+	        }
+	        $this->_out('/BitsPerComponent '.$info['bpc']);
+	        if(isset($info['f']))
+	            $this->_out('/Filter /'.$info['f']);
+	        if(isset($info['parms']))
+	            $this->_out($info['parms']);
+	        if(isset($info['trns']) && is_array($info['trns']))
+	        {
+	            $trns='';
+	            for($i=0;$i<count($info['trns']);$i++)
+	                $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
+	            $this->_out('/Mask ['.$trns.']');
+	        }
+	        $this->_out('/Length '.strlen($info['data']).'>>');
+	        $this->_putstream($info['data']);
+	        unset($this->images[$file]['data']);
+	        $this->_out('endobj');
+	        //Palette
+	        if($info['cs']=='Indexed')
+	        {
+	            $this->_newobj();
+	            $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
+	            $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
+	            $this->_putstream($pal);
+	            $this->_out('endobj');
+	        }
+	    }
+	}
+	
+	// GD seems to use a different gamma, this method is used to correct it again
+	function _gamma($v){
+	    return pow ($v/255, 2.2) * 255;
+	}
+	
+     function _parsegif($file) 
+     { 
+	//Function by Jerome Fenal
+	require_once(BASECLASSES.'/fpdi/gif.php'); //GIF class in pure PHP from Yamasoft (formerly at http://www.yamasoft.com)
+
+	$h=0;
+	$w=0;
+	$gif=new CGIF();
+
+	if (!$gif->loadFile($file, 0))
+		$this->Error("GIF parser: unable to open file $file");
+
+	if($gif->m_img->m_gih->m_bLocalClr) {
+		$nColors = $gif->m_img->m_gih->m_nTableSize;
+		$pal = $gif->m_img->m_gih->m_colorTable->toString();
+		if($bgColor != -1) {
+			$bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
+		}
+		$colspace='Indexed';
+	} elseif($gif->m_gfh->m_bGlobalClr) {
+		$nColors = $gif->m_gfh->m_nTableSize;
+		$pal = $gif->m_gfh->m_colorTable->toString();
+		if($bgColor != -1) {
+			$bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
+		}
+		$colspace='Indexed';
+	} else {
+		$nColors = 0;
+		$bgColor = -1;
+		$colspace='DeviceGray';
+		$pal='';
+	}
+
+	$trns='';
+	if($gif->m_img->m_bTrans && ($nColors > 0)) {
+		$trns=array($gif->m_img->m_nTrans);
+	}
+
+	$data=$gif->m_img->m_data;
+	$w=$gif->m_gfh->m_nWidth;
+	$h=$gif->m_gfh->m_nHeight;
+
+	if($colspace=='Indexed' and empty($pal))
+		$this->Error('Missing palette in '.$file);
+
+	if ($this->compress) {
+		$data=gzcompress($data);
+		return array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'f'=>'FlateDecode', 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data);
+	} else {
+		return array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data);
+	} 
+}
+
+	// this method overwriing the original version is only needed to make the Image method support PNGs with alpha channels.
+	// if you only use the ImagePngWithAlpha method for such PNGs, you can remove it from this script.
+	function _parsepng($file)
+	{
+	    //Extract info from a PNG file
+	    $f=fopen($file,'rb');
+	    if(!$f)
+	        $this->Error('Can\'t open image file: '.$file);
+	    //Check signature
+	    if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
+	        $this->Error('Not a PNG file: '.$file);
+	    //Read header chunk
+	    fread($f,4);
+	    if(fread($f,4)!='IHDR')
+	        $this->Error('Incorrect PNG file: '.$file);
+	    $w=$this->_freadint($f);
+	    $h=$this->_freadint($f);
+	    $bpc=ord(fread($f,1));
+	    if($bpc>8)
+	        $this->Error('16-bit depth not supported: '.$file);
+	    $ct=ord(fread($f,1));
+	    if($ct==0)
+	        $colspace='DeviceGray';
+	    elseif($ct==2)
+	        $colspace='DeviceRGB';
+	    elseif($ct==3)
+	        $colspace='Indexed';
+	    else {
+	        fclose($f);      // the only changes are
+	        return 'alpha';  // made in those 2 lines
+	    }
+	    if(ord(fread($f,1))!=0)
+	        $this->Error('Unknown compression method: '.$file);
+	    if(ord(fread($f,1))!=0)
+	        $this->Error('Unknown filter method: '.$file);
+	    if(ord(fread($f,1))!=0)
+	        $this->Error('Interlacing not supported: '.$file);
+	    fread($f,4);
+	    $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
+	    //Scan chunks looking for palette, transparency and image data
+	    $pal='';
+	    $trns='';
+	    $data='';
+	    do
+	    {
+	        $n=$this->_freadint($f);
+	        $type=fread($f,4);
+	        if($type=='PLTE')
+	        {
+	            //Read palette
+	            $pal=fread($f,$n);
+	            fread($f,4);
+	        }
+	        elseif($type=='tRNS')
+	        {
+	            //Read transparency info
+	            $t=fread($f,$n);
+	            if($ct==0)
+	                $trns=array(ord(substr($t,1,1)));
+	            elseif($ct==2)
+	                $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
+	            else
+	            {
+	                $pos=strpos($t,chr(0));
+	                if($pos!==false)
+	                    $trns=array($pos);
+	            }
+	            fread($f,4);
+	        }
+	        elseif($type=='IDAT')
+	        {
+	            //Read image data block
+	            $data.=fread($f,$n);
+	            fread($f,4);
+	        }
+	        elseif($type=='IEND')
+	            break;
+	        else
+	            fread($f,$n+4);
+	    }
+	    while($n);
+	    if($colspace=='Indexed' && empty($pal))
+	        $this->Error('Missing palette in '.$file);
+	    fclose($f);
+	    return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);
+	}
+
+	var $angle=0;
+	
+	function Rotate($angle, $x=-1, $y=-1)
+	{
+	    if($x==-1)
+	        $x=$this->x;
+	    if($y==-1)
+	        $y=$this->y;
+	    if($this->angle!=0)
+	        $this->_out('Q');
+	    $this->angle=$angle;
+	    if($angle!=0)
+	    {
+	        $angle*=M_PI/180;
+	        $c=cos($angle);
+	        $s=sin($angle);
+	        $cx=$x*$this->k;
+	        $cy=($this->h-$y)*$this->k;
+	        $this->_out(sprintf('q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm', $c, $s, -$s, $c, $cx, $cy, -$cx, -$cy));
+	    }
+	}
+	
+	function _endpage()
+	{
+	    if($this->angle!=0)
+	    {
+	        $this->angle=0;
+	        $this->_out('Q');
+	    }
+	    parent::_endpage();
+	}
+    
+	function RotatedText($x, $y, $txt, $angle)
+	{
+	    //Text rotated around its origin
+	    $this->Rotate($angle, $x, $y);
+	    $this->Text($x, $y, $txt);
+	    $this->Rotate(0);
+	}
+	
+}
+
+?>
\ No newline at end of file



More information about the Mapbender_commits mailing list