- Image resize with GD extension (#1488383)
1 files added
3 files modified
| | |
| | | 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) |
| | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | * |
New file |
| | |
| | | <?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; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | 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'] |
| | |
| | | $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'; |
| | | } |
| | |
| | | 'group' => 'contact', |
| | | )); |
| | | } |
| | | else |
| | | else { |
| | | $attachment['error'] = rcube_label('invalidimageformat'); |
| | | } |
| | | |
| | | if ($attachment['status'] && !$attachment['abort']) { |
| | | $file_id = $attachment['id']; |