Apache Zeta Components Manual :: File Source for imagemagick_base.php

Source for file imagemagick_base.php

Documentation is available at imagemagick_base.php

  1. <?php
  2. /**
  3.  * This file contains the ezcImageImagemagickBaseHandler class.
  4.  *
  5.  * Licensed to the Apache Software Foundation (ASF) under one
  6.  * or more contributor license agreements.  See the NOTICE file
  7.  * distributed with this work for additional information
  8.  * regarding copyright ownership.  The ASF licenses this file
  9.  * to you under the Apache License, Version 2.0 (the
  10.  * "License"); you may not use this file except in compliance
  11.  * with the License.  You may obtain a copy of the License at
  12.  * 
  13.  *   http://www.apache.org/licenses/LICENSE-2.0
  14.  * 
  15.  * Unless required by applicable law or agreed to in writing,
  16.  * software distributed under the License is distributed on an
  17.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18.  * KIND, either express or implied.  See the License for the
  19.  * specific language governing permissions and limitations
  20.  * under the License.
  21.  *
  22.  * @package ImageConversion
  23.  * @version //autogentag//
  24.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25.  * @filesource
  26.  */
  27.  
  28.  
  29. /**
  30.  * ezcImageHandler implementation for ImageMagick.
  31.  * This class only implements the base funtionality of handling images with
  32.  * ImageMagick. If you want to manipulate images using ImageMagick in your
  33.  * application, you should use the {@link ezcImageImagemagickHandler}.
  34.  *
  35.  * You can use this base class to implement your own filter set on basis of
  36.  * ImageMagick, but you can also use {@link ezcImageImagemagickHandler} for
  37.  * this and profit from its already implemented filters.
  38.  *
  39.  * @see ezcImageConverter
  40.  * @see ezcImageHandler
  41.  *
  42.  * @package ImageConversion
  43.  * @version //autogentag//
  44.  */
  45. class ezcImageImagemagickBaseHandler extends ezcImageMethodcallHandler 
  46. {
  47.     /**
  48.      * Path to the convert binary.
  49.      * 
  50.      * @var string 
  51.      */
  52.     private $binary;
  53.  
  54.     /**
  55.      * Map of MIME types to convert tags.
  56.      * 
  57.      * @var array(string=>string) 
  58.      */
  59.     private $tagMap array();
  60.  
  61.     /**
  62.      * Filter options per reference.
  63.      * 
  64.      * @var array(string=>array) 
  65.      */
  66.     private $filterOptions array();
  67.  
  68.     /**
  69.      * Composite image setting per reference.
  70.      * 
  71.      * @var array(string=>bool) 
  72.      */
  73.     private $compositeImages array();
  74.  
  75.     /**
  76.      * Create a new image handler.
  77.      * Creates an image handler. This should never be done directly,
  78.      * but only through the manager for configuration reasons. One can
  79.      * get a direct reference through manager afterwards.
  80.      *
  81.      * This handler has an option 'binary' available, which allows you to
  82.      * explicitly set the path to your ImageMagicks "convert" binary (this
  83.      * may be necessary on Windows, since there may be an obscure "convert.exe"
  84.      * in the $PATH variable available, which has nothing to do with
  85.      * ImageMagick).
  86.      *
  87.      * @throws ezcImageHandlerNotAvailableException
  88.      *          If the ImageMagick binary is not found.
  89.      *
  90.      * @param ezcImageHandlerSettings $settings Settings for the handler.
  91.      */
  92.     public function __constructezcImageHandlerSettings $settings )
  93.     {
  94.         // Check for ImageMagick
  95.         $this->checkImageMagick$settings );
  96.         $this->determineTypes();
  97.         parent::__construct$settings );
  98.     }
  99.  
  100.     /**
  101.      * Load an image file.
  102.      * Loads an image file and returns a reference to it.
  103.      *
  104.      * @param string $file File to load.
  105.      * @param string $mime The MIME type of the file.
  106.      *
  107.      * @return string Reference to the file in this handler.
  108.      *
  109.      * @see ezcImageAnalyzer
  110.      *
  111.      * @throws ezcBaseFileNotFoundException
  112.      *          If the desired file does not exist.
  113.      * @throws ezcImageMimeTypeUnsupportedException
  114.      *          If the desired file has a not recognized type.
  115.      * @throws ezcImageFileNameInvalidException
  116.      *          If an invalid character (", ', $) is found in the file name.
  117.      */
  118.     public function load$file$mime null )
  119.     {
  120.         $this->checkFileName$file );
  121.         $ref $this->loadCommon$file$mime );
  122.  
  123.         // Atomic file operation
  124.         $fileTmp tempnamdirname$file DIRECTORY_SEPARATOR'.' basename$file ) );
  125.         copy$file$fileTmp );
  126.  
  127.         $this->setReferenceData$ref$fileTmp'resource' );
  128.         return $ref;
  129.     }
  130.  
  131.     /**
  132.      * Save an image file.
  133.      * Saves a given open file. Can optionally save to a new file name.
  134.      *
  135.      * @see ezcImageHandler::load()
  136.      *
  137.      * @param string $image                File reference created through load().
  138.      * @param string $newFile              Filename to save the image to.
  139.      * @param string $mime                 New MIME type, if differs from initial one.
  140.      * @param ezcImageSaveOptions $options Save options.
  141.      * @return void 
  142.      *
  143.      * @throws ezcBaseFilePermissionException
  144.      *          If the desired file exists and is not writeable.
  145.      * @throws ezcImageMimeTypeUnsupportedException
  146.      *          If the desired MIME type is not recognized.
  147.      * @throws ezcImageFileNameInvalidException
  148.      *          If an invalid character (", ', $) is found in the file name.
  149.      */
  150.     public function save$image$newFile null$mime nullezcImageSaveOptions $options null )
  151.     {
  152.         if $options === null )
  153.         {
  154.             $options new ezcImageSaveOptions();
  155.         }
  156.  
  157.         if $newFile !== null )
  158.         {
  159.             $this->checkFileName$newFile );
  160.         }
  161.         
  162.         // Check is transparency must be converted
  163.         if  $this->needsTransparencyConversion$this->getReferenceData$image'mime' )$mime && $options->transparencyReplacementColor !== null )
  164.         {
  165.             $this->addFilterOption$image'-background'$this->colorArrayToString$options->transparencyReplacementColor ) );
  166.             $this->addFilterOption$image'-flatten' );
  167.         }
  168.  
  169.         $this->saveCommon$image$newFile$mime );
  170.         
  171.         switch $this->getReferenceData$image'mime' ) )
  172.         {
  173.             case "image/jpeg":
  174.                 if $options->quality !== null )
  175.                 {
  176.                     $this->addFilterOption$image"-quality"$options->quality );
  177.                 }
  178.             break;
  179.             case "image/png":
  180.                 if $options->compression !== null )
  181.                 {
  182.                     // ImageMagick uses qualtiy options here and incorporates filter options
  183.                     $this->addFilterOption$image"-quality"$options->compression 10 );
  184.                 }
  185.             break;
  186.         }
  187.  
  188.         // Prepare ImageMagick command
  189.         // Here we need a work around, because older ImageMagick versions do not
  190.         // support this option order
  191.  
  192.         if isset$this->compositeImages[$image) )
  193.         {
  194.             $command $this->binary ' ' .
  195.                 isset$this->filterOptions[$imageimplode' '$this->filterOptions[$image'' ' ' .
  196.                 escapeshellarg$this->getReferenceData$image'resource' ) ) ' ' .
  197.                 implode' '$this->compositeImages[$image' ' .
  198.                 escapeshellarg$this->tagMap[$this->getReferenceData$image'mime' )':' $this->getReferenceData$image'resource' ) );
  199.         }
  200.         else
  201.         {
  202.             $command $this->binary ' ' .
  203.                 escapeshellarg$this->getReferenceData$image'resource' ) ) ' ' .
  204.                 isset$this->filterOptions[$imageimplode' '$this->filterOptions[$image'' ' ' .
  205.                 escapeshellarg$this->tagMap[$this->getReferenceData$image'mime' )':' $this->getReferenceData$image'resource' ) );
  206.         }
  207.  
  208.         
  209.         // Prepare to run ImageMagick command
  210.         $descriptors array
  211.             array'pipe''r' ),
  212.             array'pipe''w' ),
  213.             array'pipe''w' ),
  214.         );
  215.         
  216.         // Open ImageMagick process
  217.         $imageProcess proc_open$command$descriptors$pipes );
  218.         // Close STDIN pipe
  219.         fclose$pipes[0);
  220.         
  221.         $errorString  '';
  222.         $outputString '';
  223.         // Read STDERR 
  224.         do 
  225.         {
  226.             $outputString .= rtrimfgets$pipes[1]1024 )"\n" );
  227.             $errorString  .= rtrimfgets$pipes[2]1024 )"\n" );
  228.         while !feof$pipes[2) );
  229.         
  230.         // Wait for process to terminate and store return value
  231.         $status proc_get_status$imageProcess );
  232.         while $status['running'!== false )
  233.         {
  234.             // Sleep 1/100 second to wait for convert to exit
  235.             usleep10000 );
  236.             $status proc_get_status$imageProcess );
  237.         }
  238.         $return proc_close$imageProcess );
  239.         
  240.         // Process potential errors
  241.         // Exit code may be messed up with -1, especially on Windoze
  242.         if ( ( $status['exitcode'!= && $status['exitcode'!= -|| strlen$errorString )
  243.         {
  244.             throw new ezcImageFileNotProcessableException(
  245.                 $this->getReferenceData$image'resource' ),
  246.                 "The command '{$command}' resulted in an error ({$status['exitcode']}): '{$errorString}'. Output: '{$outputString}'"
  247.             );
  248.         }
  249.         // Finish atomic file operation
  250.         copy$this->getReferenceData$image'resource' )$this->getReferenceData$image'file' ) );
  251.     }
  252.  
  253.     /**
  254.      * Returns a string representation of the given color array.
  255.      *
  256.      * ImageConversion uses arrays to represent color values, in the format:
  257.      * <code>
  258.      * array(
  259.      *      255,
  260.      *      0,
  261.      *      0,
  262.      * )
  263.      * </code>
  264.      * This array represents the color red.
  265.      *
  266.      * This method takes such a color array and converts it into a string
  267.      * representation usable by the convert binary. For the above examle it
  268.      * would be '#FF0000'.
  269.      * 
  270.      * @param array $color 
  271.      * @return void 
  272.      *
  273.      * @throws ezcBaseValueException
  274.      *          if one of the color values in the array is invalid (not integer,
  275.      *          smaller than 0 or larger than 255).
  276.      */
  277.     protected function colorArrayToStringarray $color )
  278.     {
  279.         $colorString '#';
  280.         $i 0;
  281.         foreach $color as $id => $colorVal )
  282.         {
  283.             if $i++ > )
  284.             {
  285.                 break;
  286.             }
  287.             if !is_int$colorVal || $colorVal || $colorVal 255 )
  288.             {
  289.                 throw new ezcBaseValueException"color[$id]"$color[$id]'int > 0 and < 256' );
  290.             }
  291.             $colorString .= sprintf'%02x'$colorVal );
  292.         }
  293.         return $colorString;
  294.     }
  295.  
  296.     /**
  297.      * Close the file referenced by $image.
  298.      * Frees the image reference. You should call close() before.
  299.      *
  300.      * @see ezcImageHandler::load()
  301.      * @see ezcImageHandler::save()
  302.      * @param string $image The image reference.
  303.      */
  304.     public function close$image )
  305.     {
  306.         unlink$this->getReferenceData$image'resource' ) );
  307.         $this->setReferenceData$imagefalse'resource' );
  308.         $this->closeCommon$image );
  309.     }
  310.  
  311.     /**
  312.      * Add a filter option to a given reference
  313.      *
  314.      * @param string $reference The reference to add a filter for.
  315.      * @param string $name      The option name.
  316.      * @param string $parameter The option parameter.
  317.      * @return void 
  318.      */
  319.     protected function addFilterOption$reference$name$parameter null )
  320.     {
  321.         $this->filterOptions[$reference][$name $parameter !== null ' ' escapeshellarg$parameter '' );
  322.     }
  323.  
  324.     /**
  325.      * Add an image to composite with the given reference.
  326.      * 
  327.      * @param string $reference The reference to add an image to
  328.      * @param string $file      The file to composite with the image.
  329.      * @return void 
  330.      */
  331.     protected function addCompositeImage$reference$file )
  332.     {
  333.         $this->compositeImages[$reference][$file;
  334.     }
  335.  
  336.     /**
  337.      * Determines the supported input/output types supported by handler.
  338.      * Set's various attributes to reflect the MIME types this handler is
  339.      * capable to process.
  340.      *
  341.      * @return void 
  342.      *
  343.      * @apichange Faulty MIME type "image/svg" will be removed and replaced by
  344.      *             correct MIME type image/svg+xml.
  345.      */
  346.     private function determineTypes()
  347.     {
  348.         $tagMap array(
  349.             'application/pcl' => 'PCL',
  350.             'application/pdf' => 'PDF',
  351.             'application/postscript' => 'PS',
  352.             'application/vnd.palm' => 'PDB',
  353.             'application/x-icb' => 'ICB',
  354.             'application/x-mif' => 'MIFF',
  355.             'image/bmp' => 'BMP3',
  356.             'image/dcx' => 'DCX',
  357.             'image/g3fax' => 'G3',
  358.             'image/gif' => 'GIF',
  359.             'image/jng' => 'JNG',
  360.             'image/jpeg' => 'JPG',
  361.             'image/pbm' => 'PBM',
  362.             'image/pcd' => 'PCD',
  363.             'image/pict' => 'PCT',
  364.             'image/pjpeg' => 'PJPEG',
  365.             'image/png' => 'PNG',
  366.             'image/ras' => 'RAS',
  367.             'image/sgi' => 'SGI',
  368.             'image/svg+xml' => 'SVG',
  369.             // Left over for BC reasons
  370.             'image/svg' => 'SVG',
  371.             'image/tga' => 'TGA',
  372.             'image/tiff' => 'TIF',
  373.             'image/vda' => 'VDA',
  374.             'image/vnd.wap.wbmp' => 'WBMP',
  375.             'image/vst' => 'VST',
  376.             'image/x-fits' => 'FITS',
  377.             'image/x-otb' => 'OTB',
  378.             'image/x-palm' => 'PALM',
  379.             'image/x-pcx' => 'PCX',
  380.             'image/x-pgm' => 'PGM',
  381.             'image/psd' => 'PSD',
  382.             'image/x-ppm' => 'PPM',
  383.             'image/x-ptiff' => 'PTIF',
  384.             'image/x-viff' => 'VIFF',
  385.             'image/x-xbitmap' => 'XPM',
  386.             'image/x-xv' => 'P7',
  387.             'image/xpm' => 'PICON',
  388.             'image/xwd' => 'XWD',
  389.             'text/plain' => 'TXT',
  390.             'video/mng' => 'MNG',
  391.             'video/mpeg' => 'MPEG',
  392.             'video/mpeg2' => 'M2V',
  393.         );
  394.         $types array_keys$tagMap );
  395.         $this->inputTypes $types;
  396.         $this->outputTypes $types;
  397.         $this->tagMap $tagMap;
  398.     }
  399.  
  400.     /**
  401.      * Checks for ImageMagick on the system.
  402.      *
  403.      * @param ezcImageHandlerSettings $settings The settings object of the current handler instance.
  404.      * @return void 
  405.      *
  406.      * @throws ezcImageHandlerNotAvailableException
  407.      *          If the ImageMagick binary is not found.
  408.      */
  409.     private function checkImageMagickezcImageHandlerSettings $settings )
  410.     {
  411.         if !isset$settings->options['binary') )
  412.         {
  413.             $this->binary ezcBaseFeatures::getImageConvertExecutable();
  414.         }
  415.         else if file_exists$settings->options['binary') )
  416.         {
  417.             $this->binary $settings->options['binary'];
  418.         }
  419.  
  420.         if $this->binary === null )
  421.         {
  422.             throw new ezcImageHandlerNotAvailableException(
  423.                 'ezcImageImagemagickHandler',
  424.                 'ImageMagick not installed or not available in PATH variable.'
  425.             );
  426.         }
  427.         
  428.         // Prepare to run ImageMagick command
  429.         $descriptors array
  430.             array'pipe''r' ),
  431.             array'pipe''w' ),
  432.             array'pipe''w' ),
  433.         );
  434.  
  435.         // Open ImageMagick process
  436.         $imageProcess proc_open$this->binary$descriptors$pipes );
  437.  
  438.         // Close STDIN pipe
  439.         fclose$pipes[0);
  440.  
  441.         $outputString '';
  442.         // Read STDOUT 
  443.         do 
  444.         {
  445.             $outputString .= rtrimfgets$pipes[1]1024 )"\n" );
  446.         while !feof$pipes[1) );
  447.  
  448.         $errorString '';
  449.         // Read STDERR 
  450.         do 
  451.         {
  452.             $errorString .= rtrimfgets$pipes[2]1024 )"\n" );
  453.         while !feof$pipes[2) );
  454.         
  455.         // Wait for process to terminate and store return value
  456.         $return proc_close$imageProcess );
  457.  
  458.         // Process potential errors
  459.         if strlen$errorString || strpos$outputString'ImageMagick' === false )
  460.         {
  461.             throw new ezcImageHandlerNotAvailableException'ezcImageImagemagickHandler''ImageMagick not installed or not available in PATH variable.' );
  462.         }
  463.     }
  464.     
  465.     /**
  466.      * Creates default settings for the handler and returns it.
  467.      * The reference name will be set to 'ImageMagick'.
  468.      *
  469.      * @return ezcImageHandlerSettings 
  470.      */
  471.     static public function defaultSettings()
  472.     {
  473.         return new ezcImageHandlerSettings'ImageMagick''ezcImageImagemagickHandler' );
  474.     }
  475. }
  476.  
  477. ?>
Documentation generated by phpDocumentor 1.4.3