Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   1  <?php
   2  //============================================================+
   3  // File name   : tcpdf_images.php
   4  // Version     : 1.0.005
   5  // Begin       : 2002-08-03
   6  // Last Update : 2014-11-15
   7  // Author      : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
   8  // License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
   9  // -------------------------------------------------------------------
  10  // Copyright (C) 2002-2014 Nicola Asuni - Tecnick.com LTD
  11  //
  12  // This file is part of TCPDF software library.
  13  //
  14  // TCPDF is free software: you can redistribute it and/or modify it
  15  // under the terms of the GNU Lesser General Public License as
  16  // published by the Free Software Foundation, either version 3 of the
  17  // License, or (at your option) any later version.
  18  //
  19  // TCPDF is distributed in the hope that it will be useful, but
  20  // WITHOUT ANY WARRANTY; without even the implied warranty of
  21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  22  // See the GNU Lesser General Public License for more details.
  23  //
  24  // You should have received a copy of the License
  25  // along with TCPDF. If not, see
  26  // <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
  27  //
  28  // See LICENSE.TXT file for more information.
  29  // -------------------------------------------------------------------
  30  //
  31  // Description :
  32  //   Static image methods used by the TCPDF class.
  33  //
  34  //============================================================+
  35  
  36  /**
  37   * @file
  38   * This is a PHP class that contains static image methods for the TCPDF class.<br>
  39   * @package com.tecnick.tcpdf
  40   * @author Nicola Asuni
  41   * @version 1.0.005
  42   */
  43  
  44  /**
  45   * @class TCPDF_IMAGES
  46   * Static image methods used by the TCPDF class.
  47   * @package com.tecnick.tcpdf
  48   * @brief PHP class for generating PDF documents without requiring external extensions.
  49   * @version 1.0.005
  50   * @author Nicola Asuni - info@tecnick.com
  51   */
  52  class TCPDF_IMAGES {
  53  
  54  	 /**
  55  	  * Array of hinheritable SVG properties.
  56  	  * @since 5.0.000 (2010-05-02)
  57  	  * @public static
  58  	  */
  59  	 public static $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', 'fill', 'fill-opacity', 'fill-rule', 'font', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'marker', 'marker-end', 'marker-mid', 'marker-start', 'pointer-events', 'shape-rendering', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-rendering', 'visibility', 'word-spacing', 'writing-mode');
  60  
  61  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  62  
  63  	 /**
  64  	  * Return the image type given the file name or array returned by getimagesize() function.
  65  	  * @param $imgfile (string) image file name
  66  	  * @param $iminfo (array) array of image information returned by getimagesize() function.
  67  	  * @return string image type
  68  	  * @since 4.8.017 (2009-11-27)
  69  	  * @public static
  70  	  */
  71  	public static function getImageFileType($imgfile, $iminfo=array()) {
  72  	 	 $type = '';
  73  	 	 if (isset($iminfo['mime']) AND !empty($iminfo['mime'])) {
  74  	 	 	 $mime = explode('/', $iminfo['mime']);
  75  	 	 	 if ((count($mime) > 1) AND ($mime[0] == 'image') AND (!empty($mime[1]))) {
  76  	 	 	 	 $type = strtolower(trim($mime[1]));
  77  	 	 	 }
  78  	 	 }
  79  	 	 if (empty($type)) {
  80  	 	 	 $fileinfo = pathinfo($imgfile);
  81  	 	 	 if (isset($fileinfo['extension']) AND (!TCPDF_STATIC::empty_string($fileinfo['extension']))) {
  82  	 	 	 	 $type = strtolower(trim($fileinfo['extension']));
  83  	 	 	 }
  84  	 	 }
  85  	 	 if ($type == 'jpg') {
  86  	 	 	 $type = 'jpeg';
  87  	 	 }
  88  	 	 return $type;
  89  	 }
  90  
  91  	 /**
  92  	  * Set the transparency for the given GD image.
  93  	  * @param $new_image (image) GD image object
  94  	  * @param $image (image) GD image object.
  95  	  * return GD image object.
  96  	  * @since 4.9.016 (2010-04-20)
  97  	  * @public static
  98  	  */
  99  	public static function setGDImageTransparency($new_image, $image) {
 100  	 	 // default transparency color (white)
 101  	 	 $tcol = array('red' => 255, 'green' => 255, 'blue' => 255);
 102  	 	 // transparency index
 103  	 	 $tid = imagecolortransparent($image);
 104  	 	 $palletsize = imagecolorstotal($image);
 105  	 	 if (($tid >= 0) AND ($tid < $palletsize)) {
 106  	 	 	 // get the colors for the transparency index
 107  	 	 	 $tcol = imagecolorsforindex($image, $tid);
 108  	 	 }
 109  	 	 $tid = imagecolorallocate($new_image, $tcol['red'], $tcol['green'], $tcol['blue']);
 110  	 	 imagefill($new_image, 0, 0, $tid);
 111  	 	 imagecolortransparent($new_image, $tid);
 112  	 	 return $new_image;
 113  	 }
 114  
 115  	 /**
 116  	  * Convert the loaded image to a PNG and then return a structure for the PDF creator.
 117  	  * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
 118  	  * @param $image (image) Image object.
 119  	  * @param $tempfile (string) Temporary file name.
 120  	  * return image PNG image object.
 121  	  * @since 4.9.016 (2010-04-20)
 122  	  * @public static
 123  	  */
 124  	public static function _toPNG($image, $tempfile) {
 125  	 	 // turn off interlaced mode
 126  	 	 imageinterlace($image, 0);
 127  	 	 // create temporary PNG image
 128  	 	 imagepng($image, $tempfile);
 129  	 	 // remove image from memory
 130  	 	 imagedestroy($image);
 131  	 	 // get PNG image data
 132  	 	 $retvars = self::_parsepng($tempfile);
 133  	 	 // tidy up by removing temporary image
 134  	 	 unlink($tempfile);
 135  	 	 return $retvars;
 136  	 }
 137  
 138  	 /**
 139  	  * Convert the loaded image to a JPEG and then return a structure for the PDF creator.
 140  	  * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
 141  	  * @param $image (image) Image object.
 142  	  * @param $quality (int) JPEG quality.
 143  	  * @param $tempfile (string) Temporary file name.
 144  	  * return image JPEG image object.
 145  	  * @public static
 146  	  */
 147  	public static function _toJPEG($image, $quality, $tempfile) {
 148  	 	 imagejpeg($image, $tempfile, $quality);
 149  	 	 imagedestroy($image);
 150  	 	 $retvars = self::_parsejpeg($tempfile);
 151  	 	 // tidy up by removing temporary image
 152  	 	 unlink($tempfile);
 153  	 	 return $retvars;
 154  	 }
 155  
 156  	 /**
 157  	  * Extract info from a JPEG file without using the GD library.
 158  	  * @param $file (string) image file to parse
 159  	  * @return array structure containing the image data
 160  	  * @public static
 161  	  */
 162  	public static function _parsejpeg($file) {
 163  	 	 // check if is a local file
 164  	 	 if (!@TCPDF_STATIC::file_exists($file)) {
 165  	 	 	 return false;
 166  	 	 }
 167  	 	 $a = getimagesize($file);
 168  	 	 if (empty($a)) {
 169  	 	 	 //Missing or incorrect image file
 170  	 	 	 return false;
 171  	 	 }
 172  	 	 if ($a[2] != 2) {
 173  	 	 	 // Not a JPEG file
 174  	 	 	 return false;
 175  	 	 }
 176  	 	 // bits per pixel
 177  	 	 $bpc = isset($a['bits']) ? intval($a['bits']) : 8;
 178  	 	 // number of image channels
 179  	 	 if (!isset($a['channels'])) {
 180  	 	 	 $channels = 3;
 181  	 	 } else {
 182  	 	 	 $channels = intval($a['channels']);
 183  	 	 }
 184  	 	 // default colour space
 185  	 	 switch ($channels) {
 186  	 	 	 case 1: {
 187  	 	 	 	 $colspace = 'DeviceGray';
 188  	 	 	 	 break;
 189  	 	 	 }
 190  	 	 	 case 3: {
 191  	 	 	 	 $colspace = 'DeviceRGB';
 192  	 	 	 	 break;
 193  	 	 	 }
 194  	 	 	 case 4: {
 195  	 	 	 	 $colspace = 'DeviceCMYK';
 196  	 	 	 	 break;
 197  	 	 	 }
 198  	 	 	 default: {
 199  	 	 	 	 $channels = 3;
 200  	 	 	 	 $colspace = 'DeviceRGB';
 201  	 	 	 	 break;
 202  	 	 	 }
 203  	 	 }
 204  	 	 // get file content
 205  	 	 $data = file_get_contents($file);
 206  	 	 // check for embedded ICC profile
 207  	 	 $icc = array();
 208  	 	 $offset = 0;
 209  	 	 while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
 210  	 	 	 // get ICC sequence length
 211  	 	 	 $length = (TCPDF_STATIC::_getUSHORT($data, ($pos - 2)) - 16);
 212  	 	 	 // marker sequence number
 213  	 	 	 $msn = max(1, ord($data[($pos + 12)]));
 214  	 	 	 // number of markers (total of APP2 used)
 215  	 	 	 $nom = max(1, ord($data[($pos + 13)]));
 216  	 	 	 // get sequence segment
 217  	 	 	 $icc[($msn - 1)] = substr($data, ($pos + 14), $length);
 218  	 	 	 // move forward to next sequence
 219  	 	 	 $offset = ($pos + 14 + $length);
 220  	 	 }
 221  	 	 // order and compact ICC segments
 222  	 	 if (count($icc) > 0) {
 223  	 	 	 ksort($icc);
 224  	 	 	 $icc = implode('', $icc);
 225  	 	 	 if ((ord($icc[36]) != 0x61) OR (ord($icc[37]) != 0x63) OR (ord($icc[38]) != 0x73) OR (ord($icc[39]) != 0x70)) {
 226  	 	 	 	 // invalid ICC profile
 227  	 	 	 	 $icc = false;
 228  	 	 	 }
 229  	 	 } else {
 230  	 	 	 $icc = false;
 231  	 	 }
 232  	 	 return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
 233  	 }
 234  
 235  	 /**
 236  	  * Extract info from a PNG file without using the GD library.
 237  	  * @param $file (string) image file to parse
 238  	  * @return array structure containing the image data
 239  	  * @public static
 240  	  */
 241  	public static function _parsepng($file) {
 242  	 	 $f = @fopen($file, 'rb');
 243  	 	 if ($f === false) {
 244  	 	 	 // Can't open image file
 245  	 	 	 return false;
 246  	 	 }
 247  	 	 //Check signature
 248  	 	 if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
 249  	 	 	 // Not a PNG file
 250  	 	 	 return false;
 251  	 	 }
 252  	 	 //Read header chunk
 253  	 	 fread($f, 4);
 254  	 	 if (fread($f, 4) != 'IHDR') {
 255  	 	 	 //Incorrect PNG file
 256  	 	 	 return false;
 257  	 	 }
 258  	 	 $w = TCPDF_STATIC::_freadint($f);
 259  	 	 $h = TCPDF_STATIC::_freadint($f);
 260  	 	 $bpc = ord(fread($f, 1));
 261  	 	 $ct = ord(fread($f, 1));
 262  	 	 if ($ct == 0) {
 263  	 	 	 $colspace = 'DeviceGray';
 264  	 	 } elseif ($ct == 2) {
 265  	 	 	 $colspace = 'DeviceRGB';
 266  	 	 } elseif ($ct == 3) {
 267  	 	 	 $colspace = 'Indexed';
 268  	 	 } else {
 269  	 	 	 // alpha channel
 270  	 	 	 fclose($f);
 271  	 	 	 return 'pngalpha';
 272  	 	 }
 273  	 	 if (ord(fread($f, 1)) != 0) {
 274  	 	 	 // Unknown compression method
 275  	 	 	 fclose($f);
 276  	 	 	 return false;
 277  	 	 }
 278  	 	 if (ord(fread($f, 1)) != 0) {
 279  	 	 	 // Unknown filter method
 280  	 	 	 fclose($f);
 281  	 	 	 return false;
 282  	 	 }
 283  	 	 if (ord(fread($f, 1)) != 0) {
 284  	 	 	 // Interlacing not supported
 285  	 	 	 fclose($f);
 286  	 	 	 return false;
 287  	 	 }
 288  	 	 fread($f, 4);
 289  	 	 $channels = ($ct == 2 ? 3 : 1);
 290  	 	 $parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>';
 291  	 	 //Scan chunks looking for palette, transparency and image data
 292  	 	 $pal = '';
 293  	 	 $trns = '';
 294  	 	 $data = '';
 295  	 	 $icc = false;
 296  	 	 $n = TCPDF_STATIC::_freadint($f);
 297  	 	 do {
 298  	 	 	 $type = fread($f, 4);
 299  	 	 	 if ($type == 'PLTE') {
 300  	 	 	 	 // read palette
 301  	 	 	 	 $pal = TCPDF_STATIC::rfread($f, $n);
 302  	 	 	 	 fread($f, 4);
 303  	 	 	 } elseif ($type == 'tRNS') {
 304  	 	 	 	 // read transparency info
 305  	 	 	 	 $t = TCPDF_STATIC::rfread($f, $n);
 306  	 	 	 	 if ($ct == 0) { // DeviceGray
 307  	 	 	 	 	 $trns = array(ord($t[1]));
 308  	 	 	 	 } elseif ($ct == 2) { // DeviceRGB
 309  	 	 	 	 	 $trns = array(ord($t[1]), ord($t[3]), ord($t[5]));
 310  	 	 	 	 } else { // Indexed
 311  	 	 	 	 	 if ($n > 0) {
 312  	 	 	 	 	 	 $trns = array();
 313  	 	 	 	 	 	 for ($i = 0; $i < $n; ++ $i) {
 314  	 	 	 	 	 	 	 $trns[] = ord($t[$i]);
 315  	 	 	 	 	 	 }
 316  	 	 	 	 	 }
 317  	 	 	 	 }
 318  	 	 	 	 fread($f, 4);
 319  	 	 	 } elseif ($type == 'IDAT') {
 320  	 	 	 	 // read image data block
 321  	 	 	 	 $data .= TCPDF_STATIC::rfread($f, $n);
 322  	 	 	 	 fread($f, 4);
 323  	 	 	 } elseif ($type == 'iCCP') {
 324  	 	 	 	 // skip profile name
 325  	 	 	 	 $len = 0;
 326  	 	 	 	 while ((ord(fread($f, 1)) != 0) AND ($len < 80)) {
 327  	 	 	 	 	 ++$len;
 328  	 	 	 	 }
 329  	 	 	 	 // get compression method
 330  	 	 	 	 if (ord(fread($f, 1)) != 0) {
 331  	 	 	 	 	 // Unknown filter method
 332  	 	 	 	 	 fclose($f);
 333  	 	 	 	 	 return false;
 334  	 	 	 	 }
 335  	 	 	 	 // read ICC Color Profile
 336  	 	 	 	 $icc = TCPDF_STATIC::rfread($f, ($n - $len - 2));
 337  	 	 	 	 // decompress profile
 338  	 	 	 	 $icc = gzuncompress($icc);
 339  	 	 	 	 fread($f, 4);
 340  	 	 	 } elseif ($type == 'IEND') {
 341  	 	 	 	 break;
 342  	 	 	 } else {
 343  	 	 	 	 TCPDF_STATIC::rfread($f, $n + 4);
 344  	 	 	 }
 345  	 	 	 $n = TCPDF_STATIC::_freadint($f);
 346  	 	 } while ($n);
 347  	 	 if (($colspace == 'Indexed') AND (empty($pal))) {
 348  	 	 	 // Missing palette
 349  	 	 	 fclose($f);
 350  	 	 	 return false;
 351  	 	 }
 352  	 	 fclose($f);
 353  	 	 return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
 354  	 }
 355  
 356  } // END OF TCPDF_IMAGES CLASS
 357  
 358  //============================================================+
 359  // END OF FILE
 360  //============================================================+