3 # if someone uploads an image, which is larger than the allowed
4 # image size (EWIKI_IMAGE_MAXSIZE), then this plugin tries to
5 # rescale that image until it fits; it utilizes the PHP libgd
6 # functions to accomplish this
8 # NOTE: It is currently disabled for Win32, because nobody knows, if
9 # this will crash the PHP interpreter on those systems.
11 # Changed on 6/8/04 by Alfred Sterphone, III
12 # Types supported: gif, png, jpeg
13 # All that are resized are converted to jpeg in the end
14 # WBMP stands for wireless bitmap and not windows bitmap
15 # Bitmap support for only 25KB files is folly anyway
17 # Revamped again, later the same day (6/8/04) by me again
18 # Implemented a binary search for the correct pixel width
19 # Next step is to put PHPUnit around and test all cases
21 # Refactoring and bullet-proofing completed (6/15/04) by me again
25 - Handled formats: jpeg, gif, png
26 - Images wider than 90% of our page width will be resized proportionally to 90% of page width at upload
27 - Images uploaded as images will be restricted to 25 kilobytes
28 - Images larger than this will:
29 -# Be scaled according to our page width
30 -# Be converted to JPEG
31 -# Be re-compressed as JPEG with compression settings that suits us
32 -# Rescaled via binary search for suitable size down to 20% of page width
33 -# Rejected as too large
34 - Image format may be changed in scaling
35 - Images uploaded as attachments will not be scaled in this manner
40 define("EWIKI_IMGRESIZE_WIN", 0);
41 define("EWIKI_IMAGE_MAX_PIXELS", 11000000); //11 megapixels
42 define("EWIKI_IMAGE_MAXSIZE", 65536);
43 define("EWIKI_IMAGE_TOLERANCE", 60000); //don't settle for smaller than this during resize
44 define("EWIKI_WORK_AREA", 640); //width of whitespace or work area within ewiki
45 define("EWIKI_IMAGE_MAX_X", (int)(.9*EWIKI_WORK_AREA)); //90% max
46 define("EWIKI_IMAGE_MIN_X", (int)(.2*EWIKI_WORK_AREA)); //20% min
47 define("EWIKI_IMAGE_MAX_Y",1000); //max y value if picture is "candy cane"
48 define("EWIKI_IMAGE_RATIO", 10); //maximum acceptable y:x ratio
50 if (!strstr(PHP_VERSION, "-dev") && !(extension_loaded("php_gd2.dll") or extension_loaded("gd.so")) && !function_exists("imagecreate") && function_exists("dl"))
51 { #-- try to load gd lib
52 @dl("php_gd2.dll") or @dl("gd.so");
55 if (function_exists("imagecreate"))
57 $ewiki_plugins["image_resize"][] = "ewiki_binary_resize_image_gd";
60 function ewiki_binary_resize_image_gd(&$filename, &$mime, $return=0)
62 return resizeImage($filename, $mime, $return);
65 function getTypeFromMIME($mime)
73 function getXY($orig_image,&$orig_x,&$orig_y)
75 $orig_x = imagesx($orig_image);
76 $orig_y = imagesy($orig_image);
79 function isResizeNeeded($a_width, $a_fileName)
83 if ($a_width > EWIKI_IMAGE_MAX_X)
88 if (filesize($a_fileName) > EWIKI_IMAGE_MAXSIZE)
96 function isImageTolerable($a_fileName)
100 if (filesize($a_fileName) > EWIKI_IMAGE_MAXSIZE)
105 if (filesize($a_fileName) < EWIKI_IMAGE_TOLERANCE)
113 function getImageStream($filename,$type)
117 if ((($type != "gif") && ($type !="jpeg") && ($type !="png") && ($type != "vnd.wap.wbmp")))
122 if (!function_exists($pf = "imagecreatefrom$type"))
127 $retval = $pf($filename);
132 function getInitialResize($orig_image,&$new_x,&$new_y)
134 getXY($orig_image,$orig_x,$orig_y);
136 if ($orig_x <= EWIKI_IMAGE_MAX_X)
137 //keep original dimesions
143 //wider than max width, so resize
145 $new_x=EWIKI_IMAGE_MAX_X;
146 $new_y=(int)((EWIKI_IMAGE_MAX_X*$orig_y)/$orig_x);
150 function doResize($orig_image,$new_x,$new_y,&$type)
152 $tc = function_exists("imageistruecolor") && imageistruecolor($orig_image);
153 if (!$tc || ($type == "gif"))
155 $new_image = imagecreate($new_x, $new_y);
156 $white = imagecolorallocate($new_image,255,255,255);
157 imagefill($new_image, 0, 0, $white);
158 imagepalettecopy($new_image, $orig_image);
162 $new_image = imagecreatetruecolor($new_x, $new_y);
163 $white = imagecolorallocate($new_image,255,255,255);
164 imagefill($new_image, 0, 0, $white);
167 getXY($orig_image,$orig_x,$orig_y);
170 imagecopyresampled($new_image, $orig_image, 0,0, 0,0, $new_x,$new_y, $orig_x,$orig_y);
177 function doSave(&$image,$filename,$type)
179 if (function_exists($pf = "image$type"))
181 $pf($image,$filename,70);
185 return(false); # cannot save in orig format
189 function isCandyCane($filename)
193 list($width, $height, $type, $attr) = getimagesize($filename);
194 $ratio = ($height/$width);
195 $fs = filesize($filename);
197 if (($ratio > EWIKI_IMAGE_RATIO) && ($fs > EWIKI_IMAGE_MAXSIZE) && ($height > EWIKI_IMAGE_MAX_Y))
199 ewiki_log("$filename is a candy cane",3);
205 function isMemoryFriendly($filename)
207 list($width, $height, $type, $attr) = getimagesize($filename);
208 $pixels = (int)($height*$width);
210 if ($pixels > EWIKI_IMAGE_MAX_PIXELS)
212 ewiki_log("$filename at $pixels pixels is too big!",3);
219 function resizeImage(&$filename, &$mime, $return=0)
222 $time_start = getmicrotime();
224 /*** this disallows Win32 ***/
225 if ((DIRECTORY_SEPARATOR!="/") && !EWIKI_IMAGERESIZE_WIN || (strpos($mime, "image/")!==0))
230 if (!isMemoryFriendly($filename))
235 if (isCandyCane($filename))
240 $rescaled_filename = $filename;
242 $type = getTypeFromMIME($mime);
244 $orig_image = getImageStream($rescaled_filename,$type);
245 if (!isset($orig_image))
250 getXY($orig_image,$orig_x,$orig_y);
252 if (!isResizeNeeded($orig_x, $filename))
255 getInitialResize($orig_image,$new_x,$new_y);
257 $orig_image = doResize($orig_image,$new_x,$new_y,$type);
259 $rescaled_filename = tempnam(EWIKI_TMP, "ewiki.img_resize_gd.tmp.");
260 doSave($orig_image,$rescaled_filename,$type);
262 if (isResizeNeeded($new_x, $rescaled_filename))
263 //will only take cases that need to be resized
265 ewiki_log("Resize beyond initial resize is needed. Carrying through.",3);
267 //set starting points for binary search
268 $x_max=EWIKI_IMAGE_MAX_X-1;
269 $x_min=EWIKI_IMAGE_MIN_X;
271 //set failsafe break to max number of iterations through the loop
272 $failsafe = (int)(log($orig_x)+1);
274 while (($x_min <= $x_max) && !isImageTolerable($rescaled_filename))
275 //the resize while loop
277 ewiki_log("While loop initiated",3);
279 //somehow made it to an infinite loop, so get out
280 if($failsafe < 0) return(false);
282 //take a guess at the correct width
283 $x_guess=(int)(($x_max+$x_min)/2);
285 if ($filename == $rescaled_filename)
287 $rescaled_filename = tempnam(EWIKI_TMP, "ewiki.img_resize_gd.tmp.");
291 $new_x = (int)($x_guess);
292 $new_y = (int)(($x_guess*$orig_y)/$orig_x);
294 $new_image = doResize($orig_image,$new_x,$new_y,$type);
296 doSave($new_image,$rescaled_filename,$type);
299 imagedestroy($new_image);
304 $ftmp = filesize($rescaled_filename);
305 ewiki_log("xguess: $x_guess, xmin: $x_min, xmax: $x_max, filesize: $ftmp",3);
307 if (filesize($rescaled_filename) < EWIKI_IMAGE_TOLERANCE)
311 else if (filesize($rescaled_filename) > EWIKI_IMAGE_MAXSIZE)
317 ewiki_log("While loop ended",3);
322 imagedestroy($orig_image);
325 #-- security check filesizes, abort
326 if (!filesize($filename) || !filesize($rescaled_filename) || (filesize($rescaled_filename) > EWIKI_IMAGE_MAXSIZE))
328 unlink($rescaled_filename);
332 #-- set $mime, as it may have changed (.gif)
333 $mime = strtok($mime, "/") . "/" . $type;
334 if (!strstr($filename, ".$type"))
337 $filename .= ".$type";
340 #-- move tmp file to old name
341 copy($rescaled_filename, $filename);
342 unlink($rescaled_filename);
345 $time_end = getmicrotime();
346 $time = $time_end - $time_start;
347 ewiki_log("$time seconds to perform resizing", 3);