Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   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  	  * @var string[]
  60  	  */
  61  	 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');
  62  
  63  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  64  
  65  	 /**
  66  	  * Return the image type given the file name or array returned by getimagesize() function.
  67  	  * @param string $imgfile image file name
  68  	  * @param array $iminfo array of image information returned by getimagesize() function.
  69  	  * @return string image type
  70  	  * @since 4.8.017 (2009-11-27)
  71  	  * @public static
  72  	  */
  73  	public static function getImageFileType($imgfile, $iminfo=array()) {
  74  	 	 $type = '';
  75  	 	 if (isset($iminfo['mime']) AND !empty($iminfo['mime'])) {
  76  	 	 	 $mime = explode('/', $iminfo['mime']);
  77  	 	 	 if ((count($mime) > 1) AND ($mime[0] == 'image') AND (!empty($mime[1]))) {
  78  	 	 	 	 $type = strtolower(trim($mime[1]));
  79  	 	 	 }
  80  	 	 }
  81  	 	 if (empty($type)) {
  82              $type = strtolower(trim(pathinfo(parse_url($imgfile, PHP_URL_PATH), PATHINFO_EXTENSION)));
  83  	 	 }
  84  	 	 if ($type == 'jpg') {
  85  	 	 	 $type = 'jpeg';
  86  	 	 }
  87  	 	 return $type;
  88  	 }
  89  
  90  	 /**
  91  	  * Set the transparency for the given GD image.
  92  	  * @param resource $new_image GD image object
  93  	  * @param resource $image GD image object.
  94  	  * @return resource GD image object $new_image
  95  	  * @since 4.9.016 (2010-04-20)
  96  	  * @public static
  97  	  */
  98  	public static function setGDImageTransparency($new_image, $image) {
  99  	 	 // default transparency color (white)
 100  	 	 $tcol = array('red' => 255, 'green' => 255, 'blue' => 255);
 101  	 	 // transparency index
 102  	 	 $tid = imagecolortransparent($image);
 103  	 	 $palletsize = imagecolorstotal($image);
 104  	 	 if (($tid >= 0) AND ($tid < $palletsize)) {
 105  	 	 	 // get the colors for the transparency index
 106  	 	 	 $tcol = imagecolorsforindex($image, $tid);
 107  	 	 }
 108  	 	 $tid = imagecolorallocate($new_image, $tcol['red'], $tcol['green'], $tcol['blue']);
 109  	 	 imagefill($new_image, 0, 0, $tid);
 110  	 	 imagecolortransparent($new_image, $tid);
 111  	 	 return $new_image;
 112  	 }
 113  
 114  	 /**
 115  	  * Convert the loaded image to a PNG and then return a structure for the PDF creator.
 116  	  * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
 117  	  * @param resource $image Image object.
 118  	  * @param string $tempfile Temporary file name.
 119  	  * return image PNG image object.
 120  	  * @since 4.9.016 (2010-04-20)
 121  	  * @public static
 122  	  */
 123  	public static function _toPNG($image, $tempfile) {
 124  	 	 // turn off interlaced mode
 125  	 	 imageinterlace($image, 0);
 126  	 	 // create temporary PNG image
 127  	 	 imagepng($image, $tempfile);
 128  	 	 // remove image from memory
 129  	 	 imagedestroy($image);
 130  	 	 // get PNG image data
 131  	 	 $retvars = self::_parsepng($tempfile);
 132  	 	 // tidy up by removing temporary image
 133  	 	 unlink($tempfile);
 134  	 	 return $retvars;
 135  	 }
 136  
 137  	 /**
 138  	  * Convert the loaded image to a JPEG and then return a structure for the PDF creator.
 139  	  * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
 140  	  * @param resource $image Image object.
 141  	  * @param int $quality JPEG quality.
 142  	  * @param string $tempfile Temporary file name.
 143  	  * return array|false image JPEG image object.
 144  	  * @public static
 145  	  */
 146  	public static function _toJPEG($image, $quality, $tempfile) {
 147  	 	 imagejpeg($image, $tempfile, $quality);
 148  	 	 imagedestroy($image);
 149  	 	 $retvars = self::_parsejpeg($tempfile);
 150  	 	 // tidy up by removing temporary image
 151  	 	 unlink($tempfile);
 152  	 	 return $retvars;
 153  	 }
 154  
 155  	 /**
 156  	  * Extract info from a JPEG file without using the GD library.
 157  	  * @param string $file image file to parse
 158  	  * @return array|false structure containing the image data
 159  	  * @public static
 160  	  */
 161  	public static function _parsejpeg($file) {
 162  	 	 // check if is a local file
 163  	 	 if (!@TCPDF_STATIC::file_exists($file)) {
 164  	 	 	 return false;
 165  	 	 }
 166  	 	 $a = getimagesize($file);
 167  	 	 if (empty($a)) {
 168  	 	 	 //Missing or incorrect image file
 169  	 	 	 return false;
 170  	 	 }
 171  	 	 if ($a[2] != 2) {
 172  	 	 	 // Not a JPEG file
 173  	 	 	 return false;
 174  	 	 }
 175  	 	 // bits per pixel
 176  	 	 $bpc = isset($a['bits']) ? intval($a['bits']) : 8;
 177  	 	 // number of image channels
 178  	 	 if (!isset($a['channels'])) {
 179  	 	 	 $channels = 3;
 180  	 	 } else {
 181  	 	 	 $channels = intval($a['channels']);
 182  	 	 }
 183  	 	 // default colour space
 184  	 	 switch ($channels) {
 185  	 	 	 case 1: {
 186  	 	 	 	 $colspace = 'DeviceGray';
 187  	 	 	 	 break;
 188  	 	 	 }
 189  	 	 	 case 3: {
 190  	 	 	 	 $colspace = 'DeviceRGB';
 191  	 	 	 	 break;
 192  	 	 	 }
 193  	 	 	 case 4: {
 194  	 	 	 	 $colspace = 'DeviceCMYK';
 195  	 	 	 	 break;
 196  	 	 	 }
 197  	 	 	 default: {
 198  	 	 	 	 $channels = 3;
 199  	 	 	 	 $colspace = 'DeviceRGB';
 200  	 	 	 	 break;
 201  	 	 	 }
 202  	 	 }
 203  	 	 // get file content
 204  	 	 $data = file_get_contents($file);
 205  	 	 // check for embedded ICC profile
 206  	 	 $icc = array();
 207  	 	 $offset = 0;
 208  	 	 while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
 209  	 	 	 // get ICC sequence length
 210  	 	 	 $length = (TCPDF_STATIC::_getUSHORT($data, ($pos - 2)) - 16);
 211  	 	 	 // marker sequence number
 212  	 	 	 $msn = max(1, ord($data[($pos + 12)]));
 213  	 	 	 // number of markers (total of APP2 used)
 214  	 	 	 $nom = max(1, ord($data[($pos + 13)]));
 215  	 	 	 // get sequence segment
 216  	 	 	 $icc[($msn - 1)] = substr($data, ($pos + 14), $length);
 217  	 	 	 // move forward to next sequence
 218  	 	 	 $offset = ($pos + 14 + $length);
 219  	 	 }
 220  	 	 // order and compact ICC segments
 221  	 	 if (count($icc) > 0) {
 222  	 	 	 ksort($icc);
 223  	 	 	 $icc = implode('', $icc);
 224  	 	 	 if ((ord($icc[36]) != 0x61) OR (ord($icc[37]) != 0x63) OR (ord($icc[38]) != 0x73) OR (ord($icc[39]) != 0x70)) {
 225  	 	 	 	 // invalid ICC profile
 226  	 	 	 	 $icc = false;
 227  	 	 	 }
 228  	 	 } else {
 229  	 	 	 $icc = false;
 230  	 	 }
 231  	 	 return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
 232  	 }
 233  
 234  	 /**
 235  	  * Extract info from a PNG file without using the GD library.
 236  	  * @param string $file image file to parse
 237  	  * @return array|false structure containing the image data
 238  	  * @public static
 239  	  */
 240  	public static function _parsepng($file) {
 241  	 	 $f = @fopen($file, 'rb');
 242  	 	 if ($f === false) {
 243  	 	 	 // Can't open image file
 244  	 	 	 return false;
 245  	 	 }
 246  	 	 //Check signature
 247  	 	 if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
 248  	 	 	 // Not a PNG file
 249  	 	 	 return false;
 250  	 	 }
 251  	 	 //Read header chunk
 252  	 	 fread($f, 4);
 253  	 	 if (fread($f, 4) != 'IHDR') {
 254  	 	 	 //Incorrect PNG file
 255  	 	 	 return false;
 256  	 	 }
 257  	 	 $w = TCPDF_STATIC::_freadint($f);
 258  	 	 $h = TCPDF_STATIC::_freadint($f);
 259  	 	 $bpc = ord(fread($f, 1));
 260  	 	 $ct = ord(fread($f, 1));
 261  	 	 if ($ct == 0) {
 262  	 	 	 $colspace = 'DeviceGray';
 263  	 	 } elseif ($ct == 2) {
 264  	 	 	 $colspace = 'DeviceRGB';
 265  	 	 } elseif ($ct == 3) {
 266  	 	 	 $colspace = 'Indexed';
 267  	 	 } else {
 268  	 	 	 // alpha channel
 269  	 	 	 fclose($f);
 270  	 	 	 return 'pngalpha';
 271  	 	 }
 272  	 	 if (ord(fread($f, 1)) != 0) {
 273  	 	 	 // Unknown compression method
 274  	 	 	 fclose($f);
 275  	 	 	 return false;
 276  	 	 }
 277  	 	 if (ord(fread($f, 1)) != 0) {
 278  	 	 	 // Unknown filter method
 279  	 	 	 fclose($f);
 280  	 	 	 return false;
 281  	 	 }
 282  	 	 if (ord(fread($f, 1)) != 0) {
 283  	 	 	 // Interlacing not supported
 284  	 	 	 fclose($f);
 285  	 	 	 return false;
 286  	 	 }
 287  	 	 fread($f, 4);
 288  	 	 $channels = ($ct == 2 ? 3 : 1);
 289  	 	 $parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>';
 290  	 	 //Scan chunks looking for palette, transparency and image data
 291  	 	 $pal = '';
 292  	 	 $trns = '';
 293  	 	 $data = '';
 294  	 	 $icc = false;
 295  	 	 $n = TCPDF_STATIC::_freadint($f);
 296  	 	 do {
 297  	 	 	 $type = fread($f, 4);
 298  	 	 	 if ($type == 'PLTE') {
 299  	 	 	 	 // read palette
 300  	 	 	 	 $pal = TCPDF_STATIC::rfread($f, $n);
 301  	 	 	 	 fread($f, 4);
 302  	 	 	 } elseif ($type == 'tRNS') {
 303  	 	 	 	 // read transparency info
 304  	 	 	 	 $t = TCPDF_STATIC::rfread($f, $n);
 305  	 	 	 	 if ($ct == 0) { // DeviceGray
 306  	 	 	 	 	 $trns = array(ord($t[1]));
 307  	 	 	 	 } elseif ($ct == 2) { // DeviceRGB
 308  	 	 	 	 	 $trns = array(ord($t[1]), ord($t[3]), ord($t[5]));
 309  	 	 	 	 } else { // Indexed
 310  	 	 	 	 	 if ($n > 0) {
 311  	 	 	 	 	 	 $trns = array();
 312  	 	 	 	 	 	 for ($i = 0; $i < $n; ++ $i) {
 313  	 	 	 	 	 	 	 $trns[] = ord($t[$i]);
 314  	 	 	 	 	 	 }
 315  	 	 	 	 	 }
 316  	 	 	 	 }
 317  	 	 	 	 fread($f, 4);
 318  	 	 	 } elseif ($type == 'IDAT') {
 319  	 	 	 	 // read image data block
 320  	 	 	 	 $data .= TCPDF_STATIC::rfread($f, $n);
 321  	 	 	 	 fread($f, 4);
 322  	 	 	 } elseif ($type == 'iCCP') {
 323  	 	 	 	 // skip profile name
 324  	 	 	 	 $len = 0;
 325  	 	 	 	 while ((ord(fread($f, 1)) != 0) AND ($len < 80)) {
 326  	 	 	 	 	 ++$len;
 327  	 	 	 	 }
 328  	 	 	 	 // get compression method
 329  	 	 	 	 if (ord(fread($f, 1)) != 0) {
 330  	 	 	 	 	 // Unknown filter method
 331  	 	 	 	 	 fclose($f);
 332  	 	 	 	 	 return false;
 333  	 	 	 	 }
 334  	 	 	 	 // read ICC Color Profile
 335  	 	 	 	 $icc = TCPDF_STATIC::rfread($f, ($n - $len - 2));
 336  	 	 	 	 // decompress profile
 337  	 	 	 	 $icc = gzuncompress($icc);
 338  	 	 	 	 fread($f, 4);
 339  	 	 	 } elseif ($type == 'IEND') {
 340  	 	 	 	 break;
 341  	 	 	 } else {
 342  	 	 	 	 TCPDF_STATIC::rfread($f, $n + 4);
 343  	 	 	 }
 344  	 	 	 $n = TCPDF_STATIC::_freadint($f);
 345  	 	 } while ($n);
 346  	 	 if (($colspace == 'Indexed') AND (empty($pal))) {
 347  	 	 	 // Missing palette
 348  	 	 	 fclose($f);
 349  	 	 	 return false;
 350  	 	 }
 351  	 	 fclose($f);
 352  	 	 return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
 353  	 }
 354  
 355  } // END OF TCPDF_IMAGES CLASS
 356  
 357  //============================================================+
 358  // END OF FILE
 359  //============================================================+