alecpl
2012-03-19 a71a97fa49fb1c7fbe5e042b2cf6239f7372acb4
- Image resize with GD extension (#1488383) 


1 files added
3 files modified
236 ■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/include/rcmail.php 60 ●●●●● patch | view | raw | blame | history
program/include/rcube_image.php 165 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/upload_photo.inc 10 ●●●● patch | view | raw | blame | history
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)
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
   *
program/include/rcube_image.php
New file
@@ -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;
    }
}
program/steps/addressbook/upload_photo.inc
@@ -31,7 +31,8 @@
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']
@@ -41,9 +42,7 @@
        $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)) {
        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'];