Skip to content

Commit

Permalink
Add resource limits for Imagick to manage memory and disk usage
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelzotikov committed Jan 10, 2025
1 parent 829e6a0 commit 9c64bcc
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/SocialMediaImageGenerator/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ class Generator

private $layers_counter = 0;

/**
* @throws \ImagickException
*/
public function __construct(int $width, int $height, string $color)
{
$this->image = new \Imagick();
ImagickResourceLimiter::applyLimits($this->image);

$this->image->setResolution(300, 300);
$this->image->newImage($width, $height, $color);

Expand Down Expand Up @@ -59,6 +64,9 @@ public function loadLayers(array $array): self
return $this;
}

/**
* @throws \ImagickException
*/
public function addLayer(AbstractType $layer): self
{
if ($layer->getName()) {
Expand Down
18 changes: 18 additions & 0 deletions src/SocialMediaImageGenerator/ImagickResourceLimiter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace SocialMediaImageGenerator;

class ImagickResourceLimiter
{
/**
* @throws \ImagickException
*/
public static function applyLimits(\Imagick $im): void
{
$im->setResourceLimit(\Imagick::RESOURCETYPE_MEMORY, 256);
$im->setResourceLimit(\Imagick::RESOURCETYPE_MAP, 256);
$im->setResourceLimit(\Imagick::RESOURCETYPE_AREA, 1512);
$im->setResourceLimit(\Imagick::RESOURCETYPE_FILE, 768);
$im->setResourceLimit(\Imagick::RESOURCETYPE_DISK, -1);
}
}
27 changes: 27 additions & 0 deletions src/SocialMediaImageGenerator/Magnetic.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ class Magnetic
/** @var AbstractType */
private $to_layer;

/**
* @throws \ImagickException
*/
public function __construct(array &$layers, array &$layers_with_names)
{
$this->im = new \Imagick();
ImagickResourceLimiter::applyLimits($this->im);

$this->layers = &$layers;
$this->layers_with_names = &$layers_with_names;
Expand Down Expand Up @@ -73,6 +77,7 @@ private function horizontalCenter(AbstractType &$layer)
} else {

/*$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);
$layer_info = $im->queryFontMetrics($layer->$this->getImage(), $layer->getText());*/

$layer->setX(
Expand All @@ -89,6 +94,7 @@ private function horizontalCenter(AbstractType &$layer)
if ($layer->getImage() instanceof \Imagick) {

/*$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);
$to_layer_info = $im->queryFontMetrics($this->to_layer->getImage(), $this->to_layer->getText());*/

$layer->setX(
Expand Down Expand Up @@ -122,6 +128,7 @@ private function left(AbstractType &$layer)
/*if ($layer_image instanceof \ImagickDraw) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);
$layer_info = $im->queryFontMetrics($layer_image, $layer->getText());
if ($layer->getAlignment() === \Imagick::ALIGN_CENTER) {
Expand All @@ -145,6 +152,7 @@ private function right(AbstractType &$layer)
/*if ($layer_image instanceof \ImagickDraw) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);
$layer_info = $im->queryFontMetrics($layer_image, $layer->getText());
if ($layer->getAlignment() === \Imagick::ALIGN_CENTER) {
Expand Down Expand Up @@ -183,6 +191,9 @@ private function right(AbstractType &$layer)
unset($layer);
}

/**
* @throws \ImagickException
*/
private function verticalCenter(AbstractType &$layer)
{
if ($this->to_layer->getImage()instanceof \Imagick) {
Expand All @@ -193,6 +204,8 @@ private function verticalCenter(AbstractType &$layer)
));
} else {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$layer_info = $im->queryFontMetrics($layer->getImage(), $layer->getText());

$layer->setY((int) (
Expand All @@ -205,6 +218,8 @@ private function verticalCenter(AbstractType &$layer)
} elseif ($this->to_layer->getImage() instanceof \ImagickDraw) {
if ($layer->getImage() instanceof \Imagick) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$to_layer_info = $im->queryFontMetrics($this->to_layer->getImage(), $this->to_layer->getText());

$layer->setY((int) (
Expand All @@ -215,6 +230,8 @@ private function verticalCenter(AbstractType &$layer)
));
} else {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$layer_info = $im->queryFontMetrics($layer->getImage(), $layer->getText());
$to_layer_info = $im->queryFontMetrics($this->to_layer->getImage(), $this->to_layer->getText());

Expand All @@ -240,6 +257,8 @@ private function top(AbstractType &$layer)
));
} elseif ($layer->getImage() instanceof \ImagickDraw) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$layer_info = $im->queryFontMetrics($layer->getImage(), $layer->getText());

$layer->setY((int) (
Expand All @@ -249,6 +268,8 @@ private function top(AbstractType &$layer)
} elseif ($this->to_layer->getImage() instanceof \ImagickDraw) {
if ($layer->getImage() instanceof \Imagick) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$to_layer_info = $im->queryFontMetrics($this->to_layer->getImage(), $this->to_layer->getText());

$layer->setY((int) (
Expand All @@ -275,6 +296,8 @@ private function bottom(AbstractType &$layer)
));
} elseif ($layer->getImage() instanceof \ImagickDraw) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$layer_info = $im->queryFontMetrics($layer->getImage(), $layer->getText());

$layer->setY((int) (
Expand All @@ -287,6 +310,8 @@ private function bottom(AbstractType &$layer)
} elseif ($this->to_layer->getImage() instanceof \ImagickDraw) {
if ($layer->getImage() instanceof \Imagick) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$to_layer_info = $im->queryFontMetrics($this->to_layer->getImage(), $this->to_layer->getText());

$layer->setY((int) (
Expand All @@ -297,6 +322,8 @@ private function bottom(AbstractType &$layer)
));
} elseif ($layer->getImage() instanceof \ImagickDraw) {
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$to_layer_info = $im->queryFontMetrics($this->to_layer->getImage(), $this->to_layer->getText());

$layer->setY((int) (
Expand Down
7 changes: 7 additions & 0 deletions src/SocialMediaImageGenerator/Types/Background.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@
declare(strict_types=1);
namespace SocialMediaImageGenerator\Types;

use SocialMediaImageGenerator\ImagickResourceLimiter;

class Background extends AbstractType
{
protected $color = '#FFFFFF';
protected $layer;

/**
* @throws \ImagickException
*/
public function getImage(): \Imagick
{
if ($this->layer) {
return $this->layer;
}

$layer = new \Imagick();
ImagickResourceLimiter::applyLimits($layer);

$layer->newImage($this->getWidth(), $this->getHeight(), $this->getColor());

$this->layer = $layer;
Expand Down
5 changes: 5 additions & 0 deletions src/SocialMediaImageGenerator/Types/BackgroundImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
declare(strict_types=1);
namespace SocialMediaImageGenerator\Types;

use SocialMediaImageGenerator\ImagickResourceLimiter;
use SocialMediaImageGenerator\Properties\Blackout;

class BackgroundImage extends Background
Expand All @@ -16,6 +17,8 @@ public function getImage(): \Imagick
}

$layer = new \Imagick();
ImagickResourceLimiter::applyLimits($layer);

$layer->readImage($this->getPath());

$layer->setImageInterpolateMethod(\Imagick::INTERPOLATE_BICUBIC);
Expand All @@ -40,6 +43,8 @@ public function getImage(): \Imagick

if ($this->getBlackout()) {
$blackout_draw = new \Imagick();
ImagickResourceLimiter::applyLimits($blackout_draw);

$blackout_draw->newImage($width, $height, new \ImagickPixel($this->getBlackout()->getColor()));

if (method_exists($blackout_draw, 'setImageAlpha')) {
Expand Down
11 changes: 11 additions & 0 deletions src/SocialMediaImageGenerator/Types/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
declare(strict_types=1);
namespace SocialMediaImageGenerator\Types;

use SocialMediaImageGenerator\ImagickResourceLimiter;
use SocialMediaImageGenerator\Properties\Transform;

class Image extends AbstractType
Expand All @@ -14,13 +15,19 @@ class Image extends AbstractType

protected $round_corners = 0;

/**
* @throws \ImagickDrawException
* @throws \ImagickException
*/
public function getImage(bool $no_resize = false): \Imagick
{
if ($this->layer) {
return $this->layer;
}

$layer = new \Imagick();
ImagickResourceLimiter::applyLimits($layer);

$layer->readImage($this->getPath());
$layer->setImageResolution(300, 300);
$layer->resampleImage(300, 300, \Imagick::FILTER_LANCZOS, 0);
Expand All @@ -31,6 +38,8 @@ public function getImage(bool $no_resize = false): \Imagick

if ($this->getRoundCorners()) {
$mask = new \Imagick();
ImagickResourceLimiter::applyLimits($mask);

$mask->newImage($this->getWidth(), $this->getHeight(), new \ImagickPixel('transparent'));

$shape = new \ImagickDraw();
Expand All @@ -47,6 +56,8 @@ public function getImage(bool $no_resize = false): \Imagick

if ($this->getFill()) {
$layer_colorize = new \Imagick();
ImagickResourceLimiter::applyLimits($layer_colorize);

$layer_colorize->newImage($layer->getImageWidth(), $layer->getImageHeight(), $this->getFill());
$layer_colorize->compositeImage($layer, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);

Expand Down
4 changes: 4 additions & 0 deletions src/SocialMediaImageGenerator/Types/ImageGravityCenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
declare(strict_types=1);
namespace SocialMediaImageGenerator\Types;

use SocialMediaImageGenerator\ImagickResourceLimiter;

class ImageGravityCenter extends Image
{
public function getImage(bool $no_resize = true): \Imagick
Expand All @@ -17,6 +19,8 @@ public function getImage(bool $no_resize = true): \Imagick

if ($this->fill) {
$layer_colorize = new \Imagick();
ImagickResourceLimiter::applyLimits($layer_colorize);

$layer_colorize->newImage($layer->getImageWidth(), $layer->getImageHeight(), $this->fill);
$layer_colorize->compositeImage($layer, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$layer = $layer_colorize;
Expand Down
9 changes: 9 additions & 0 deletions src/SocialMediaImageGenerator/Types/Text.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
declare(strict_types=1);
namespace SocialMediaImageGenerator\Types;

use SocialMediaImageGenerator\ImagickResourceLimiter;
use SocialMediaImageGenerator\Properties\Font as FontProperties;
use SocialMediaImageGenerator\Properties\Underline as UnderlineProperties;

Expand Down Expand Up @@ -78,9 +79,13 @@ private function sliceTextByLines(string $text, int $lines, string $symbol = '..
return implode("\n", $slice_text_arr) . $symbol;
}

/**
* @throws \ImagickException
*/
private function getMetricsForEachOfLine(string $text, \ImagickDraw $draw): array
{
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$info = [];
foreach (explode("\n", $text) as $string) {
Expand All @@ -91,9 +96,13 @@ private function getMetricsForEachOfLine(string $text, \ImagickDraw $draw): arra
return $info;
}

/**
* @throws \ImagickException
*/
private function wordwrap(string $text, int $width, \ImagickDraw $draw, int &$number_of_lines = 1): string
{
$im = new \Imagick();
ImagickResourceLimiter::applyLimits($im);

$final_text = "";
$words = explode(' ', $text);
Expand Down

0 comments on commit 9c64bcc

Please sign in to comment.