3 * Laconica, the distributed open-source microblogging tool
5 * Abstraction for an image file
9 * LICENCE: This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * @author Evan Prodromou <evan@controlyourself.ca>
25 * @author Zach Copley <zach@controlyourself.ca>
26 * @copyright 2008-2009 Control Yourself, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
28 * @link http://laconi.ca/
31 if (!defined('LACONICA')) {
36 * A wrapper on uploaded files
38 * Makes it slightly easier to accept an image file from upload.
42 * @author Evan Prodromou <evan@controlyourself.ca>
43 * @author Zach Copley <zach@controlyourself.ca>
44 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
45 * @link http://laconi.ca/
57 function __construct($id=null, $filepath=null, $type=null, $width=null, $height=null)
60 $this->filepath = $filepath;
62 $info = @getimagesize($this->filepath);
63 $this->type = ($info) ? $info[2]:$type;
64 $this->width = ($info) ? $info[0]:$width;
65 $this->height = ($info) ? $info[1]:$height;
68 static function fromUpload($param='upload')
70 switch ($_FILES[$param]['error']) {
71 case UPLOAD_ERR_OK: // success, jump out
73 case UPLOAD_ERR_INI_SIZE:
74 case UPLOAD_ERR_FORM_SIZE:
75 throw new Exception(sprintf(_('That file is too big. The maximum file size is %d.'), $this->maxFileSize()));
77 case UPLOAD_ERR_PARTIAL:
78 @unlink($_FILES[$param]['tmp_name']);
79 throw new Exception(_('Partial upload.'));
82 throw new Exception(_('System error uploading file.'));
86 $info = @getimagesize($_FILES[$param]['tmp_name']);
89 @unlink($_FILES[$param]['tmp_name']);
90 throw new Exception(_('Not an image or corrupt file.'));
94 if ($info[2] !== IMAGETYPE_GIF &&
95 $info[2] !== IMAGETYPE_JPEG &&
96 $info[2] !== IMAGETYPE_PNG) {
98 @unlink($_FILES[$param]['tmp_name']);
99 throw new Exception(_('Unsupported image file format.'));
103 return new ImageFile(null, $_FILES[$param]['tmp_name']);
106 function resize($size, $x = 0, $y = 0, $w = null, $h = null)
108 $w = ($w === null) ? $this->width:$w;
109 $h = ($h === null) ? $this->height:$h;
111 if (!file_exists($this->filepath)) {
112 throw new Exception(_('Lost our file.'));
116 // Don't crop/scale if it isn't necessary
117 if ($size === $this->width
118 && $size === $this->height
121 && $w === $this->width
122 && $h === $this->height) {
124 $outname = Avatar::filename($this->id,
125 image_type_to_extension($this->type),
128 $outpath = Avatar::path($outname);
129 @copy($this->filepath, $outpath);
133 switch ($this->type) {
135 $image_src = imagecreatefromgif($this->filepath);
138 $image_src = imagecreatefromjpeg($this->filepath);
141 $image_src = imagecreatefrompng($this->filepath);
144 throw new Exception(_('Unknown file type'));
148 $image_dest = imagecreatetruecolor($size, $size);
150 if ($this->type == IMAGETYPE_GIF || $this->type == IMAGETYPE_PNG) {
152 $transparent_idx = imagecolortransparent($image_src);
154 if ($transparent_idx >= 0) {
156 $transparent_color = imagecolorsforindex($image_src, $transparent_idx);
157 $transparent_idx = imagecolorallocate($image_dest, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
158 imagefill($image_dest, 0, 0, $transparent_idx);
159 imagecolortransparent($image_dest, $transparent_idx);
161 } elseif ($this->type == IMAGETYPE_PNG) {
163 imagealphablending($image_dest, false);
164 $transparent = imagecolorallocatealpha($image_dest, 0, 0, 0, 127);
165 imagefill($image_dest, 0, 0, $transparent);
166 imagesavealpha($image_dest, true);
171 imagecopyresampled($image_dest, $image_src, 0, 0, $x, $y, $size, $size, $w, $h);
173 $outname = Avatar::filename($this->id,
174 image_type_to_extension($this->type),
178 $outpath = Avatar::path($outname);
180 switch ($this->type) {
182 imagegif($image_dest, $outpath);
185 imagejpeg($image_dest, $outpath, 100);
188 imagepng($image_dest, $outpath);
191 throw new Exception(_('Unknown file type'));
195 imagedestroy($image_src);
196 imagedestroy($image_dest);
203 @unlink($this->filename);
206 static function maxFileSize()
208 $value = ImageFile::maxFileSizeInt();
210 if ($value > 1024 * 1024) {
211 return ($value/(1024*1024)).'Mb';
212 } else if ($value > 1024) {
213 return ($value/(1024)).'kB';
219 static function maxFileSizeInt()
221 return min(ImageFile::strToInt(ini_get('post_max_size')),
222 ImageFile::strToInt(ini_get('upload_max_filesize')),
223 ImageFile::strToInt(ini_get('memory_limit')));
226 static function strToInt($str)
228 $unit = substr($str, -1);
229 $num = substr($str, 0, -1);
231 switch(strtoupper($unit)){