Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

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

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Shared;
   4  
   5  use GdImage;
   6  use SimpleXMLElement;
   7  
   8  class Drawing
   9  {
  10      /**
  11       * Convert pixels to EMU.
  12       *
  13       * @param int $pixelValue Value in pixels
  14       *
  15       * @return int Value in EMU
  16       */
  17      public static function pixelsToEMU($pixelValue)
  18      {
  19          return $pixelValue * 9525;
  20      }
  21  
  22      /**
  23       * Convert EMU to pixels.
  24       *
  25       * @param int|SimpleXMLElement $emuValue Value in EMU
  26       *
  27       * @return int Value in pixels
  28       */
  29      public static function EMUToPixels($emuValue)
  30      {
  31          $emuValue = (int) $emuValue;
  32          if ($emuValue != 0) {
  33              return (int) round($emuValue / 9525);
  34          }
  35  
  36          return 0;
  37      }
  38  
  39      /**
  40       * Convert pixels to column width. Exact algorithm not known.
  41       * By inspection of a real Excel file using Calibri 11, one finds 1000px ~ 142.85546875
  42       * This gives a conversion factor of 7. Also, we assume that pixels and font size are proportional.
  43       *
  44       * @param int $pixelValue Value in pixels
  45       *
  46       * @return float|int Value in cell dimension
  47       */
  48      public static function pixelsToCellDimension($pixelValue, \PhpOffice\PhpSpreadsheet\Style\Font $defaultFont)
  49      {
  50          // Font name and size
  51          $name = $defaultFont->getName();
  52          $size = $defaultFont->getSize();
  53  
  54          if (isset(Font::$defaultColumnWidths[$name][$size])) {
  55              // Exact width can be determined
  56              return $pixelValue * Font::$defaultColumnWidths[$name][$size]['width']
  57                  / Font::$defaultColumnWidths[$name][$size]['px'];
  58          }
  59  
  60          // We don't have data for this particular font and size, use approximation by
  61          // extrapolating from Calibri 11
  62          return $pixelValue * 11 * Font::$defaultColumnWidths['Calibri'][11]['width']
  63              / Font::$defaultColumnWidths['Calibri'][11]['px'] / $size;
  64      }
  65  
  66      /**
  67       * Convert column width from (intrinsic) Excel units to pixels.
  68       *
  69       * @param float $cellWidth Value in cell dimension
  70       * @param \PhpOffice\PhpSpreadsheet\Style\Font $defaultFont Default font of the workbook
  71       *
  72       * @return int Value in pixels
  73       */
  74      public static function cellDimensionToPixels($cellWidth, \PhpOffice\PhpSpreadsheet\Style\Font $defaultFont)
  75      {
  76          // Font name and size
  77          $name = $defaultFont->getName();
  78          $size = $defaultFont->getSize();
  79  
  80          if (isset(Font::$defaultColumnWidths[$name][$size])) {
  81              // Exact width can be determined
  82              $colWidth = $cellWidth * Font::$defaultColumnWidths[$name][$size]['px']
  83                  / Font::$defaultColumnWidths[$name][$size]['width'];
  84          } else {
  85              // We don't have data for this particular font and size, use approximation by
  86              // extrapolating from Calibri 11
  87              $colWidth = $cellWidth * $size * Font::$defaultColumnWidths['Calibri'][11]['px']
  88                  / Font::$defaultColumnWidths['Calibri'][11]['width'] / 11;
  89          }
  90  
  91          // Round pixels to closest integer
  92          $colWidth = (int) round($colWidth);
  93  
  94          return $colWidth;
  95      }
  96  
  97      /**
  98       * Convert pixels to points.
  99       *
 100       * @param int $pixelValue Value in pixels
 101       *
 102       * @return float Value in points
 103       */
 104      public static function pixelsToPoints($pixelValue)
 105      {
 106          return $pixelValue * 0.75;
 107      }
 108  
 109      /**
 110       * Convert points to pixels.
 111       *
 112       * @param int $pointValue Value in points
 113       *
 114       * @return int Value in pixels
 115       */
 116      public static function pointsToPixels($pointValue)
 117      {
 118          if ($pointValue != 0) {
 119              return (int) ceil($pointValue / 0.75);
 120          }
 121  
 122          return 0;
 123      }
 124  
 125      /**
 126       * Convert degrees to angle.
 127       *
 128       * @param int $degrees Degrees
 129       *
 130       * @return int Angle
 131       */
 132      public static function degreesToAngle($degrees)
 133      {
 134          return (int) round($degrees * 60000);
 135      }
 136  
 137      /**
 138       * Convert angle to degrees.
 139       *
 140       * @param int|SimpleXMLElement $angle Angle
 141       *
 142       * @return int Degrees
 143       */
 144      public static function angleToDegrees($angle)
 145      {
 146          $angle = (int) $angle;
 147          if ($angle != 0) {
 148              return (int) round($angle / 60000);
 149          }
 150  
 151          return 0;
 152      }
 153  
 154      /**
 155       * Create a new image from file. By alexander at alexauto dot nl.
 156       *
 157       * @see http://www.php.net/manual/en/function.imagecreatefromwbmp.php#86214
 158       *
 159       * @param string $bmpFilename Path to Windows DIB (BMP) image
 160       *
 161       * @return GdImage|resource
 162       */
 163      public static function imagecreatefrombmp($bmpFilename)
 164      {
 165          //    Load the image into a string
 166          $file = fopen($bmpFilename, 'rb');
 167          $read = fread($file, 10);
 168          while (!feof($file) && ($read != '')) {
 169              $read .= fread($file, 1024);
 170          }
 171  
 172          $temp = unpack('H*', $read);
 173          $hex = $temp[1];
 174          $header = substr($hex, 0, 108);
 175  
 176          //    Process the header
 177          //    Structure: http://www.fastgraph.com/help/bmp_header_format.html
 178          $width = 0;
 179          $height = 0;
 180          if (substr($header, 0, 4) == '424d') {
 181              //    Cut it in parts of 2 bytes
 182              $header_parts = str_split($header, 2);
 183  
 184              //    Get the width        4 bytes
 185              $width = hexdec($header_parts[19] . $header_parts[18]);
 186  
 187              //    Get the height        4 bytes
 188              $height = hexdec($header_parts[23] . $header_parts[22]);
 189  
 190              //    Unset the header params
 191              unset($header_parts);
 192          }
 193  
 194          //    Define starting X and Y
 195          $x = 0;
 196          $y = 1;
 197  
 198          //    Create newimage
 199          $image = imagecreatetruecolor($width, $height);
 200  
 201          //    Grab the body from the image
 202          $body = substr($hex, 108);
 203  
 204          //    Calculate if padding at the end-line is needed
 205          //    Divided by two to keep overview.
 206          //    1 byte = 2 HEX-chars
 207          $body_size = (strlen($body) / 2);
 208          $header_size = ($width * $height);
 209  
 210          //    Use end-line padding? Only when needed
 211          $usePadding = ($body_size > ($header_size * 3) + 4);
 212  
 213          //    Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption
 214          //    Calculate the next DWORD-position in the body
 215          for ($i = 0; $i < $body_size; $i += 3) {
 216              //    Calculate line-ending and padding
 217              if ($x >= $width) {
 218                  // If padding needed, ignore image-padding
 219                  // Shift i to the ending of the current 32-bit-block
 220                  if ($usePadding) {
 221                      $i += $width % 4;
 222                  }
 223  
 224                  //    Reset horizontal position
 225                  $x = 0;
 226  
 227                  //    Raise the height-position (bottom-up)
 228                  ++$y;
 229  
 230                  //    Reached the image-height? Break the for-loop
 231                  if ($y > $height) {
 232                      break;
 233                  }
 234              }
 235  
 236              // Calculation of the RGB-pixel (defined as BGR in image-data)
 237              // Define $i_pos as absolute position in the body
 238              $i_pos = $i * 2;
 239              $r = hexdec($body[$i_pos + 4] . $body[$i_pos + 5]);
 240              $g = hexdec($body[$i_pos + 2] . $body[$i_pos + 3]);
 241              $b = hexdec($body[$i_pos] . $body[$i_pos + 1]);
 242  
 243              // Calculate and draw the pixel
 244              $color = imagecolorallocate($image, $r, $g, $b);
 245              imagesetpixel($image, $x, $height - $y, $color);
 246  
 247              // Raise the horizontal position
 248              ++$x;
 249          }
 250  
 251          // Unset the body / free the memory
 252          unset($body);
 253  
 254          //    Return image-object
 255          return $image;
 256      }
 257  }