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

Source for file php.php

Documentation is available at php.php

  1. <?php
  2. /**
  3.  * File containing the ezcImageAnalyzerPhpHandler 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 ImageAnalysis
  23.  * @version //autogentag//
  24.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25.  * @filesource
  26.  */
  27.  
  28. /**
  29.  * Class to retrieve information about a given image file.
  30.  * This handler implements image analyzation using direct PHP functionality,
  31.  * mainly the {@link getimagesize()} function and, if available, the EXIF
  32.  * extension {@link exif_read_data()}. The driver is capable of determining
  33.  * the type the following file formats:
  34.  *
  35.  * - GIF
  36.  * - JPG
  37.  * - PNG
  38.  * - SWF
  39.  * - SWC
  40.  * - PSD
  41.  * - TIFF
  42.  * - BMP
  43.  * - IFF
  44.  * - JP2
  45.  * - JPX
  46.  * - JB2
  47.  * - JPC
  48.  * - XBM
  49.  * - WBMP
  50.  *
  51.  * The driver determines the MIME type of these images (using the
  52.  * {@link ezcImageAnalyzerPhpHandler::analyzeType()} method). The width,
  53.  * height and size of the given image are always available after analyzing a
  54.  * file, if the file in general can be analyzed
  55.  * {@link ezcImageAnalyzerPhpHandler::canAnalyze()}.
  56.  *
  57.  * For JPEG and TIFF images this driver will try to read in information using
  58.  * the EXIF extension in PHP and fills in the following properties of the
  59.  * {@link ezcImageAnalyzerData} struct, returned by the
  60.  * {@link ezcImageAnalyzerPhpHandler::analyzeImage()} method:
  61.  * - exif
  62.  * - isColor
  63.  * - comment
  64.  * - copyright
  65.  * - date
  66.  * - hasThumbnail
  67.  * - isAnimated
  68.  *
  69.  * For GIF (also animated) it finds information by scanning the file manually
  70.  * and fills in the following properties of the
  71.  * {@link ezcImageAnalyzerData} struct, returned by the
  72.  * {@link ezcImageAnalyzerPhpHandler::analyzeImage()} method:
  73.  * - mode
  74.  * - transparencyType
  75.  * - comment
  76.  * - commentList
  77.  * - colorCount
  78.  * - isAnimated
  79.  *
  80.  * @package ImageAnalysis
  81.  * @version //autogentag//
  82.  */
  83. {
  84.     /**
  85.      * Analyzes the image type.
  86.      *
  87.      * This method analyzes image data to determine the MIME type. This method
  88.      * returns the MIME type of the file to analyze in lowercase letters (e.g.
  89.      * "image/jpeg") or false, if the images MIME type could not be determined.
  90.      *
  91.      * For a list of image types this handler will be able to analyze, see
  92.      * {@link ezcImageAnalyzerPhpHandler}.
  93.      *
  94.      * @param string $file The file to analyze.
  95.      * @return string|boolThe MIME type if analyzation suceeded or false.
  96.      */
  97.     public function analyzeType$file )
  98.     {
  99.         $data getimagesize$file );
  100.         if $data === false )
  101.         {
  102.             return false;
  103.         }
  104.         return image_type_to_mime_type$data[2);
  105.     }
  106.  
  107.     /**
  108.      * Analyze the image for detailed information.
  109.      *
  110.      * This may return various information about the image, depending on it's
  111.      * type. All information is collected in the struct
  112.      * {@link ezcImageAnalyzerData}. At least the
  113.      * {@link ezcImageAnalyzerData::$mime} attribute is always available, if the
  114.      * image type can be analyzed at all. Additionally this handler will always
  115.      * set the {@link ezcImageAnalyzerData::$width},
  116.      * {@link ezcImageAnalyzerData::$height} and
  117.      * {@link ezcImageAnalyzerData::$size} attributes. For detailes information
  118.      * on the additional data returned, see {@link ezcImageAnalyzerPhpHandler}.
  119.      *
  120.      * @throws ezcImageAnalyzerFileNotProcessableException
  121.      *          If image file can not be processed.
  122.      * @param string $file The file to analyze.
  123.      * @return ezcImageAnalyzerData 
  124.      */
  125.     public function analyzeImage$file )
  126.     {
  127.         $data getimagesize$file );
  128.         if $data === false )
  129.         {
  130.             throw new ezcImageAnalyzerFileNotProcessableException(
  131.                 $file,
  132.                 'getimagesize() returned false.'
  133.             );
  134.         }
  135.  
  136.         $dataStruct new ezcImageAnalyzerData();
  137.         $dataStruct->width $data[0];
  138.         $dataStruct->height $data[1];
  139.         $dataStruct->mime image_type_to_mime_type$data[2);
  140.         $dataStruct->size filesize$file );
  141.  
  142.         if ( ( $dataStruct->mime === 'image/jpeg' || $dataStruct->mime === 'image/tiff' )
  143.              && ezcBaseFeatures::hasFunction'exif_read_data')
  144.            )
  145.         {
  146.             $this->analyzeExif$file$dataStruct );
  147.         }
  148.         elseif $dataStruct->mime === 'image/gif' )
  149.         {
  150.             $this->analyzeGif$file$dataStruct );
  151.         }
  152.  
  153.         return $dataStruct;
  154.     }
  155.  
  156.     /**
  157.      * Returns if the handler can analyze a given MIME type.
  158.      *
  159.      * This method returns if the driver is capable of analyzing a given MIME
  160.      * type. This method should be called before trying to actually analyze an
  161.      * image using the drivers {@link self::analyzeImage()} method.
  162.      *
  163.      * @param string $mime The MIME type to check for.
  164.      * @return bool True if the handler is able to analyze the MIME type.
  165.      */
  166.     public function canAnalyze$mime )
  167.     {
  168.         switch $mime )
  169.         {
  170.             case 'image/gif':
  171.             case 'image/jpeg':
  172.             case 'image/png':
  173.             case 'image/psd':
  174.             case 'image/bmp':
  175.             case 'image/tiff':
  176.             case 'image/tiff':
  177.             case 'image/jp2':
  178.             case 'application/x-shockwave-flash':
  179.             case 'image/iff':
  180.             case 'image/vnd.wap.wbmp':
  181.             case 'image/xbm':
  182.                 return true;
  183.         }
  184.         return false;
  185.     }
  186.  
  187.     /**
  188.      * Checks wether the GD handler is available on the system.
  189.      *
  190.      * Returns if PHP's {@link getimagesize()} function is available.
  191.      *
  192.      * @return bool True is the handler is available.
  193.      */
  194.     public function isAvailable()
  195.     {
  196.         return ezcBaseFeatures::hasFunction'getimagesize' );
  197.     }
  198.  
  199.     /**
  200.      * Analyze EXIF enabled file format for EXIF data entries.
  201.      *
  202.      * The image file is analyzed by calling exif_read_data and placing the
  203.      * result in self::exif. In addition it fills in extra properties from
  204.      * the EXIF data for easy and uniform access.
  205.      *
  206.      * @param string $file                     The file to analyze.
  207.      * @param ezcImageAnalyzerData $dataStruct The data struct to fill.
  208.      * @return ezcImageAnalyzerData The filled data struct.
  209.      */
  210.     private function analyzeExif$fileezcImageAnalyzerData $dataStruct )
  211.     {
  212.         $dataStruct->exif exif_read_data$file"COMPUTED,FILE"truefalse );
  213.  
  214.         // Section "COMPUTED"
  215.         if isset$dataStruct->exif['COMPUTED']['Width'&& isset$dataStruct->exif['COMPUTED']['Height') )
  216.         {
  217.             $dataStruct->width $dataStruct->exif['COMPUTED']['Width'];
  218.             $dataStruct->height $dataStruct->exif['COMPUTED']['Height'];
  219.         }
  220.         if isset$dataStruct->exif['COMPUTED']['IsColor') )
  221.         {
  222.             $dataStruct->isColor $dataStruct->exif['COMPUTED']['IsColor'== 1;
  223.         }
  224.         if isset$dataStruct->exif['COMPUTED']['UserComment') )
  225.         {
  226.             $dataStruct->comment $dataStruct->exif['COMPUTED']['UserComment'];
  227.             $dataStruct->commentList array$dataStruct->comment );
  228.         }
  229.         if isset$dataStruct->exif['COMPUTED']['Copyright') )
  230.         {
  231.             $dataStruct->copyright $dataStruct->exif['COMPUTED']['Copyright'];
  232.         }
  233.  
  234.         // Section THUMBNAIL
  235.         $dataStruct->hasThumbnail = isset$dataStruct->exif['THUMBNAIL');
  236.  
  237.         // Section "FILE"
  238.         if isset$dataStruct->exif['FILE']['FileSize') )
  239.         {
  240.             $dataStruct->size $dataStruct->exif['FILE']['FileSize'];
  241.         }
  242.         if isset$dataStruct->exif['FILE']['FileDateTime') )
  243.         {
  244.             $dataStruct->date $dataStruct->exif['FILE']['FileDateTime'];
  245.         }
  246.  
  247.         // EXIF based image are never animated.
  248.         $dataStruct->isAnimated false;
  249.  
  250.         return $dataStruct;
  251.     }
  252.  
  253.     /**
  254.      * Analyze GIF files for detailed information.
  255.      *
  256.      * The GIF file is analyzed by scanning for frame entries, if more than one
  257.      * is found it is assumed to be animated.
  258.      * It also extracts other information such as image width and height, color
  259.      * count, image mode, transparency type and comments.
  260.      *
  261.      * @throws ezcBaseFileIoException
  262.      *          If image file could not be read.
  263.      * @throws ezcImageAnalyzerFileNotProcessableException
  264.      *          If image file can not be processed.
  265.      * @param string $file                     The file to analyze.
  266.      * @param ezcImageAnalyzerData $dataStruct The data struct to fill.
  267.      * @return ezcImageAnalyzerData The filled data struct.
  268.      */
  269.     private function analyzeGif$fileezcImageAnalyzerData $dataStruct )
  270.     {
  271.         if ( ( $fp fopen$file'rb' ) ) === false )
  272.         {
  273.             throw new ezcBaseFileIoException$fileezcBaseFileException::READ );
  274.         }
  275.  
  276.         // Read GIF header
  277.         $magic fread$fp);
  278.         $offset 6;
  279.         if $magic != 'GIF87a' &&
  280.              $magic != 'GIF89a' )
  281.         {
  282.             throw new ezcImageAnalyzerFileNotProcessableException$file'Not a valid GIF image file' );
  283.         }
  284.  
  285.         $info array();
  286.  
  287.         $version substr$magic);
  288.         $frames 0;
  289.         // Gifs are always indexed
  290.         $dataStruct->mode             self::MODE_INDEXED;
  291.         $dataStruct->commentList      array();
  292.         $dataStruct->transparencyType self::TRANSPARENCY_OPAQUE;
  293.  
  294.         // Read Logical Screen Descriptor
  295.         $data unpack"v1width/v1height/C1bitfield/C1index/C1ration"fread$fp) );
  296.         $offset += 7;
  297.  
  298.         $lsdFields            $data['bitfield'];
  299.         $globalColorCount     0;
  300.         $globalColorTableSize 0;
  301.         if $lsdFields >> )
  302.         {
  303.             // Extract 3 bits for color count
  304.             $globalColorCount     << ( ( $lsdFields 0x07 1) );
  305.             // Each color entry is RGB ie. 3 bytes
  306.             $globalColorTableSize $globalColorCount 3;
  307.         }
  308.  
  309.         $dataStruct->colorCount $globalColorCount;
  310.         $dataStruct->width      $data['width'];
  311.         $dataStruct->height     $data['height'];
  312.  
  313.         if $globalColorTableSize )
  314.         {
  315.             // Skip the color table, we don't need the data
  316.             fseek$fp$globalColorTableSizeSEEK_CUR );
  317.             $offset += $globalColorTableSize;
  318.         }
  319.  
  320.         $done false;
  321.         // Iterate over all blocks and extract information
  322.         while !$done )
  323.         {
  324.             $data      fread$fp);
  325.             $offset   += 1;
  326.             $blockType ord$data[0);
  327.  
  328.             if $blockType == 0x21 // Extension Introducer
  329.             {
  330.                 $data          .= fread$fp);
  331.                 $offset        += 1;
  332.                 $extensionLabel ord$data[1);
  333.  
  334.                 if $extensionLabel == 0xf9 // Graphical Control Extension
  335.                 {
  336.                     $data     unpack"C1blocksize/C1bitfield/v1delay/C1index/C1term"fread$fp) );
  337.                     $gceFlags $data['bitfield'];//ord( $data[1] );
  338.                     // $animationTimer is currently not in use.
  339.                     /* $animationTimer = $data['delay']; */
  340.  
  341.                     // Check bit 0
  342.                     if $gceFlags 0x01 )
  343.                     {
  344.                         $dataStruct->transparencyType self::TRANSPARENCY_TRANSPARENT;
  345.                     }
  346.                     $offset += 1;
  347.                 }
  348.                 else if $extensionLabel == 0xff // Application Extension
  349.                 {
  350.                     $data    fread$fp12 );
  351.                     $offset += 12;
  352.  
  353.                     $dataBlockDone false;
  354.                     while !$dataBlockDone )
  355.                     {
  356.                         $data       unpack"C1blocksize"fread$fp) );
  357.                         $offset    += 1;
  358.                         $blockBytes $data['blocksize'];
  359.  
  360.                         if $blockBytes )
  361.                         {
  362.                             // Skip application data, we don't need the data
  363.                             fseek$fp$blockBytesSEEK_CUR );
  364.                             $offset += $blockBytes;
  365.                         }
  366.                         else
  367.                         {
  368.                             $dataBlockDone true;
  369.                         }
  370.                     }
  371.                 }
  372.                 else if $extensionLabel == 0xfe // Comment Extension
  373.                 {
  374.                     $commentBlockDone false;
  375.                     $comment          false;
  376.  
  377.                     while !$commentBlockDone )
  378.                     {
  379.                         $data       unpack"C1blocksize"fread$fp) );
  380.                         $offset    += 1;
  381.                         $blockBytes $data['blocksize'];
  382.  
  383.                         if $blockBytes )
  384.                         {
  385.                             // Append current block to comment
  386.                             $data     fread$fp$blockBytes );
  387.                             $comment .= $data;
  388.                             $offset  += $blockBytes;
  389.                         }
  390.                         else
  391.                         {
  392.                             $commentBlockDone true;
  393.                         }
  394.                     }
  395.                     if $comment )
  396.                     {
  397.                         if $dataStruct->comment === null )
  398.                         {
  399.                             $dataStruct->comment $comment;
  400.                         }
  401.                         $dataStruct->commentList[$comment;
  402.                     }
  403.                 }
  404.                 else
  405.                 {
  406.                     throw new ezcImageAnalyzerFileNotProcessableException$file"Invalid extension label 0x" hexdec$extensionLabel " in GIF image." );
  407.                 }
  408.             }
  409.             else if $blockType == 0x2c // Image Descriptor
  410.             {
  411.                 ++$frames;
  412.                 $data               .= fread$fp);
  413.                 $data                unpack"C1separator/v1leftpos/v1toppos/v1width/v1height/C1bitfield"$data );
  414.                 $localColorTableSize 0;
  415.                 $localColorCount     0;
  416.                 $idFields            $data['bitfield'];
  417.                 if $idFields >> // Local Color Table
  418.                 {
  419.                     // Extract 3 bits for color count
  420.                     $localColorCount     << ( ( $idFields 0x07 1) );
  421.                     // Each color entry is RGB ie. 3 bytes
  422.                     $localColorTableSize $localColorCount 3;
  423.                 }
  424.                 if $localColorCount $globalColorCount )
  425.                 {
  426.                     $dataStruct->colorCount $localColorCount;
  427.                 }
  428.  
  429.                 if $localColorTableSize )
  430.                 {
  431.                     // Skip the color table, we don't need the data
  432.                     fseek$fp$localColorTableSizeSEEK_CUR );
  433.                     $offset += $localColorTableSize;
  434.                 }
  435.  
  436.                 $lzwCodeSize fread$fp)// LZW Minimum Code Size, currently unused
  437.                 $offset     += 1;
  438.  
  439.                 $dataBlockDone false;
  440.                 while !$dataBlockDone )
  441.                 {
  442.                     $data       unpack"C1blocksize"fread$fp) );
  443.                     $offset    += 1;
  444.                     $blockBytes $data['blocksize'];
  445.  
  446.                     if $blockBytes )
  447.                     {
  448.                         // Skip image data, we don't need the data
  449.                         fseek$fp$blockBytesSEEK_CUR );
  450.                         $offset += $blockBytes;
  451.                     }
  452.                     else
  453.                     {
  454.                         $dataBlockDone true;
  455.                     }
  456.                 }
  457.             }
  458.             else if $blockType == 0x3b // Trailer, end of stream
  459.             {
  460.                 $done true;
  461.             }
  462.             else
  463.             {
  464.                 throw new ezcImageAnalyzerFileNotProcessableException$file"Invalid block type 0x" hexdec$blockType " in GIF image." );
  465.             }
  466.             if feof$fp ) )
  467.             {
  468.                 break;
  469.             }
  470.         }
  471.         $dataStruct->isAnimated $frames 1;
  472.  
  473.         return $dataStruct;
  474.     }
  475. }
  476. ?>
Documentation generated by phpDocumentor 1.4.3