Skip to content

Commit f70a53b

Browse files
committed
Implement check for memory limit before loading image
1 parent d4aa571 commit f70a53b

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

lib/IMagickLuminanceSource.php

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ final class IMagickLuminanceSource extends LuminanceSource
1212
private $dataWidth;
1313
private $dataHeight;
1414
/**
15-
* @var mixed|int
16-
*/
15+
* @var mixed|int
16+
*/
1717
private $left;
1818
/**
19-
* @var mixed|int
20-
*/
19+
* @var mixed|int
20+
*/
2121
private $top;
2222
private ?\Imagick $image = null;
2323

@@ -66,13 +66,40 @@ public function _IMagickLuminanceSource(\Imagick $image, $width, $height): void
6666
$this->top = 0;
6767
$this->image = $image;
6868

69+
/**
70+
* Converts shorthand memory notation value to bytes
71+
* From http://php.net/manual/en/function.ini-get.php
72+
*
73+
* @param int $val Memory size shorthand notation string
74+
*/
75+
function kmgStringToBytes(string $val)
76+
{
77+
$val = trim($val);
78+
$last = strtolower($val[strlen($val) - 1]);
79+
$val = substr($val, 0, -1);
80+
switch ($last) {
81+
// The 'G' modifier is available since PHP 5.1.0
82+
case 'g':
83+
$val *= 1024;
84+
// no break
85+
case 'm':
86+
$val *= 1024;
87+
// no break
88+
case 'k':
89+
$val *= 1024;
90+
}
91+
return $val;
92+
}
6993

7094
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
7195
// up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
7296
$this->luminances = [];
7397

7498
$image->setImageColorspace(\Imagick::COLORSPACE_GRAY);
75-
// $image->newPseudoImage(0, 0, "magick:rose");
99+
// Check that we actually have enough space to do it
100+
if ($width * $height * 16 * 3 > kmgStringToBytes(ini_get('memory_limit'))) {
101+
throw new \RuntimeException("PHP Memory Limit does not allow pixel export.");
102+
}
76103
$pixels = $image->exportImagePixels(1, 1, $width, $height, "RGB", \Imagick::PIXEL_CHAR);
77104

78105
$array = [];
@@ -85,16 +112,15 @@ public function _IMagickLuminanceSource(\Imagick $image, $width, $height): void
85112
$b = $pixels[$i + 2] & 0xff;
86113
if ($r == $g && $g == $b) {
87114
// Image is already greyscale, so pick any channel.
88-
89-
$this->luminances[] = $r;//(($r + 128) % 256) - 128;
115+
$this->luminances[] = $r; //(($r + 128) % 256) - 128;
90116
} else {
91117
// Calculate luminance cheaply, favoring green.
92-
$this->luminances[] = ($r + 2 * $g + $b) / 4;//(((($r + 2 * $g + $b) / 4) + 128) % 256) - 128;
118+
$this->luminances[] = ($r + 2 * $g + $b) / 4; //(((($r + 2 * $g + $b) / 4) + 128) % 256) - 128;
93119
}
94120
}
95121
}
96122

97-
123+
98124
public function getRow($y, $row = null)
99125
{
100126
if ($y < 0 || $y >= $this->getHeight()) {
@@ -110,7 +136,7 @@ public function getRow($y, $row = null)
110136
return $row;
111137
}
112138

113-
139+
114140
public function getMatrix()
115141
{
116142
$width = $this->getWidth();
@@ -144,13 +170,13 @@ public function getMatrix()
144170
return $matrix;
145171
}
146172

147-
173+
148174
public function isCropSupported(): bool
149175
{
150176
return true;
151177
}
152178

153-
179+
154180
public function crop($left, $top, $width, $height): LuminanceSource
155181
{
156182
return $this->luminances->cropImage($width, $height, $left, $top);

0 commit comments

Comments
 (0)