Alpha Framework alpha--view--widgets
[ class tree: alpha--view--widgets ] [ index: alpha--view--widgets ] [ all elements ]

Source for file Image.inc

Documentation is available at Image.inc

  1. <?php
  2.  
  3. require_once $config->get('sysRoot').'alpha/util/AlphaErrorHandlers.inc';
  4. require_once $config->get('sysRoot').'alpha/util/Logger.inc';
  5. require_once $config->get('sysRoot').'alpha/model/types/Enum.inc';
  6. require_once $config->get('sysRoot').'alpha/model/types/Double.inc';
  7. require_once $config->get('sysRoot').'alpha/model/types/Boolean.inc';
  8. require_once $config->get('sysRoot').'alpha/model/types/Integer.inc';
  9. require_once $config->get('sysRoot').'alpha/exceptions/IllegalArguementException.inc';
  10. require_once $config->get('sysRoot').'alpha/controller/front/FrontController.inc';
  11. require_once $config->get('sysRoot').'alpha/view/AlphaView.inc';
  12.  
  13. /**
  14.  * A widget that can generate an image which is scaled to the screen resolution of the
  15.  * user, and can be made secured to prevent hot-linking from remote sites.  Note that by
  16.  * default, a jpg file will be returned (the source file can be jpg, png, or gif).
  17.  * 
  18.  * @package alpha::view::widgets
  19.  * @since 1.0
  20.  * @author John Collins <dev@alphaframework.org>
  21.  * @version $Id: Image.inc 1341 2011-03-17 15:02:02Z johnc $
  22.  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
  23.  * @copyright Copyright (c) 2011, John Collins (founder of Alpha Framework).
  24.  *  All rights reserved.
  25.  * 
  26.  *  <pre>
  27.  *  Redistribution and use in source and binary forms, with or
  28.  *  without modification, are permitted provided that the
  29.  *  following conditions are met:
  30.  * 
  31.  *  * Redistributions of source code must retain the above
  32.  *    copyright notice, this list of conditions and the
  33.  *    following disclaimer.
  34.  *  * Redistributions in binary form must reproduce the above
  35.  *    copyright notice, this list of conditions and the
  36.  *    following disclaimer in the documentation and/or other
  37.  *    materials provided with the distribution.
  38.  *  * Neither the name of the Alpha Framework nor the names
  39.  *    of its contributors may be used to endorse or promote
  40.  *    products derived from this software without specific
  41.  *    prior written permission.
  42.  *   
  43.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  44.  *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  45.  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  46.  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  47.  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  48.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  49.  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  50.  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  51.  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  52.  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  53.  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  54.  *  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  55.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  56.  *  </pre>
  57.  *  
  58.  */
  59. class Image {
  60.     /**
  61.      * The title of the image for alt text (optional).
  62.      * 
  63.      * @var string 
  64.      * @since 1.0
  65.      */
  66.     private $title;
  67.     
  68.     /**
  69.      * The absolute path to the source image.
  70.      * 
  71.      * @var string 
  72.      * @since 1.0
  73.      */
  74.     private $source;
  75.     
  76.     /**
  77.      * The width of the image (can differ from the source file when scale=true).
  78.      * 
  79.      * @var Integer 
  80.      * @since 1.0
  81.      */
  82.     private $width;
  83.     
  84.     /**
  85.      * The height of the image (can differ from the source file when scale=true).
  86.      * 
  87.      * @var Integer 
  88.      * @since 1.0
  89.      */
  90.     private $height;
  91.     
  92.     /**
  93.      * The file type of the source image (gif, jpg, or png supported)
  94.      * 
  95.      * @var Enum 
  96.      * @since 1.0
  97.      */
  98.     private $sourceType;
  99.     
  100.     /**
  101.      * The quality of the jpg image generated (0.00 to 1.00, 0.75 by default).
  102.      * 
  103.      * @var Double 
  104.      * @since 1.0
  105.      */
  106.     private $quality;
  107.     
  108.     /**
  109.      * Flag to determine if the image will scale to match the target resolution (false
  110.      * by default).
  111.      * 
  112.      * @var Boolean 
  113.      * @since 1.0
  114.      */
  115.     private $scale;
  116.     
  117.     /**
  118.      * Flag to determine if the link to the image will change every 24hrs, making hot-linking
  119.      * to the image difficult (false by default).
  120.      * 
  121.      * @var Boolean 
  122.      * @since 1.0
  123.      */
  124.     private $secure;
  125.     
  126.     /**
  127.      * The auto-generated name of the cache file for the image.
  128.      * 
  129.      * @var string 
  130.      * @since 1.0
  131.      */
  132.     private $filename;
  133.     
  134.     /**
  135.      * Trace logger
  136.      * 
  137.      * @var Logger 
  138.      * @since 1.0
  139.      */
  140.     private static $logger null;
  141.     
  142.     /**
  143.      * The constructor.
  144.      * 
  145.      * @param $source 
  146.      * @param $width 
  147.      * @param $height 
  148.      * @param $sourceType 
  149.      * @param $quality 
  150.      * @param $scale 
  151.      * @throws IllegalArguementException
  152.      * @since 1.0
  153.      */
  154.     public function __construct($source$width$height$sourceType$quality=0.75$scale=false$secure=false{
  155.         self::$logger new Logger('Image');
  156.         self::$logger->debug('>>__construct(source=['.$source.'], width=['.$width.'], height=['.$height.'], sourceType=['.$sourceType.'], quality=['.$quality.'], scale=['.$scale.'], secure=['.$secure.'])');
  157.             
  158.         global $config;
  159.             
  160.         if(file_exists($source))
  161.             $this->source $source;
  162.         else
  163.             throw new IllegalArguementException('The source file for the Image widget ['.$source.'] cannot be found!');
  164.         
  165.         $this->sourceType new Enum();
  166.         $this->sourceType->setOptions(array('jpg','png','gif'));
  167.         $this->sourceType->setValue($sourceType);
  168.         
  169.         if($quality 0.0 || $quality 1.0)
  170.             throw new IllegalArguementException('The quality setting of ['.$quality.'] is outside of the allowable range of 0.0 to 1.0');
  171.         
  172.         $this->quality new Double($quality);
  173.         $this->scale new Boolean($scale);
  174.         $this->secure new Boolean($secure);
  175.         
  176.         $this->width new Integer($width);
  177.         $this->height new Integer($height);
  178.         
  179.         $this->setFilename();
  180.         
  181.         self::$logger->debug('<<__construct');
  182.     }
  183.     
  184.     /**
  185.      * Renders the HTML <img> tag to the ViewImage controller, with all of the correct params to render the source
  186.      * image in the desired resolution.
  187.      * 
  188.      * @param $altText Set this value to render alternate text as part of the HTML link (defaults to no alternate text)
  189.      * @return string 
  190.      * @since 1.0
  191.      */
  192.     public function renderHTMLLink($altText=''{
  193.         global $config;
  194.         
  195.         if($this->secure->getBooleanValue()) {
  196.             $params AlphaController::generateSecurityFields();
  197.             return '<img src="'.FrontController::generateSecureURL('act=ViewImage&s='.$this->source.'&w='.$this->width->getValue().'&h='.$this->height->getValue().'&t='.$this->sourceType->getValue().'&q='.$this->quality->getValue().'&sc='.$this->scale->getValue().'&se='.$this->secure->getValue().'&var1='.$params[0].'&var2='.$params[1]).'"'.(empty($altText'' ' alt="'.$altText.'"').'/>';
  198.         }else{
  199.             return '<img src="'.FrontController::generateSecureURL('act=ViewImage&s='.$this->source.'&w='.$this->width->getValue().'&h='.$this->height->getValue().'&t='.$this->sourceType->getValue().'&q='.$this->quality->getValue().'&sc='.$this->scale->getValue().'&se='.$this->secure->getValue()).'"'.(empty($altText'' ' alt="'.$altText.'"').'/>';
  200.         }
  201.     }
  202.     
  203.     /**
  204.      * Setter for the filename, which also creates a sub-directory under /cache for images when required
  205.      * 
  206.      * @since 1.0
  207.      * @throws AlphaException
  208.      */
  209.     private function setFilename({
  210.         global $config;
  211.         
  212.         if(!strpos($this->source'attachments/article_')) {
  213.             // checking to see if we will write a jpg or png to the cache
  214.             if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG'))
  215.                 $this->filename $config->get('sysRoot').'cache/images/'.basename($this->source".".$this->sourceType->getValue()).'_'.$this->width->getValue().'x'.$this->height->getValue().'.png';
  216.             else
  217.                 $this->filename $config->get('sysRoot').'cache/images/'.basename($this->source".".$this->sourceType->getValue()).'_'.$this->width->getValue().'x'.$this->height->getValue().'.jpg';
  218.         }else{
  219.             // make a cache dir for the article
  220.             $cacheDir $config->get('sysRoot').'cache/images/article_'.substr($this->sourcestrpos($this->source'attachments/article_')+2011);
  221.             if(!file_exists($cacheDir)) {
  222.                 $success mkdir($cacheDir);
  223.             
  224.                 if (!$success{
  225.                     throw new AlphaException('Unable to create the folder '.$cacheDir.' for the cache image, source file is '.$this->source);
  226.                 }
  227.                 
  228.                 // ...and set write permissions on the folder
  229.                 $success chmod($cacheDir0777);
  230.                     
  231.                 if (!$success{
  232.                     throw new AlphaException('Unable to set write permissions on the folder ['.$cacheDir.'].');
  233.                 }
  234.             }
  235.             
  236.             // now set the filename to include the new cache directory
  237.             if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG'))
  238.                 $this->filename $cacheDir.'/'.basename($this->source".".$this->sourceType->getValue()).'_'.$this->width->getValue().'x'.$this->height->getValue().'.png';
  239.             else
  240.                 $this->filename $cacheDir.'/'.basename($this->source".".$this->sourceType->getValue()).'_'.$this->width->getValue().'x'.$this->height->getValue().'.jpg';
  241.         }
  242.         
  243.         self::$logger->debug('Image filename is ['.$this->filename.']');
  244.     }
  245.     
  246.     /**
  247.      * Gets the auto-generated filename for the image in the /cache directory
  248.      * 
  249.      * @since 1.0
  250.      */
  251.     public function getFilename({
  252.         return $this->filename;
  253.     }
  254.     
  255.     /**
  256.      * Renders the actual binary image using GD library calls.
  257.      * 
  258.      *  @since 1.0
  259.      */
  260.     public function renderImage({
  261.         global $config;
  262.         
  263.         /*
  264.          * Handle secure image validation (if enabled in config).
  265.          * Not required for the view_article_pdf.php controller.
  266.          */
  267.         if($config->get('sysCMSImagesWidgetSecure'&& basename($_SERVER["PHP_SELF"]!= 'ViewArticlePDF.php'{
  268.             $valid AlphaController::checkSecurityFields();            
  269.             
  270.             // if not valid, just return a blank black image of the same dimensions
  271.             if(!$valid{
  272.                 $im  imagecreatetruecolor($this->width->getValue()$this->height->getValue())/* Create a blank image */ 
  273.                 $bgc imagecolorallocate($im000);                
  274.                 imagefilledrectangle($im00$this->width->getValue()$this->height->getValue()$bgc)
  275.                 
  276.                 if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG')) {
  277.                     header("Content-Type: image/png");
  278.                     imagepng($im);
  279.                 }else{
  280.                     header("Content-Type: image/jpeg");
  281.                     imagejpeg($im);
  282.                 }
  283.                 
  284.                 imagedestroy($im);
  285.                 
  286.                 self::$logger->warn('The client ['.$_SERVER['HTTP_USER_AGENT'].'] was blocked from accessing the file ['.$this->filename.'] due to bad security tokens being provided');
  287.             }
  288.         }
  289.         
  290.         // if scaled, we need to compute the target image size
  291.         if($this->scale->getBooleanValue(&& isset($_COOKIE['screenSize'])) {
  292.             $originalScreenResolution explode('x'$config->get('sysCMSImagesWidgetScreenResolution'));
  293.             $originalScreenX $originalScreenResolution[0];
  294.             $originalScreenY $originalScreenResolution[1];
  295.                 
  296.             $targetScreenResolution explode('x'$_COOKIE['screenSize']);
  297.             $targetScreenX $targetScreenResolution[0];
  298.             $targetScreenY $targetScreenResolution[1];
  299.                 
  300.             // calculate the new units we will scale by 
  301.             $xu $targetScreenX/$originalScreenX;
  302.             $yu $targetScreenY/$originalScreenY;
  303.                 
  304.             $this->width new Integer(intval($this->width->getValue()*$xu));
  305.             $this->height new Integer(intval($this->height->getValue()*$yu));
  306.             
  307.             // need to update the cache filename as the dimensions have changed
  308.             $this->setFilename();
  309.         }
  310.         
  311.         // check the image cache first before we proceed
  312.         if ($this->checkCache()) {
  313.             $this->loadCache();            
  314.         }else{
  315.             // now get the old image
  316.             switch ($this->sourceType->getValue()) {
  317.                 case "gif":
  318.                     $old_image imagecreatefromgif($this->source);
  319.                 break;
  320.                 case "jpg":
  321.                     $old_image imagecreatefromjpeg($this->source);
  322.                 break;
  323.                 case "png":
  324.                     $old_image imagecreatefrompng($this->source);
  325.                 break;
  326.             }
  327.             
  328.             if (!$old_image/* See if it failed */ 
  329.                 $im  imagecreatetruecolor($this->width->getValue()$this->height->getValue())/* Create a blank image */ 
  330.                 $bgc imagecolorallocate($im255255255)
  331.                 $tc  imagecolorallocate($im000)
  332.                 imagefilledrectangle($im00$this->width->getValue()$this->height->getValue()$bgc)
  333.                 
  334.                 imagestring($im155"Error loading $this->source"$tc);
  335.                 if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG')) {
  336.                     header("Content-Type: image/png");
  337.                     imagepng($im);
  338.                 }else{
  339.                     header("Content-Type: image/jpeg");
  340.                     imagejpeg($im);
  341.                 }
  342.                 imagedestroy($im);
  343.             }else{
  344.                 // the dimensions of the source image
  345.                 $oldWidth imagesx($old_image);
  346.                 $oldHeight imagesy($old_image);
  347.             
  348.                 // now create the new image
  349.                 $new_image imagecreatetruecolor($this->width->getValue()$this->height->getValue());
  350.             
  351.                 // set a transparent background for PNGs
  352.                 if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG')) {
  353.                     // Turn off transparency blending (temporarily)
  354.                     imagealphablending($new_imagefalse);
  355.             
  356.                     // Create a new transparent color for image
  357.                     $color imagecolorallocatealpha($new_image255000);
  358.             
  359.                     // Completely fill the background of the new image with allocated color.
  360.                     imagefill($new_image00$color);
  361.             
  362.                     // Restore transparency blending
  363.                     imagesavealpha($new_imagetrue);
  364.                 }
  365.                 // copy the old image to the new image (in memory, not the file!)
  366.                 imagecopyresampled($new_image$old_image0000$this->width->getValue()$this->height->getValue()$oldWidth$oldHeight);    
  367.                 
  368.                 if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG')) {
  369.                     header("Content-Type: image/png");
  370.                     imagepng($new_image);
  371.                 }else{
  372.                     header("Content-Type: image/jpeg");
  373.                     imagejpeg($new_image''100*$this->quality->getValue());
  374.                 }
  375.                 
  376.                 $this->cache($new_image);
  377.                 imagedestroy($old_image);
  378.                 imagedestroy($new_image);
  379.             }
  380.         }
  381.     }
  382.     
  383.     /**
  384.      * Caches the image to the cache directory
  385.      * 
  386.      * @param image $image the binary GD image stream to save
  387.      * @since 1.0
  388.      */
  389.     private function cache($image{
  390.         global $config;
  391.         
  392.         if($this->sourceType->getValue(== 'png' && $config->get('sysImagesPerservePNG'))
  393.             imagepng($image$this->filename);
  394.         else
  395.             imagejpeg($image$this->filename100*$this->quality->getValue());
  396.     }
  397.     
  398.     /**
  399.      * Used to check the image cache for the image jpeg cache file.
  400.      *      
  401.      * @return bool 
  402.      * @since 1.0
  403.      */
  404.     private function checkCache({
  405.         return file_exists($this->filename);
  406.     }
  407.     
  408.     /**
  409.      * Method to load the content of the image cache file to the standard output stream (the browser)
  410.      * 
  411.      * @since 1.0
  412.      */
  413.     private function loadCache({        
  414.         readfile($this->filename);        
  415.     }
  416.     
  417.     /**
  418.      * Converts a URL for an image to a relative file system path for the image, assuming it is
  419.      * hosted on the same server as the application.
  420.      * 
  421.      * @param string $imgURL 
  422.      * @return string the path of the image
  423.      * @since 1.0
  424.      */
  425.     public static function convertImageURLToPath($imgURL{
  426.         global $config;
  427.         
  428.         $imgPath str_replace($config->get('sysURL')''$imgURL);
  429.  
  430.         return $imgPath;
  431.     }
  432. }
  433.  
  434. ?>

Documentation generated on Thu, 17 Mar 2011 16:44:22 +0000 by phpDocumentor 1.4.3