See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 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 /** @phpstan-ignore-next-line */ 168 $read = fread($file, 10); 169 // @phpstan-ignore-next-line 170 while (!feof($file) && ($read != '')) { 171 // @phpstan-ignore-next-line 172 $read .= fread($file, 1024); 173 } 174 175 /** @phpstan-ignore-next-line */ 176 $temp = unpack('H*', $read); 177 $hex = $temp[1]; 178 $header = substr($hex, 0, 108); 179 180 // Process the header 181 // Structure: http://www.fastgraph.com/help/bmp_header_format.html 182 $width = 0; 183 $height = 0; 184 if (substr($header, 0, 4) == '424d') { 185 // Cut it in parts of 2 bytes 186 $header_parts = str_split($header, 2); 187 188 // Get the width 4 bytes 189 $width = hexdec($header_parts[19] . $header_parts[18]); 190 191 // Get the height 4 bytes 192 $height = hexdec($header_parts[23] . $header_parts[22]); 193 194 // Unset the header params 195 unset($header_parts); 196 } 197 198 // Define starting X and Y 199 $x = 0; 200 $y = 1; 201 202 // Create newimage 203 204 /** @phpstan-ignore-next-line */ 205 $image = imagecreatetruecolor($width, $height); 206 207 // Grab the body from the image 208 $body = substr($hex, 108); 209 210 // Calculate if padding at the end-line is needed 211 // Divided by two to keep overview. 212 // 1 byte = 2 HEX-chars 213 $body_size = (strlen($body) / 2); 214 $header_size = ($width * $height); 215 216 // Use end-line padding? Only when needed 217 $usePadding = ($body_size > ($header_size * 3) + 4); 218 219 // Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption 220 // Calculate the next DWORD-position in the body 221 for ($i = 0; $i < $body_size; $i += 3) { 222 // Calculate line-ending and padding 223 if ($x >= $width) { 224 // If padding needed, ignore image-padding 225 // Shift i to the ending of the current 32-bit-block 226 if ($usePadding) { 227 $i += $width % 4; 228 } 229 230 // Reset horizontal position 231 $x = 0; 232 233 // Raise the height-position (bottom-up) 234 ++$y; 235 236 // Reached the image-height? Break the for-loop 237 if ($y > $height) { 238 break; 239 } 240 } 241 242 // Calculation of the RGB-pixel (defined as BGR in image-data) 243 // Define $i_pos as absolute position in the body 244 $i_pos = $i * 2; 245 $r = hexdec($body[$i_pos + 4] . $body[$i_pos + 5]); 246 $g = hexdec($body[$i_pos + 2] . $body[$i_pos + 3]); 247 $b = hexdec($body[$i_pos] . $body[$i_pos + 1]); 248 249 // Calculate and draw the pixel 250 251 /** @phpstan-ignore-next-line */ 252 $color = imagecolorallocate($image, $r, $g, $b); 253 // @phpstan-ignore-next-line 254 imagesetpixel($image, $x, $height - $y, $color); 255 256 // Raise the horizontal position 257 ++$x; 258 } 259 260 // Unset the body / free the memory 261 unset($body); 262 263 // Return image-object 264 // @phpstan-ignore-next-line 265 return $image; 266 } 267 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body