Imagick seems slow, can i make it faster?
Posted: 2015-02-11T09:03:34-07:00
I'm using ImageMagick 6.6.5-9 2010-11-15 Q16
with PHP module 3.1.2 (php_imagick-3.1.2-5.3-nts-vc9-x86.zip)
running on Windows 8.1 / Intel i7 with 32GB RAM
I have replaced GD-library with Imagick in my PHP project because i've needed some functions
like change perspective on an image, which works great btw.
But...Imagick seems so much slower in some regards, generating 2 different image copies (100x100 and 800x800) from
12 PNG-images with an average size of 1200x800 now takes 7-10 secs instead of near instantaneously with GD-library.
Is this normal?
Reviews i've read claims that Imagick is the faster and more optimized choice...but 'ive also read the opposite.
Don't know what to belief anymore.
Anyway, ive read that using the Q8 version speeds things up, can i use that version when working with 24-bit PNG-images?
Or is the colourspace limited to 8-bit
Anyway, here is my PHP Image class containing all (hints to get things more optimized is very much appreciated)
with PHP module 3.1.2 (php_imagick-3.1.2-5.3-nts-vc9-x86.zip)
running on Windows 8.1 / Intel i7 with 32GB RAM
I have replaced GD-library with Imagick in my PHP project because i've needed some functions
like change perspective on an image, which works great btw.
But...Imagick seems so much slower in some regards, generating 2 different image copies (100x100 and 800x800) from
12 PNG-images with an average size of 1200x800 now takes 7-10 secs instead of near instantaneously with GD-library.
Is this normal?
Reviews i've read claims that Imagick is the faster and more optimized choice...but 'ive also read the opposite.
Don't know what to belief anymore.
Anyway, ive read that using the Q8 version speeds things up, can i use that version when working with 24-bit PNG-images?
Or is the colourspace limited to 8-bit
Anyway, here is my PHP Image class containing all (hints to get things more optimized is very much appreciated)
Code: Select all
<?php
class Image {
private $file;
private $image;
private $info;
public function __construct($file) {
if (extension_loaded('imagick')) {
if (file_exists($file)) {
$this->file = $file;
$image = new Imagick();
$image->readImage($file);
$info = $image->identifyImage(true);
$this->info = array(
'width' => $info['geometry']['width'],
'height' => $info['geometry']['height'],
'filesize' => $info['fileSize'],
'compression' => $info['compression'],
'signature' => $info['signature'],
'colorspace' => $info['colorSpace'],
'units' => $info['units'],
'type' => $info['type'],
'mime' => $info['mimetype']
);
if ($this->info['mime'] == 'image/png') {
$image->setFormat('png24');
}
$this->image = $image;
} else {
exit('Error: Could not load image ' . $file . '!');
}
} else {
exit('Error: The Imagick component is not installed on your server!');
}
}
private function create($file = false) {
if ($file) {
return new Imagick($file);
} else {
return new Imagick();
}
}
public function perspective($offset = array(), $background = 'transparent') {
if (count($offset) > 7) {
$points = array(0,0,
(float)$offset['transform_topleft_x'], (float)$offset['transform_topleft_y'],
0, $this->image->getImageHeight(),
(float)$offset['transform_bottomleft_x'], (float)$offset['transform_bottomleft_y'],
$this->image->getImageWidth(), 0,
(float)$offset['transform_topright_x'], (float)$offset['transform_topright_y'],
$this->image->getImageWidth(), $this->image->getImageHeight(),
(float)$offset['transform_bottomright_x'], (float)$offset['transform_bottomright_y']
);
$this->image->setImageMatte(true);
$this->image->setImageMatteColor($background);
$this->image->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
$this->image->distortImage(Imagick::DISTORTION_PERSPECTIVE, $points, true);
}
}
public function save($file, $quality = 90) {
$info = pathinfo($file);
$extension = strtolower($info['extension']);
if (is_object($this->image)) {
if ($extension == 'jpeg' || $extension == 'jpg') {
$this->image->setImageFormat('jpg');
$this->image->setImageCompression(imagick::COMPRESSION_JPEG2000);
$this->image->setImageCompressionQuality($quality);
$this->image->stripImage();
} elseif ($extension == 'png') {
$this->image->setImageFormat('png');
$this->image->setImageCompression(0);
} elseif ($extension == 'gif') {
$this->image->setImageFormat('gif');
}
$this->image->writeImage($file);
}
}
public function output() {
return $this->image;
}
public function base64output($quality = 90) {
if ($this->info['mime']) {
$response = new Response();
$response->addHeader('Content-Type: ' . $this->info['mime']);
$response->addHeader('Content-transfer-encoding: base64');
$response->addHeader('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
$response->addHeader('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
$response->addHeader('Cache-Control: post-check=0, pre-check=0');
$response->addHeader('Pragma: no-cache');
if ($this->info['mime'] == 'image/jpeg') {
$this->image->setImageFormat('jpg');
$this->image->setImageCompression(imagick::COMPRESSION_JPEG2000);
$this->image->setImageCompressionQuality($quality);
$this->image->stripImage();
} elseif ($this->info['mime'] == 'image/png') {
$this->image->setImageFormat('png');
$this->image->setImageCompression(0);
} elseif ($this->info['mime'] == 'image/gif') {
$this->image->setImageFormat('gif');
}
ob_start();
echo $this->image;
return base64_encode(ob_get_clean());
}
}
public function resize($width = 0, $height = 0, $default = '', $method = 'THUMB', $filter = Imagick::FILTER_CATROM) {
if (!$this->info['width'] || !$this->info['height']) {
return;
}
$xpos = 0;
$ypos = 0;
$scale = 1;
$scale_w = $width / $this->info['width'];
$scale_h = $height / $this->info['height'];
if ($default == 'w') {
$scale = $scale_w;
} elseif ($default == 'h') {
$scale = $scale_h;
} else {
$scale = min($scale_w, $scale_h);
}
if ($scale == 1 && $scale_h == $scale_w && $this->info['mime'] != 'image/png') {
return;
}
$new_width = (int)($this->info['width'] * $scale);
$new_height = (int)($this->info['height'] * $scale);
$xpos = (int)(($width - $new_width) / 2);
$ypos = (int)(($height - $new_height) / 2);
$image = $this->image;
if ($method == 'SCALE') {
$image->scaleImage($new_width, $new_height);
} elseif ($method == 'THUMB') {
$image->thumbnailImage($new_width, $new_height, false);
} elseif ($method == 'RESIZE') {
$image->resizeImage($new_width, $new_height, $filter, 1);
}
if ($this->info['mime'] == 'image/png') {
$background = 'none';
} else {
$background = 'white';
}
$canvas = $this->create();
$canvas->newImage($width, $height, new ImagickPixel($background));
$canvas->compositeImage($image, imagick::COMPOSITE_OVER, $xpos, $ypos);
$this->info['width'] = $width;
$this->info['height'] = $height;
$this->image = $canvas;
$image->clear();
$image->destroy();
}
public function scale($width = 0, $height = 0, $method = 'THUMB', $filter = Imagick::FILTER_CATROM) {
if ($method == 'SCALE') {
$this->image->scaleImage($width, $height);
} elseif ($method == 'THUMB') {
$this->image->thumbnailImage($width, $height, false);
} elseif ($method == 'RESIZE') {
$this->image->resizeImage($width, $height, $filter, 1);
}
$this->info['width'] = $this->image->getImageWidth();
$this->info['height'] = $this->image->getImageHeight();
}
public function watermark($file, $position = 'bottomright', $x = 0, $y = 0) {
$watermark = $this->create($file);
$watermark_width = $watermark->getImageWidth();
$watermark_height = $watermark->getImageHeight();
switch($position) {
case 'topleft':
$watermark_pos_x = 0;
$watermark_pos_y = 0;
break;
case 'topright':
$watermark_pos_x = $this->info['width'] - $watermark_width;
$watermark_pos_y = 0;
break;
case 'bottomleft':
$watermark_pos_x = 0;
$watermark_pos_y = $this->info['height'] - $watermark_height;
break;
case 'bottomright':
$watermark_pos_x = $this->info['width'] - $watermark_width;
$watermark_pos_y = $this->info['height'] - $watermark_height;
break;
case 'custom':
$watermark_pos_x = $x;
$watermark_pos_y = $y;
break;
}
$image = $this->image;
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $watermark_pos_x, $watermark_pos_y);
$this->image = $image;
}
public function opacity($opacity) {
if ($opacity < 1) {
$this->image->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity, Imagick::CHANNEL_ALPHA);
}
}
public function crop($top_x, $top_y, $bottom_x, $bottom_y) {
$this->image->cropImage($bottom_x, $bottom_y, $top_x, $top_y);
$this->info['width'] = $this->image->getImageWidth();
$this->info['height'] = $this->image->getImageHeight();
}
public function rotate($degree, $color = '#00000000') {
$this->image->rotateImage(new ImagickPixel($color), $degree);
$this->info['width'] = $this->image->getImageWidth();
$this->info['height'] = $this->image->getImageHeight();
}
public function composite($watermark, $x = 0, $y = 0) {
$this->image->compositeImage($watermark, imagick::COMPOSITE_OVER, $x, $y);
$this->info['width'] = $this->image->getImageWidth();
$this->info['height'] = $this->image->getImageHeight();
}
private function merge($file, $x = 0, $y = 0, $opacity = 1) {
$merge = $this->create($file);
if ($opacity < 1) {
$merge->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity, Imagick::CHANNEL_ALPHA);
}
$this->image->compositeImage($merge, imagick::COMPOSITE_OVER, $x, $y);
}
public function __destruct() {
$this->image->clear();
$this->image->destroy();
}
}