Avoid memory leak by releasing image resources
This also better support image cloning with a proper clone of the GD resource. #2092
This commit is contained in:
parent
50683e6068
commit
5dd00b1b1a
|
|
@ -5920,16 +5920,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/Iterator.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagesx expects resource, GdImage\\|resource given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/MemoryDrawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagesy expects resource, GdImage\\|resource given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/MemoryDrawing.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\PageSetup\\:\\:\\$pageOrder has no typehint specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ parameters:
|
|||
- '~^Return typehint of method .* has invalid type GdImage\.$~'
|
||||
- '~^Property .* has unknown class GdImage as its type\.$~'
|
||||
- '~^Parameter .* of method .* has invalid typehint type GdImage\.$~'
|
||||
- '~^Parameter \#1 \$im of function (imagedestroy|imageistruecolor|imagealphablending|imagesavealpha|imagecolortransparent|imagecolorsforindex|imagesavealpha|imagesx|imagesy) expects resource, GdImage\|resource given\.$~'
|
||||
- '~^Parameter \#2 \$src_im of function imagecopy expects resource, GdImage\|resource given\.$~'
|
||||
# Accept a bit anything for assert methods
|
||||
- '~^Parameter \#2 .* of static method PHPUnit\\Framework\\Assert\:\:assert\w+\(\) expects .*, .* given\.$~'
|
||||
- '~^Method PhpOffice\\PhpSpreadsheetTests\\.*\:\:test.*\(\) has parameter \$args with no typehint specified\.$~'
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use GdImage;
|
||||
use PhpOffice\PhpSpreadsheet\Exception;
|
||||
|
||||
class MemoryDrawing extends BaseDrawing
|
||||
{
|
||||
|
|
@ -21,7 +22,7 @@ class MemoryDrawing extends BaseDrawing
|
|||
/**
|
||||
* Image resource.
|
||||
*
|
||||
* @var GdImage|resource
|
||||
* @var null|GdImage|resource
|
||||
*/
|
||||
private $imageResource;
|
||||
|
||||
|
|
@ -60,10 +61,71 @@ class MemoryDrawing extends BaseDrawing
|
|||
parent::__construct();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->imageResource) {
|
||||
imagedestroy($this->imageResource);
|
||||
$this->imageResource = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
parent::__clone();
|
||||
$this->cloneResource();
|
||||
}
|
||||
|
||||
private function cloneResource(): void
|
||||
{
|
||||
if (!$this->imageResource) {
|
||||
return;
|
||||
}
|
||||
|
||||
$width = imagesx($this->imageResource);
|
||||
$height = imagesy($this->imageResource);
|
||||
|
||||
if (imageistruecolor($this->imageResource)) {
|
||||
$clone = imagecreatetruecolor($width, $height);
|
||||
if (!$clone) {
|
||||
throw new Exception('Could not clone image resource');
|
||||
}
|
||||
|
||||
imagealphablending($clone, false);
|
||||
imagesavealpha($clone, true);
|
||||
} else {
|
||||
$clone = imagecreate($width, $height);
|
||||
if (!$clone) {
|
||||
throw new Exception('Could not clone image resource');
|
||||
}
|
||||
|
||||
// If the image has transparency...
|
||||
$transparent = imagecolortransparent($this->imageResource);
|
||||
if ($transparent >= 0) {
|
||||
$rgb = imagecolorsforindex($this->imageResource, $transparent);
|
||||
if ($rgb === false) {
|
||||
throw new Exception('Could not get image colors');
|
||||
}
|
||||
|
||||
imagesavealpha($clone, true);
|
||||
$color = imagecolorallocatealpha($clone, $rgb['red'], $rgb['green'], $rgb['blue'], $rgb['alpha']);
|
||||
if ($color === false) {
|
||||
throw new Exception('Could not get image alpha color');
|
||||
}
|
||||
|
||||
imagefill($clone, 0, 0, $color);
|
||||
}
|
||||
}
|
||||
|
||||
//Create the Clone!!
|
||||
imagecopy($clone, $this->imageResource, 0, 0, 0, 0, $width, $height);
|
||||
|
||||
$this->imageResource = $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image resource.
|
||||
*
|
||||
* @return GdImage|resource
|
||||
* @return null|GdImage|resource
|
||||
*/
|
||||
public function getImageResource()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -690,18 +690,21 @@ class Html extends BaseWriter
|
|||
$drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' .
|
||||
$imageData . '" alt="' . $filedesc . '" />';
|
||||
} elseif ($drawing instanceof MemoryDrawing) {
|
||||
ob_start(); // Let's start output buffering.
|
||||
imagepng($drawing->getImageResource()); // This will normally output the image, but because of ob_start(), it won't.
|
||||
$contents = ob_get_contents(); // Instead, output above is saved to $contents
|
||||
ob_end_clean(); // End the output buffer.
|
||||
$imageResource = $drawing->getImageResource();
|
||||
if ($imageResource) {
|
||||
ob_start(); // Let's start output buffering.
|
||||
imagepng($imageResource); // This will normally output the image, but because of ob_start(), it won't.
|
||||
$contents = ob_get_contents(); // Instead, output above is saved to $contents
|
||||
ob_end_clean(); // End the output buffer.
|
||||
|
||||
$dataUri = 'data:image/jpeg;base64,' . base64_encode($contents);
|
||||
$dataUri = 'data:image/jpeg;base64,' . base64_encode($contents);
|
||||
|
||||
// Because of the nature of tables, width is more important than height.
|
||||
// max-width: 100% ensures that image doesnt overflow containing cell
|
||||
// width: X sets width of supplied image.
|
||||
// As a result, images bigger than cell will be contained and images smaller will not get stretched
|
||||
$html .= '<img alt="' . $filedesc . '" src="' . $dataUri . '" style="max-width:100%;width:' . $drawing->getWidth() . 'px;" />';
|
||||
// Because of the nature of tables, width is more important than height.
|
||||
// max-width: 100% ensures that image doesnt overflow containing cell
|
||||
// width: X sets width of supplied image.
|
||||
// As a result, images bigger than cell will be contained and images smaller will not get stretched
|
||||
$html .= '<img alt="' . $filedesc . '" src="' . $dataUri . '" style="max-width:100%;width:' . $drawing->getWidth() . 'px;" />';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue