summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2012-03-19 10:44:57 +0000
committeralecpl <alec@alec.pl>2012-03-19 10:44:57 +0000
commita71a97fa49fb1c7fbe5e042b2cf6239f7372acb4 (patch)
tree1a4ebc634607aae7da0858d490f0da4fd2c1cfda
parentd1e3430bfa1338268315e7425d0fbab995f5e107 (diff)
- Image resize with GD extension (#1488383)
-rw-r--r--CHANGELOG1
-rw-r--r--program/include/rcmail.php60
-rw-r--r--program/include/rcube_image.php165
-rw-r--r--program/steps/addressbook/upload_photo.inc18
4 files changed, 175 insertions, 69 deletions
diff --git a/CHANGELOG b/CHANGELOG
index ae8bee852..5902a3ba7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Image resize with GD extension (#1488383)
- Fix lack of warning when switching task in compose window (#1488399)
- Fix bug where it wasn't possible to enter ( or & characters in autocomplete fields
- Request all needed fields from address book backends (#1488394)
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 05cfefa06..6320e5e3f 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -1537,66 +1537,6 @@ class rcmail
/**
- * Use imagemagick or GD lib to read image properties
- *
- * @param string Absolute file path
- * @return mixed Hash array with image props like type, width, height or False on error
- */
- public static function imageprops($filepath)
- {
- $rcmail = rcmail::get_instance();
- if ($cmd = $rcmail->config->get('im_identify_path', false)) {
- list(, $type, $size) = explode(' ', strtolower(rcmail::exec($cmd. ' 2>/dev/null {in}', array('in' => $filepath))));
- if ($size)
- list($width, $height) = explode('x', $size);
- }
- else if (function_exists('getimagesize')) {
- $imsize = @getimagesize($filepath);
- $width = $imsize[0];
- $height = $imsize[1];
- $type = preg_replace('!image/!', '', $imsize['mime']);
- }
-
- return $type ? array('type' => $type, 'width' => $width, 'height' => $height) : false;
- }
-
-
- /**
- * Convert an image to a given size and type using imagemagick (ensures input is an image)
- *
- * @param $p['in'] Input filename (mandatory)
- * @param $p['out'] Output filename (mandatory)
- * @param $p['size'] Width x height of resulting image, e.g. "160x60"
- * @param $p['type'] Output file type, e.g. "jpg"
- * @param $p['-opts'] Custom command line options to ImageMagick convert
- * @return Success of convert as true/false
- */
- public static function imageconvert($p)
- {
- $result = false;
- $rcmail = rcmail::get_instance();
- $convert = $rcmail->config->get('im_convert_path', false);
- $identify = $rcmail->config->get('im_identify_path', false);
-
- // imagemagick is required for this
- if (!$convert)
- return false;
-
- if (!(($imagetype = @exif_imagetype($p['in'])) && ($type = image_type_to_extension($imagetype, false))))
- list(, $type) = explode(' ', strtolower(rcmail::exec($identify . ' 2>/dev/null {in}', $p))); # for things like eps
-
- $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps"));
- $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75);
- $p['-opts'] = array('-resize' => $p['size'].'>') + (array)$p['-opts'];
-
- if (in_array($type, explode(',', $p['types']))) # Valid type?
- $result = rcmail::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p) === "";
-
- return $result;
- }
-
-
- /**
* Construct shell command, execute it and return output as string.
* Keywords {keyword} are replaced with arguments
*
diff --git a/program/include/rcube_image.php b/program/include/rcube_image.php
new file mode 100644
index 000000000..9fe15fe54
--- /dev/null
+++ b/program/include/rcube_image.php
@@ -0,0 +1,165 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcube_image.php |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2005-2012, The Roundcube Dev Team |
+ | Copyright (C) 2011-2012, Kolab Systems AG |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Image resizer |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+
+ $Id$
+
+*/
+
+class rcube_image
+{
+ private $image_file;
+
+ function __construct($filename)
+ {
+ $this->image_file = $filename;
+ }
+
+ /**
+ * Get image properties.
+ *
+ * @return mixed Hash array with image props like type, width, height
+ */
+ public function props()
+ {
+ $rcmail = rcmail::get_instance();
+
+ if (function_exists('getimagesize') && ($imsize = @getimagesize($this->image_file))) {
+ $width = $imsize[0];
+ $height = $imsize[1];
+ $gd_type = $imsize['2'];
+ $type = image_type_to_extension($imsize['2'], false);
+ }
+
+ if (!$type && ($cmd = $rcmail->config->get('im_identify_path', false))) {
+ $id = rcmail::exec($cmd. ' 2>/dev/null {in}', array('in' => $this->image_file));
+ list(, $type, $size) = explode(' ', strtolower($id));
+ if ($size) {
+ list($width, $height) = explode('x', $size);
+ }
+ }
+
+ if ($type) {
+ return array(
+ 'type' => $type,
+ 'gd_type' => $gd_type,
+ 'width' => $width,
+ 'height' => $height,
+ );
+ }
+ }
+
+
+ /**
+ * Resize image to a given size
+ *
+ * @param int $size Max width/height size
+ * @param string $filename Output filename
+ *
+ * @return Success of convert as true/false
+ */
+ public function resize($size, $filename = null)
+ {
+ $result = false;
+ $rcmail = rcmail::get_instance();
+ $convert = $rcmail->config->get('im_convert_path', false);
+ $identify = $rcmail->config->get('im_identify_path', false);
+ $props = $this->props();
+
+ if (!$filename) {
+ $filename = $this->image_file;
+ }
+
+ // use Imagemagick
+ if ($convert) {
+ $p['out'] = $filename;
+ $p['in'] = $this->image_file;
+ $p['size'] = $size.'x'.$size;
+ $p['type'] = $type = $props['type'];
+
+ if (!$type) {
+ list(, $p['type']) = explode(' ', strtolower(rcmail::exec($identify . ' 2>/dev/null {in}', $p))); // for things like eps
+ }
+
+ $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps"));
+ $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75);
+ $p['-opts'] = array('-resize' => $size.'>');
+
+ if (in_array($type, explode(',', $p['types']))) { // Valid type?
+ $result = rcmail::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p) === '';
+ }
+
+ if ($result) {
+ return true;
+ }
+ }
+
+ // use GD extension
+ $gd_types = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
+ if ($props['gd_type'] && in_array($props['gd_type'], $gd_types)) {
+ if ($props['gd_type'] == IMAGETYPE_JPEG) {
+ $image = imagecreatefromjpeg($this->image_file);
+ }
+ elseif($props['gd_type'] == IMAGETYPE_GIF) {
+ $image = imagecreatefromgif($this->image_file);
+ }
+ elseif($props['gd_type'] == IMAGETYPE_PNG) {
+ $image = imagecreatefrompng($this->image_file);
+ }
+
+ $scale = $size / max($props['width'], $props['height']);
+ $width = $props['width'] * $scale;
+ $height = $props['height'] * $scale;
+
+ $new_image = imagecreatetruecolor($width, $height);
+
+ // Fix transparency of gif/png image
+ if ($props['gd_type'] != IMAGETYPE_JPEG) {
+ imagealphablending($new_image, false);
+ imagesavealpha($new_image, true);
+ $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
+ imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
+ }
+
+ imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $props['width'], $props['height']);
+ $image = $new_image;
+
+ if ($props['gd_type'] == IMAGETYPE_JPEG) {
+ $result = imagejpeg($image, $filename, 75);
+ }
+ elseif($props['gd_type'] == IMAGETYPE_GIF) {
+ $result = imagegif($image, $filename);
+ }
+ elseif($props['gd_type'] == IMAGETYPE_PNG) {
+ $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS);
+ }
+
+ if ($result) {
+ return true;
+ }
+ }
+
+
+ // @TODO: print error to the log?
+ return false;
+ }
+
+}
diff --git a/program/steps/addressbook/upload_photo.inc b/program/steps/addressbook/upload_photo.inc
index 039a7b202..195bac563 100644
--- a/program/steps/addressbook/upload_photo.inc
+++ b/program/steps/addressbook/upload_photo.inc
@@ -31,20 +31,19 @@ $OUTPUT->reset();
if ($filepath = $_FILES['_photo']['tmp_name']) {
// check file type and resize image
- $imageprop = rcmail::imageprops($_FILES['_photo']['tmp_name']);
+ $image = new rcube_image($_FILES['_photo']['tmp_name']);
+ $imageprop = $image->props();
if (in_array(strtolower($imageprop['type']), $IMAGE_TYPES)
- && $imageprop['width'] && $imageprop['height']
+ && $imageprop['width'] && $imageprop['height']
) {
- $maxsize = intval($RCMAIL->config->get('contact_photo_size', 160));
- $tmpfname = tempnam($RCMAIL->config->get('temp_dir'), 'rcmImgConvert');
+ $maxsize = intval($RCMAIL->config->get('contact_photo_size', 160));
+ $tmpfname = tempnam($RCMAIL->config->get('temp_dir'), 'rcmImgConvert');
$save_hook = 'attachment_upload';
// scale image to a maximum size
- if (($imageprop['width'] > $maxsize || $imageprop['height'] > $maxsize) &&
- (rcmail::imageconvert(array('in' => $filepath, 'out' => $tmpfname,
- 'size' => $maxsize.'x'.$maxsize, 'type' => $imageprop['type'])) !== false)) {
- $filepath = $tmpfname;
+ if (($imageprop['width'] > $maxsize || $imageprop['height'] > $maxsize) && $image->resize($maxsize, $tmpfname)) {
+ $filepath = $tmpfname;
$save_hook = 'attachment_save';
}
@@ -57,8 +56,9 @@ if ($filepath = $_FILES['_photo']['tmp_name']) {
'group' => 'contact',
));
}
- else
+ else {
$attachment['error'] = rcube_label('invalidimageformat');
+ }
if ($attachment['status'] && !$attachment['abort']) {
$file_id = $attachment['id'];