From 8968f9543fb52b1196a4627ab1ccf777f50c7be9 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 6 May 2014 16:18:36 +0200 Subject: Support image operations with Imagick extension (#1489734) --- CHANGELOG | 1 + program/lib/Roundcube/rcube_image.php | 120 +++++++++++++++++++++++++++------- program/steps/mail/func.inc | 4 +- program/steps/mail/get.inc | 2 +- program/steps/mail/show.inc | 2 +- 5 files changed, 99 insertions(+), 30 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6c7734916..b265b1053 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Support image operations with Imagick extension (#1489734) - Support upload progress with session.upload_progress and PECL uploadprogress module (#1488702) - Make identity name field optional (#1489510) - Utility script to remove user records from the local database diff --git a/program/lib/Roundcube/rcube_image.php b/program/lib/Roundcube/rcube_image.php index 4e4caae93..a15368a7e 100644 --- a/program/lib/Roundcube/rcube_image.php +++ b/program/lib/Roundcube/rcube_image.php @@ -102,10 +102,10 @@ class rcube_image } // use Imagemagick - if ($convert) { - $p['out'] = $filename; - $p['in'] = $this->image_file; - $type = $props['type']; + if ($convert || class_exists('Imagick', false)) { + $p['out'] = $filename; + $p['in'] = $this->image_file; + $type = $props['type']; if (!$type && ($data = $this->identify())) { $type = $data[0]; @@ -129,26 +129,49 @@ class rcube_image $result = ($this->image_file == $filename || copy($this->image_file, $filename)) ? '' : false; } else { - if ($scale >= 1) { - $width = $props['width']; - $height = $props['height']; - } - else { - $width = intval($props['width'] * $scale); - $height = intval($props['height'] * $scale); - } - $valid_types = "bmp,eps,gif,jp2,jpg,png,svg,tif"; - $p += array( - 'type' => $type, - 'quality' => 75, - 'size' => $width . 'x' . $height, - ); - if (in_array($type, explode(',', $valid_types))) { // Valid type? - $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace sRGB -strip' - . ' -quality {quality} -resize {size} {intype}:{in} {type}:{out}', $p); + if ($scale >= 1) { + $width = $props['width']; + $height = $props['height']; + } + else { + $width = intval($props['width'] * $scale); + $height = intval($props['height'] * $scale); + } + + // use ImageMagick in command line + if ($convert) { + $p += array( + 'type' => $type, + 'quality' => 75, + 'size' => $width . 'x' . $height, + ); + + $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace sRGB -strip' + . ' -quality {quality} -resize {size} {intype}:{in} {type}:{out}', $p); + } + // use PHP's Imagick class + else { + try { + $image = new Imagick($this->image_file); + $image = $image->flattenImages(); + + $image->setImageColorspace(Imagick::COLORSPACE_SRGB); + $image->setImageCompressionQuality(75); + $image->setImageFormat($type); + $image->stripImage(); + $image->scaleImage($width, $height); + + if ($image->writeImage($filename)) { + $result = ''; + } + } + catch (Exception $e) { + rcube::raise_error($e, true, false); + } + } } } @@ -249,7 +272,7 @@ class rcube_image } } - // use ImageMagick + // use ImageMagick in command line if ($convert) { $p['in'] = $this->image_file; $p['out'] = $filename; @@ -258,11 +281,31 @@ class rcube_image $result = rcube::exec($convert . ' 2>&1 -colorspace sRGB -strip -quality 75 {in} {type}:{out}', $p); if ($result === '') { - @chmod($filename, 0600); + chmod($filename, 0600); return true; } } + // use PHP's Imagick class + if (class_exists('Imagick', false)) { + try { + $image = new Imagick($this->image_file); + + $image->setImageColorspace(Imagick::COLORSPACE_SRGB); + $image->setImageCompressionQuality(75); + $image->setImageFormat(self::$extensions[$type]); + $image->stripImage(); + + if ($image->writeImage($filename)) { + @chmod($filename, 0600); + return true; + } + } + catch (Exception $e) { + rcube::raise_error($e, true, false); + } + } + // use GD extension (TIFF isn't supported) $props = $this->props(); @@ -302,12 +345,26 @@ class rcube_image } /** - * Identify command handler. + * Checks if image format conversion is supported + * + * @return boolean True if specified format can be converted to another format + */ + public static function is_convertable($mimetype = null) + { + $rcube = rcube::get_instance(); + + // @TODO: check if specified mimetype is really supported + return class_exists('Imagick', false) || $rcube->config->get('im_convert_path'); + } + + /** + * ImageMagick based image properties read. */ private function identify() { $rcube = rcube::get_instance(); + // use ImageMagick in command line if ($cmd = $rcube->config->get('im_identify_path')) { $args = array('in' => $this->image_file, 'format' => "%m %[fx:w] %[fx:h]"); $id = rcube::exec($cmd. ' 2>/dev/null -format {format} {in}', $args); @@ -316,6 +373,19 @@ class rcube_image return explode(' ', strtolower($id)); } } - } + // use PHP's Imagick class + if (class_exists('Imagick', false)) { + try { + $image = new Imagick($this->image_file); + + return array( + strtolower($image->getImageFormat()), + $image->getImageWidth(), + $image->getImageHeight(), + ); + } + catch (Exception $e) {} + } + } } diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index b9971ce0c..7270cf95a 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -1343,12 +1343,10 @@ function rcmail_message_body($attrib) function rcmail_part_image_type($part) { - $rcmail = rcmail::get_instance(); - // Skip TIFF images if browser doesn't support this format... $tiff_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps']['tif']); // until we can convert them to JPEG - $tiff_support = $tiff_support || $rcmail->config->get('im_convert_path'); + $tiff_support = $tiff_support || rcube_image::is_convertable('image/tiff'); // Content-type regexp $mime_regex = $tiff_support ? '/^image\//i' : '/^image\/(?!tif)/i'; diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index c6262097f..02d57c7dc 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -221,7 +221,7 @@ else if (strlen($part_id)) { // TIFF to JPEG conversion, if needed $tiff_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps']['tif']); if (!empty($_REQUEST['_embed']) && !$tiff_support - && $RCMAIL->config->get('im_convert_path') + && rcube_image::is_convertable('image/tiff') && rcmail_part_image_type($part) == 'image/tiff' ) { $tiff2jpeg = true; diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index 9498d1dc5..beb2cc6e9 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -102,7 +102,7 @@ if ($uid) { } if (empty($_SESSION['browser_caps']['tif']) && ($key = array_search('image/tiff', $mimetypes)) !== false) { // we can convert tiff to jpeg - if (!$RCMAIL->config->get('im_convert_path')) { + if (!rcube_image::is_convertable('image/tiff')) { unset($mimetypes[$key]); } } -- cgit v1.2.3