From a71a97fa49fb1c7fbe5e042b2cf6239f7372acb4 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Mon, 19 Mar 2012 06:44:57 -0400
Subject: [PATCH] - Image resize with GD extension (#1488383) 

---
 CHANGELOG                                  |    1 
 program/include/rcube_image.php            |  165 +++++++++++++++++++++++++++++++++
 program/include/rcmail.php                 |   60 ------------
 program/steps/addressbook/upload_photo.inc |   18 +-
 4 files changed, 175 insertions(+), 69 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index ae8bee8..5902a3b 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 05cfefa..6320e5e 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -1537,66 +1537,6 @@
 
 
   /**
-   * 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 0000000..9fe15fe
--- /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 039a7b2..195bac5 100644
--- a/program/steps/addressbook/upload_photo.inc
+++ b/program/steps/addressbook/upload_photo.inc
@@ -31,20 +31,19 @@
 
 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 @@
             'group' => 'contact',
         ));
     }
-    else
+    else {
         $attachment['error'] = rcube_label('invalidimageformat');
+    }
 
     if ($attachment['status'] && !$attachment['abort']) {
         $file_id = $attachment['id'];

--
Gitblit v1.9.1