source: github/program/include/rcube_image.php @ 19cc5b9

HEADdev-browser-capabilitiespdo
Last change on this file since 19cc5b9 was 19cc5b9, checked in by Aleksander Machniak <alec@…>, 12 months ago

Display Tiff as Jpeg in browsers without Tiff support (#1488452)

  • Property mode set to 100644
File size: 8.5 KB
Line 
1<?php
2
3/*
4 +-----------------------------------------------------------------------+
5 | program/include/rcube_image.php                                       |
6 |                                                                       |
7 | This file is part of the Roundcube Webmail client                     |
8 | Copyright (C) 2005-2012, The Roundcube Dev Team                       |
9 | Copyright (C) 2011-2012, Kolab Systems AG                             |
10 |                                                                       |
11 | Licensed under the GNU General Public License version 3 or            |
12 | any later version with exceptions for skins & plugins.                |
13 | See the README file for a full license statement.                     |
14 |                                                                       |
15 | PURPOSE:                                                              |
16 |   Image resizer and converter                                         |
17 |                                                                       |
18 +-----------------------------------------------------------------------+
19 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
20 | Author: Aleksander Machniak <alec@alec.pl>                            |
21 +-----------------------------------------------------------------------+
22*/
23
24class rcube_image
25{
26    private $image_file;
27
28    const TYPE_GIF = 1;
29    const TYPE_JPG = 2;
30    const TYPE_PNG = 3;
31    const TYPE_TIF = 4;
32
33    public static $extensions = array(
34        self::TYPE_GIF => 'gif',
35        self::TYPE_JPG => 'jpg',
36        self::TYPE_PNG => 'png',
37        self::TYPE_TIF => 'tif',
38    );
39
40
41    function __construct($filename)
42    {
43        $this->image_file = $filename;
44    }
45
46    /**
47     * Get image properties.
48     *
49     * @return mixed Hash array with image props like type, width, height
50     */
51    public function props()
52    {
53        // use GD extension
54        if (function_exists('getimagesize') && ($imsize = @getimagesize($this->image_file))) {
55            $width   = $imsize[0];
56            $height  = $imsize[1];
57            $gd_type = $imsize['2'];
58            $type    = image_type_to_extension($imsize['2'], false);
59        }
60
61        // use ImageMagick
62        if (!$type && ($data = $this->identify())) {
63            list($type, $width, $height) = $data;
64        }
65
66        if ($type) {
67            return array(
68                'type'    => $type,
69                'gd_type' => $gd_type,
70                'width'   => $width,
71                'height'  => $height,
72            );
73        }
74    }
75
76    /**
77     * Resize image to a given size
78     *
79     * @param int    $size      Max width/height size
80     * @param string $filename  Output filename
81     *
82     * @return bool True on success, False on failure
83     */
84    public function resize($size, $filename = null)
85    {
86        $result  = false;
87        $rcube   = rcube::get_instance();
88        $convert = $rcube->config->get('im_convert_path', false);
89        $props   = $this->props();
90
91        if (!$filename) {
92            $filename = $this->image_file;
93        }
94
95        // use Imagemagick
96        if ($convert) {
97            $p['out']  = $filename;
98            $p['in']   = $this->image_file;
99            $p['size'] = $size.'x'.$size;
100            $type      = $props['type'];
101
102            if (!$type && ($data = $this->identify())) {
103                $type = $data[0];
104            }
105
106            $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps"));
107            $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75);
108            $p['-opts'] = array('-resize' => $size.'>');
109
110            if (in_array($type, explode(',', $p['types']))) { // Valid type?
111                $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p);
112            }
113
114            if ($result === '') {
115                return true;
116            }
117        }
118
119        // use GD extension
120        $gd_types = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
121        if ($props['gd_type'] && in_array($props['gd_type'], $gd_types)) {
122            if ($props['gd_type'] == IMAGETYPE_JPEG) {
123                $image = imagecreatefromjpeg($this->image_file);
124            }
125            elseif($props['gd_type'] == IMAGETYPE_GIF) {
126                $image = imagecreatefromgif($this->image_file);
127            }
128            elseif($props['gd_type'] == IMAGETYPE_PNG) {
129                $image = imagecreatefrompng($this->image_file);
130            }
131
132            $scale  = $size / max($props['width'], $props['height']);
133            $width  = $props['width']  * $scale;
134            $height = $props['height'] * $scale;
135
136            $new_image = imagecreatetruecolor($width, $height);
137
138            // Fix transparency of gif/png image
139            if ($props['gd_type'] != IMAGETYPE_JPEG) {
140                imagealphablending($new_image, false);
141                imagesavealpha($new_image, true);
142                $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
143                imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
144            }
145
146            imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $props['width'], $props['height']);
147            $image = $new_image;
148
149            if ($props['gd_type'] == IMAGETYPE_JPEG) {
150                $result = imagejpeg($image, $filename, 75);
151            }
152            elseif($props['gd_type'] == IMAGETYPE_GIF) {
153                $result = imagegif($image, $filename);
154            }
155            elseif($props['gd_type'] == IMAGETYPE_PNG) {
156                $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS);
157            }
158
159            if ($result) {
160                return true;
161            }
162        }
163
164        // @TODO: print error to the log?
165        return false;
166    }
167
168    /**
169     * Convert image to a given type
170     *
171     * @param int    $type      Destination file type (see class constants)
172     * @param string $filename  Output filename (if empty, original file will be used
173     *                          and filename extension will be modified)
174     *
175     * @return bool True on success, False on failure
176     */
177    public function convert($type, $filename = null)
178    {
179        $rcube   = rcube::get_instance();
180        $convert = $rcube->config->get('im_convert_path', false);
181
182        if (!$filename) {
183            $filename = $this->image_file;
184
185            // modify extension
186            if ($extension = self::$extensions[$type]) {
187                $filename = preg_replace('/\.[^.]+$/', '', $filename) . '.' . $extension;
188            }
189        }
190
191        // use ImageMagick
192        if ($convert) {
193            $p['in']   = $this->image_file;
194            $p['out']  = $filename;
195            $p['type'] = self::$extensions[$type];
196
197            $result = rcube::exec($convert . ' 2>&1 -colorspace RGB -quality 75 {in} {type}:{out}', $p);
198
199            if ($result === '') {
200                return true;
201            }
202        }
203
204        // use GD extension (TIFF isn't supported)
205        $props    = $this->props();
206        $gd_types = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
207
208        if ($props['gd_type'] && in_array($props['gd_type'], $gd_types)) {
209            if ($props['gd_type'] == IMAGETYPE_JPEG) {
210                $image = imagecreatefromjpeg($this->image_file);
211            }
212            else if ($props['gd_type'] == IMAGETYPE_GIF) {
213                $image = imagecreatefromgif($this->image_file);
214            }
215            else if ($props['gd_type'] == IMAGETYPE_PNG) {
216                $image = imagecreatefrompng($this->image_file);
217            }
218
219            if ($type == self::TYPE_JPG) {
220                $result = imagejpeg($image, $filename, 75);
221            }
222            else if ($type == self::TYPE_GIF) {
223                $result = imagegif($image, $filename);
224            }
225            else if ($type == self::TYPE_PNG) {
226                $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS);
227            }
228        }
229
230        // @TODO: print error to the log?
231        return false;
232    }
233
234    /**
235     * Identify command handler.
236     */
237    private function identify()
238    {
239        $rcube = rcube::get_instance();
240
241        if ($cmd = $rcube->config->get('im_identify_path')) {
242            $args = array('in' => $this->image_file, 'format' => "%m %[fx:w] %[fx:h]");
243            $id   = rcube::exec($cmd. ' 2>/dev/null -format {format} {in}', $args);
244
245            if ($id) {
246                return explode(' ', strtolower($id));
247            }
248        }
249    }
250
251}
Note: See TracBrowser for help on using the repository browser.