1 | <?php |
||
2 | /** |
||
3 | * Resize and crop images on the fly, store generated images in a cache. |
||
4 | * |
||
5 | * @author Mikael Roos [email protected] |
||
6 | * @example http://dbwebb.se/opensource/cimage |
||
7 | * @link https://github.com/mosbth/cimage |
||
8 | * |
||
9 | */ |
||
10 | |||
11 | /** |
||
12 | * Custom exception handler. |
||
13 | */ |
||
14 | set_exception_handler(function ($exception) { |
||
15 | errorPage( |
||
16 | "<p><b>img.php: Uncaught exception:</b> <p>" |
||
17 | . $exception->getMessage() |
||
18 | . "</p><pre>" |
||
19 | . $exception->getTraceAsString() |
||
20 | . "</pre>", |
||
21 | 500 |
||
22 | ); |
||
23 | }); |
||
24 | |||
25 | |||
26 | |||
27 | /** |
||
28 | * Get configuration options from file, if the file exists, else use $config |
||
29 | * if its defined or create an empty $config. |
||
30 | */ |
||
31 | $configFile = __DIR__.'/'.basename(__FILE__, '.php').'_config.php'; |
||
32 | |||
33 | if (is_file($configFile)) { |
||
34 | $config = require $configFile; |
||
35 | } elseif (!isset($config)) { |
||
36 | $config = array(); |
||
37 | } |
||
38 | |||
39 | // Make CIMAGE_DEBUG false by default, if not already defined |
||
40 | if (!defined("CIMAGE_DEBUG")) { |
||
41 | define("CIMAGE_DEBUG", false); |
||
42 | } |
||
43 | |||
44 | |||
45 | |||
46 | /** |
||
47 | * Setup the autoloader, but not when using a bundle. |
||
48 | */ |
||
49 | if (!defined("CIMAGE_BUNDLE")) { |
||
50 | if (!isset($config["autoloader"])) { |
||
51 | die("CImage: Missing autoloader."); |
||
52 | } |
||
53 | |||
54 | require $config["autoloader"]; |
||
55 | } |
||
56 | |||
57 | |||
58 | |||
59 | /** |
||
60 | * verbose, v - do a verbose dump of what happens |
||
61 | * vf - do verbose dump to file |
||
62 | */ |
||
63 | $verbose = getDefined(array('verbose', 'v'), true, false); |
||
64 | $verboseFile = getDefined('vf', true, false); |
||
65 | verbose("img.php version = " . CIMAGE_VERSION); |
||
66 | |||
67 | |||
68 | |||
69 | /** |
||
70 | * status - do a verbose dump of the configuration |
||
71 | */ |
||
72 | $status = getDefined('status', true, false); |
||
73 | |||
74 | |||
75 | |||
76 | /** |
||
77 | * Set mode as strict, production or development. |
||
78 | * Default is production environment. |
||
79 | */ |
||
80 | $mode = getConfig('mode', 'production'); |
||
81 | |||
82 | // Settings for any mode |
||
83 | set_time_limit(20); |
||
84 | ini_set('gd.jpeg_ignore_warning', 1); |
||
85 | |||
86 | if (!extension_loaded('gd')) { |
||
87 | errorPage("Extension gd is not loaded.", 500); |
||
88 | } |
||
89 | |||
90 | // Specific settings for each mode |
||
91 | if ($mode == 'strict') { |
||
92 | |||
93 | error_reporting(0); |
||
94 | ini_set('display_errors', 0); |
||
95 | ini_set('log_errors', 1); |
||
96 | $verbose = false; |
||
97 | $status = false; |
||
98 | $verboseFile = false; |
||
99 | |||
100 | } elseif ($mode == 'production') { |
||
101 | |||
102 | error_reporting(-1); |
||
103 | ini_set('display_errors', 0); |
||
104 | ini_set('log_errors', 1); |
||
105 | $verbose = false; |
||
106 | $status = false; |
||
107 | $verboseFile = false; |
||
108 | |||
109 | } elseif ($mode == 'development') { |
||
110 | |||
111 | error_reporting(-1); |
||
112 | ini_set('display_errors', 1); |
||
113 | ini_set('log_errors', 0); |
||
114 | $verboseFile = false; |
||
115 | |||
116 | } elseif ($mode == 'test') { |
||
117 | |||
118 | error_reporting(-1); |
||
119 | ini_set('display_errors', 1); |
||
120 | ini_set('log_errors', 0); |
||
121 | |||
122 | } else { |
||
123 | errorPage("Unknown mode: $mode", 500); |
||
124 | } |
||
125 | |||
126 | verbose("mode = $mode"); |
||
127 | verbose("error log = " . ini_get('error_log')); |
||
128 | |||
129 | |||
130 | |||
131 | /** |
||
132 | * Set default timezone if not set or if its set in the config-file. |
||
133 | */ |
||
134 | $defaultTimezone = getConfig('default_timezone', null); |
||
135 | |||
136 | if ($defaultTimezone) { |
||
137 | date_default_timezone_set($defaultTimezone); |
||
138 | } elseif (!ini_get('default_timezone')) { |
||
139 | date_default_timezone_set('UTC'); |
||
140 | } |
||
141 | |||
142 | |||
143 | |||
144 | /** |
||
145 | * Check if passwords are configured, used and match. |
||
146 | * Options decide themself if they require passwords to be used. |
||
147 | */ |
||
148 | $pwdConfig = getConfig('password', false); |
||
149 | $pwdAlways = getConfig('password_always', false); |
||
150 | $pwdType = getConfig('password_type', 'text'); |
||
151 | $pwd = get(array('password', 'pwd'), null); |
||
152 | |||
153 | // Check if passwords match, if configured to use passwords |
||
154 | $passwordMatch = null; |
||
155 | if ($pwd) { |
||
156 | switch ($pwdType) { |
||
157 | case 'md5': |
||
158 | $passwordMatch = ($pwdConfig === md5($pwd)); |
||
159 | break; |
||
160 | case 'hash': |
||
161 | $passwordMatch = password_verify($pwd, $pwdConfig); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
162 | break; |
||
163 | case 'text': |
||
164 | $passwordMatch = ($pwdConfig === $pwd); |
||
165 | break; |
||
166 | default: |
||
167 | $passwordMatch = false; |
||
168 | } |
||
169 | } |
||
170 | |||
171 | if ($pwdAlways && $passwordMatch !== true) { |
||
172 | errorPage("Password required and does not match or exists.", 403); |
||
173 | } |
||
174 | |||
175 | verbose("password match = $passwordMatch"); |
||
176 | |||
177 | |||
178 | |||
179 | /** |
||
180 | * Prevent hotlinking, leeching, of images by controlling who access them |
||
181 | * from where. |
||
182 | * |
||
183 | */ |
||
184 | $allowHotlinking = getConfig('allow_hotlinking', true); |
||
185 | $hotlinkingWhitelist = getConfig('hotlinking_whitelist', array()); |
||
186 | |||
187 | $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : null; |
||
188 | $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null; |
||
189 | $refererHost = parse_url($referer, PHP_URL_HOST); |
||
190 | |||
191 | if (!$allowHotlinking) { |
||
192 | if ($passwordMatch) { |
||
193 | ; // Always allow when password match |
||
194 | verbose("Hotlinking since passwordmatch"); |
||
195 | } elseif ($passwordMatch === false) { |
||
196 | errorPage("Hotlinking/leeching not allowed when password missmatch.", 403); |
||
197 | } elseif (!$referer) { |
||
198 | errorPage("Hotlinking/leeching not allowed and referer is missing.", 403); |
||
199 | } elseif (strcmp($serverName, $refererHost) == 0) { |
||
200 | ; // Allow when serverName matches refererHost |
||
201 | verbose("Hotlinking disallowed but serverName matches refererHost."); |
||
202 | } elseif (!empty($hotlinkingWhitelist)) { |
||
203 | $whitelist = new CWhitelist(); |
||
204 | $allowedByWhitelist = $whitelist->check($refererHost, $hotlinkingWhitelist); |
||
205 | |||
206 | if ($allowedByWhitelist) { |
||
207 | verbose("Hotlinking/leeching allowed by whitelist."); |
||
208 | } else { |
||
209 | errorPage("Hotlinking/leeching not allowed by whitelist. Referer: $referer.", 403); |
||
210 | } |
||
211 | |||
212 | } else { |
||
213 | errorPage("Hotlinking/leeching not allowed.", 403); |
||
214 | } |
||
215 | } |
||
216 | |||
217 | verbose("allow_hotlinking = $allowHotlinking"); |
||
218 | verbose("referer = $referer"); |
||
219 | verbose("referer host = $refererHost"); |
||
220 | |||
221 | |||
222 | |||
223 | /** |
||
224 | * Create the class for the image. |
||
225 | */ |
||
226 | $CImage = getConfig('CImage', 'CImage'); |
||
227 | $img = new $CImage(); |
||
228 | $img->setVerbose($verbose || $verboseFile); |
||
229 | |||
230 | |||
231 | |||
232 | /** |
||
233 | * Get the cachepath from config. |
||
234 | */ |
||
235 | $CCache = getConfig('CCache', 'CCache'); |
||
236 | $cachePath = getConfig('cache_path', __DIR__ . '/../cache/'); |
||
237 | $cache = new $CCache(); |
||
238 | $cache->setDir($cachePath); |
||
239 | |||
240 | |||
241 | |||
242 | /** |
||
243 | * no-cache, nc - skip the cached version and process and create a new version in cache. |
||
244 | */ |
||
245 | $useCache = getDefined(array('no-cache', 'nc'), false, true); |
||
246 | |||
247 | verbose("use cache = $useCache"); |
||
248 | |||
249 | |||
250 | |||
251 | /** |
||
252 | * Prepare fast track cache for swriting cache items. |
||
253 | */ |
||
254 | $fastTrackCache = "fasttrack"; |
||
255 | $allowFastTrackCache = getConfig('fast_track_allow', false); |
||
256 | |||
257 | $CFastTrackCache = getConfig('CFastTrackCache', 'CFastTrackCache'); |
||
258 | $ftc = new $CFastTrackCache(); |
||
259 | $ftc->setCacheDir($cache->getPathToSubdir($fastTrackCache)) |
||
260 | ->enable($allowFastTrackCache) |
||
261 | ->setFilename(array('no-cache', 'nc')); |
||
262 | $img->injectDependency("fastTrackCache", $ftc); |
||
263 | |||
264 | |||
265 | |||
266 | /** |
||
267 | * Load and output images from fast track cache, if items are available |
||
268 | * in cache. |
||
269 | */ |
||
270 | if ($useCache && $allowFastTrackCache) { |
||
271 | if (CIMAGE_DEBUG) { |
||
272 | trace("img.php fast track cache enabled and used"); |
||
273 | } |
||
274 | $ftc->output(); |
||
275 | } |
||
276 | |||
277 | |||
278 | |||
279 | /** |
||
280 | * Allow or disallow remote download of images from other servers. |
||
281 | * Passwords apply if used. |
||
282 | * |
||
283 | */ |
||
284 | $allowRemote = getConfig('remote_allow', false); |
||
285 | |||
286 | if ($allowRemote && $passwordMatch !== false) { |
||
287 | $cacheRemote = $cache->getPathToSubdir("remote"); |
||
288 | |||
289 | $pattern = getConfig('remote_pattern', null); |
||
290 | $img->setRemoteDownload($allowRemote, $cacheRemote, $pattern); |
||
291 | |||
292 | $whitelist = getConfig('remote_whitelist', null); |
||
293 | $img->setRemoteHostWhitelist($whitelist); |
||
294 | } |
||
295 | |||
296 | |||
297 | |||
298 | /** |
||
299 | * shortcut, sc - extend arguments with a constant value, defined |
||
300 | * in config-file. |
||
301 | */ |
||
302 | $shortcut = get(array('shortcut', 'sc'), null); |
||
303 | $shortcutConfig = getConfig('shortcut', array( |
||
304 | 'sepia' => "&f=grayscale&f0=brightness,-10&f1=contrast,-20&f2=colorize,120,60,0,0&sharpen", |
||
305 | )); |
||
306 | |||
307 | verbose("shortcut = $shortcut"); |
||
308 | |||
309 | if (isset($shortcut) |
||
310 | && isset($shortcutConfig[$shortcut])) { |
||
311 | |||
312 | parse_str($shortcutConfig[$shortcut], $get); |
||
313 | verbose("shortcut-constant = {$shortcutConfig[$shortcut]}"); |
||
314 | $_GET = array_merge($_GET, $get); |
||
315 | } |
||
316 | |||
317 | |||
318 | |||
319 | /** |
||
320 | * src - the source image file. |
||
321 | */ |
||
322 | $srcImage = urldecode(get('src')) |
||
323 | or errorPage('Must set src-attribute.', 404); |
||
324 | |||
325 | // Get settings for src-alt as backup image |
||
326 | $srcAltImage = urldecode(get('src-alt', null)); |
||
327 | $srcAltConfig = getConfig('src_alt', null); |
||
328 | if (empty($srcAltImage)) { |
||
329 | $srcAltImage = $srcAltConfig; |
||
330 | } |
||
331 | |||
332 | // Check for valid/invalid characters |
||
333 | $imagePath = getConfig('image_path', __DIR__ . '/img/'); |
||
334 | $imagePathConstraint = getConfig('image_path_constraint', true); |
||
335 | $validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#'); |
||
336 | |||
337 | // Source is remote |
||
338 | $remoteSource = false; |
||
339 | |||
340 | // Dummy image feature |
||
341 | $dummyEnabled = getConfig('dummy_enabled', true); |
||
342 | $dummyFilename = getConfig('dummy_filename', 'dummy'); |
||
343 | $dummyImage = false; |
||
344 | |||
345 | preg_match($validFilename, $srcImage) |
||
346 | or errorPage('Source filename contains invalid characters.', 404); |
||
347 | |||
348 | if ($dummyEnabled && $srcImage === $dummyFilename) { |
||
349 | |||
350 | // Prepare to create a dummy image and use it as the source image. |
||
351 | $dummyImage = true; |
||
352 | |||
353 | } elseif ($allowRemote && $img->isRemoteSource($srcImage)) { |
||
354 | |||
355 | // If source is a remote file, ignore local file checks. |
||
356 | $remoteSource = true; |
||
357 | |||
358 | } else { |
||
359 | |||
360 | // Check if file exists on disk or try using src-alt |
||
361 | $pathToImage = realpath($imagePath . $srcImage); |
||
362 | |||
363 | if (!is_file($pathToImage) && !empty($srcAltImage)) { |
||
364 | // Try using the src-alt instead |
||
365 | $srcImage = $srcAltImage; |
||
366 | $pathToImage = realpath($imagePath . $srcImage); |
||
367 | |||
368 | preg_match($validFilename, $srcImage) |
||
369 | or errorPage('Source (alt) filename contains invalid characters.', 404); |
||
370 | |||
371 | if ($dummyEnabled && $srcImage === $dummyFilename) { |
||
372 | // Check if src-alt is the dummy image |
||
373 | $dummyImage = true; |
||
374 | } |
||
375 | } |
||
376 | |||
377 | if (!$dummyImage) { |
||
378 | is_file($pathToImage) |
||
379 | or errorPage( |
||
380 | 'Source image is not a valid file, check the filename and that a |
||
381 | matching file exists on the filesystem.', |
||
382 | 404 |
||
383 | ); |
||
384 | } |
||
385 | } |
||
386 | |||
387 | if ($imagePathConstraint && !$dummyImage && !$remoteSource) { |
||
388 | // Check that the image is a file below the directory 'image_path'. |
||
389 | $imageDir = realpath($imagePath); |
||
390 | |||
391 | substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0 |
||
392 | or errorPage( |
||
393 | 'Security constraint: Source image is not below the directory "image_path" |
||
394 | as specified in the config file img_config.php.', |
||
395 | 404 |
||
396 | ); |
||
397 | } |
||
398 | |||
399 | verbose("src = $srcImage"); |
||
400 | |||
401 | |||
402 | |||
403 | /** |
||
404 | * Manage size constants from config file, use constants to replace values |
||
405 | * for width and height. |
||
406 | */ |
||
407 | $sizeConstant = getConfig('size_constant', function () { |
||
408 | |||
409 | // Set sizes to map constant to value, easier to use with width or height |
||
410 | $sizes = array( |
||
411 | 'w1' => 613, |
||
412 | 'w2' => 630, |
||
413 | ); |
||
414 | |||
415 | // Add grid column width, useful for use as predefined size for width (or height). |
||
416 | $gridColumnWidth = 30; |
||
417 | $gridGutterWidth = 10; |
||
418 | $gridColumns = 24; |
||
419 | |||
420 | for ($i = 1; $i <= $gridColumns; $i++) { |
||
421 | $sizes['c' . $i] = ($gridColumnWidth + $gridGutterWidth) * $i - $gridGutterWidth; |
||
422 | } |
||
423 | |||
424 | return $sizes; |
||
425 | }); |
||
426 | |||
427 | $sizes = call_user_func($sizeConstant); |
||
428 | |||
429 | |||
430 | |||
431 | /** |
||
432 | * width, w - set target width, affecting the resulting image width, height and resize options |
||
433 | */ |
||
434 | $newWidth = get(array('width', 'w')); |
||
435 | $maxWidth = getConfig('max_width', 2000); |
||
436 | |||
437 | // Check to replace predefined size |
||
438 | if (isset($sizes[$newWidth])) { |
||
439 | $newWidth = $sizes[$newWidth]; |
||
440 | } |
||
441 | |||
442 | // Support width as % of original width |
||
443 | if ($newWidth[strlen($newWidth)-1] == '%') { |
||
444 | is_numeric(substr($newWidth, 0, -1)) |
||
445 | or errorPage('Width % not numeric.', 404); |
||
446 | } else { |
||
447 | is_null($newWidth) |
||
448 | or ($newWidth > 10 && $newWidth <= $maxWidth) |
||
449 | or errorPage('Width out of range.', 404); |
||
450 | } |
||
451 | |||
452 | verbose("new width = $newWidth"); |
||
453 | |||
454 | |||
455 | |||
456 | /** |
||
457 | * height, h - set target height, affecting the resulting image width, height and resize options |
||
458 | */ |
||
459 | $newHeight = get(array('height', 'h')); |
||
460 | $maxHeight = getConfig('max_height', 2000); |
||
461 | |||
462 | // Check to replace predefined size |
||
463 | if (isset($sizes[$newHeight])) { |
||
464 | $newHeight = $sizes[$newHeight]; |
||
465 | } |
||
466 | |||
467 | // height |
||
468 | if ($newHeight[strlen($newHeight)-1] == '%') { |
||
469 | is_numeric(substr($newHeight, 0, -1)) |
||
470 | or errorPage('Height % out of range.', 404); |
||
471 | } else { |
||
472 | is_null($newHeight) |
||
473 | or ($newHeight > 10 && $newHeight <= $maxHeight) |
||
474 | or errorPage('Height out of range.', 404); |
||
475 | } |
||
476 | |||
477 | verbose("new height = $newHeight"); |
||
478 | |||
479 | |||
480 | |||
481 | /** |
||
482 | * aspect-ratio, ar - affecting the resulting image width, height and resize options |
||
483 | */ |
||
484 | $aspectRatio = get(array('aspect-ratio', 'ar')); |
||
485 | $aspectRatioConstant = getConfig('aspect_ratio_constant', function () { |
||
486 | return array( |
||
487 | '3:1' => 3/1, |
||
488 | '3:2' => 3/2, |
||
489 | '4:3' => 4/3, |
||
490 | '8:5' => 8/5, |
||
491 | '16:10' => 16/10, |
||
492 | '16:9' => 16/9, |
||
493 | 'golden' => 1.618, |
||
494 | ); |
||
495 | }); |
||
496 | |||
497 | // Check to replace predefined aspect ratio |
||
498 | $aspectRatios = call_user_func($aspectRatioConstant); |
||
499 | $negateAspectRatio = ($aspectRatio[0] == '!') ? true : false; |
||
500 | $aspectRatio = $negateAspectRatio ? substr($aspectRatio, 1) : $aspectRatio; |
||
501 | |||
502 | if (isset($aspectRatios[$aspectRatio])) { |
||
503 | $aspectRatio = $aspectRatios[$aspectRatio]; |
||
504 | } |
||
505 | |||
506 | if ($negateAspectRatio) { |
||
507 | $aspectRatio = 1 / $aspectRatio; |
||
508 | } |
||
509 | |||
510 | is_null($aspectRatio) |
||
511 | or is_numeric($aspectRatio) |
||
512 | or errorPage('Aspect ratio out of range', 404); |
||
513 | |||
514 | verbose("aspect ratio = $aspectRatio"); |
||
515 | |||
516 | |||
517 | |||
518 | /** |
||
519 | * crop-to-fit, cf - affecting the resulting image width, height and resize options |
||
520 | */ |
||
521 | $cropToFit = getDefined(array('crop-to-fit', 'cf'), true, false); |
||
522 | |||
523 | verbose("crop to fit = $cropToFit"); |
||
524 | |||
525 | |||
526 | |||
527 | /** |
||
528 | * Set default background color from config file. |
||
529 | */ |
||
530 | $backgroundColor = getConfig('background_color', null); |
||
531 | |||
532 | if ($backgroundColor) { |
||
533 | $img->setDefaultBackgroundColor($backgroundColor); |
||
534 | verbose("Using default background_color = $backgroundColor"); |
||
535 | } |
||
536 | |||
537 | |||
538 | |||
539 | /** |
||
540 | * bgColor - Default background color to use |
||
541 | */ |
||
542 | $bgColor = get(array('bgColor', 'bg-color', 'bgc'), null); |
||
543 | |||
544 | verbose("bgColor = $bgColor"); |
||
545 | |||
546 | |||
547 | |||
548 | /** |
||
549 | * Do or do not resample image when resizing. |
||
550 | */ |
||
551 | $resizeStrategy = getDefined(array('no-resample'), true, false); |
||
552 | |||
553 | if ($resizeStrategy) { |
||
554 | $img->setCopyResizeStrategy($img::RESIZE); |
||
555 | verbose("Setting = Resize instead of resample"); |
||
556 | } |
||
557 | |||
558 | |||
559 | |||
560 | |||
561 | /** |
||
562 | * fill-to-fit, ff - affecting the resulting image width, height and resize options |
||
563 | */ |
||
564 | $fillToFit = get(array('fill-to-fit', 'ff'), null); |
||
565 | |||
566 | verbose("fill-to-fit = $fillToFit"); |
||
567 | |||
568 | if ($fillToFit !== null) { |
||
569 | |||
570 | if (!empty($fillToFit)) { |
||
571 | $bgColor = $fillToFit; |
||
572 | verbose("fillToFit changed bgColor to = $bgColor"); |
||
573 | } |
||
574 | |||
575 | $fillToFit = true; |
||
576 | verbose("fill-to-fit (fixed) = $fillToFit"); |
||
577 | } |
||
578 | |||
579 | |||
580 | |||
581 | /** |
||
582 | * no-ratio, nr, stretch - affecting the resulting image width, height and resize options |
||
583 | */ |
||
584 | $keepRatio = getDefined(array('no-ratio', 'nr', 'stretch'), false, true); |
||
585 | |||
586 | verbose("keep ratio = $keepRatio"); |
||
587 | |||
588 | |||
589 | |||
590 | /** |
||
591 | * crop, c - affecting the resulting image width, height and resize options |
||
592 | */ |
||
593 | $crop = get(array('crop', 'c')); |
||
594 | |||
595 | verbose("crop = $crop"); |
||
596 | |||
597 | |||
598 | |||
599 | /** |
||
600 | * area, a - affecting the resulting image width, height and resize options |
||
601 | */ |
||
602 | $area = get(array('area', 'a')); |
||
603 | |||
604 | verbose("area = $area"); |
||
605 | |||
606 | |||
607 | |||
608 | /** |
||
609 | * skip-original, so - skip the original image and always process a new image |
||
610 | */ |
||
611 | $useOriginal = getDefined(array('skip-original', 'so'), false, true); |
||
612 | $useOriginalDefault = getConfig('skip_original', false); |
||
613 | |||
614 | if ($useOriginalDefault === true) { |
||
615 | verbose("skip original is default ON"); |
||
616 | $useOriginal = false; |
||
617 | } |
||
618 | |||
619 | verbose("use original = $useOriginal"); |
||
620 | |||
621 | |||
622 | |||
623 | /** |
||
624 | * quality, q - set level of quality for jpeg images |
||
625 | */ |
||
626 | $quality = get(array('quality', 'q')); |
||
627 | $qualityDefault = getConfig('jpg_quality', null); |
||
628 | |||
629 | is_null($quality) |
||
630 | or ($quality > 0 and $quality <= 100) |
||
631 | or errorPage('Quality out of range', 404); |
||
632 | |||
633 | if (is_null($quality) && !is_null($qualityDefault)) { |
||
634 | $quality = $qualityDefault; |
||
635 | } |
||
636 | |||
637 | verbose("quality = $quality"); |
||
638 | |||
639 | |||
640 | |||
641 | /** |
||
642 | * compress, co - what strategy to use when compressing png images |
||
643 | */ |
||
644 | $compress = get(array('compress', 'co')); |
||
645 | $compressDefault = getConfig('png_compression', null); |
||
646 | |||
647 | is_null($compress) |
||
648 | or ($compress > 0 and $compress <= 9) |
||
649 | or errorPage('Compress out of range', 404); |
||
650 | |||
651 | if (is_null($compress) && !is_null($compressDefault)) { |
||
652 | $compress = $compressDefault; |
||
653 | } |
||
654 | |||
655 | verbose("compress = $compress"); |
||
656 | |||
657 | |||
658 | |||
659 | /** |
||
660 | * save-as, sa - what type of image to save |
||
661 | */ |
||
662 | $saveAs = get(array('save-as', 'sa')); |
||
663 | |||
664 | verbose("save as = $saveAs"); |
||
665 | |||
666 | |||
667 | |||
668 | /** |
||
669 | * scale, s - Processing option, scale up or down the image prior actual resize |
||
670 | */ |
||
671 | $scale = get(array('scale', 's')); |
||
672 | |||
673 | is_null($scale) |
||
674 | or ($scale >= 0 and $scale <= 400) |
||
675 | or errorPage('Scale out of range', 404); |
||
676 | |||
677 | verbose("scale = $scale"); |
||
678 | |||
679 | |||
680 | |||
681 | /** |
||
682 | * palette, p - Processing option, create a palette version of the image |
||
683 | */ |
||
684 | $palette = getDefined(array('palette', 'p'), true, false); |
||
685 | |||
686 | verbose("palette = $palette"); |
||
687 | |||
688 | |||
689 | |||
690 | /** |
||
691 | * sharpen - Processing option, post filter for sharpen effect |
||
692 | */ |
||
693 | $sharpen = getDefined('sharpen', true, null); |
||
694 | |||
695 | verbose("sharpen = $sharpen"); |
||
696 | |||
697 | |||
698 | |||
699 | /** |
||
700 | * emboss - Processing option, post filter for emboss effect |
||
701 | */ |
||
702 | $emboss = getDefined('emboss', true, null); |
||
703 | |||
704 | verbose("emboss = $emboss"); |
||
705 | |||
706 | |||
707 | |||
708 | /** |
||
709 | * blur - Processing option, post filter for blur effect |
||
710 | */ |
||
711 | $blur = getDefined('blur', true, null); |
||
712 | |||
713 | verbose("blur = $blur"); |
||
714 | |||
715 | |||
716 | |||
717 | /** |
||
718 | * rotateBefore - Rotate the image with an angle, before processing |
||
719 | */ |
||
720 | $rotateBefore = get(array('rotateBefore', 'rotate-before', 'rb')); |
||
721 | |||
722 | is_null($rotateBefore) |
||
723 | or ($rotateBefore >= -360 and $rotateBefore <= 360) |
||
724 | or errorPage('RotateBefore out of range', 404); |
||
725 | |||
726 | verbose("rotateBefore = $rotateBefore"); |
||
727 | |||
728 | |||
729 | |||
730 | /** |
||
731 | * rotateAfter - Rotate the image with an angle, before processing |
||
732 | */ |
||
733 | $rotateAfter = get(array('rotateAfter', 'rotate-after', 'ra', 'rotate', 'r')); |
||
734 | |||
735 | is_null($rotateAfter) |
||
736 | or ($rotateAfter >= -360 and $rotateAfter <= 360) |
||
737 | or errorPage('RotateBefore out of range', 404); |
||
738 | |||
739 | verbose("rotateAfter = $rotateAfter"); |
||
740 | |||
741 | |||
742 | |||
743 | /** |
||
744 | * autoRotate - Auto rotate based on EXIF information |
||
745 | */ |
||
746 | $autoRotate = getDefined(array('autoRotate', 'auto-rotate', 'aro'), true, false); |
||
747 | |||
748 | verbose("autoRotate = $autoRotate"); |
||
749 | |||
750 | |||
751 | |||
752 | /** |
||
753 | * filter, f, f0-f9 - Processing option, post filter for various effects using imagefilter() |
||
754 | */ |
||
755 | $filters = array(); |
||
756 | $filter = get(array('filter', 'f')); |
||
757 | if ($filter) { |
||
758 | $filters[] = $filter; |
||
759 | } |
||
760 | |||
761 | for ($i = 0; $i < 10; $i++) { |
||
762 | $filter = get(array("filter{$i}", "f{$i}")); |
||
763 | if ($filter) { |
||
764 | $filters[] = $filter; |
||
765 | } |
||
766 | } |
||
767 | |||
768 | verbose("filters = " . print_r($filters, 1)); |
||
769 | |||
770 | |||
771 | |||
772 | /** |
||
773 | * json - output the image as a JSON object with details on the image. |
||
774 | * ascii - output the image as ASCII art. |
||
775 | */ |
||
776 | $outputFormat = getDefined('json', 'json', null); |
||
777 | $outputFormat = getDefined('ascii', 'ascii', $outputFormat); |
||
778 | |||
779 | verbose("outputformat = $outputFormat"); |
||
780 | |||
781 | if ($outputFormat == 'ascii') { |
||
782 | $defaultOptions = getConfig( |
||
783 | 'ascii-options', |
||
784 | array( |
||
785 | "characterSet" => 'two', |
||
786 | "scale" => 14, |
||
787 | "luminanceStrategy" => 3, |
||
788 | "customCharacterSet" => null, |
||
789 | ) |
||
790 | ); |
||
791 | $options = get('ascii'); |
||
792 | $options = explode(',', $options); |
||
793 | |||
794 | if (isset($options[0]) && !empty($options[0])) { |
||
795 | $defaultOptions['characterSet'] = $options[0]; |
||
796 | } |
||
797 | |||
798 | if (isset($options[1]) && !empty($options[1])) { |
||
799 | $defaultOptions['scale'] = $options[1]; |
||
800 | } |
||
801 | |||
802 | if (isset($options[2]) && !empty($options[2])) { |
||
803 | $defaultOptions['luminanceStrategy'] = $options[2]; |
||
804 | } |
||
805 | |||
806 | if (count($options) > 3) { |
||
807 | // Last option is custom character string |
||
808 | unset($options[0]); |
||
809 | unset($options[1]); |
||
810 | unset($options[2]); |
||
811 | $characterString = implode($options); |
||
812 | $defaultOptions['customCharacterSet'] = $characterString; |
||
813 | } |
||
814 | |||
815 | $img->setAsciiOptions($defaultOptions); |
||
816 | } |
||
817 | |||
818 | |||
819 | |||
820 | |||
821 | /** |
||
822 | * dpr - change to get larger image to easier support larger dpr, such as retina. |
||
823 | */ |
||
824 | $dpr = get(array('ppi', 'dpr', 'device-pixel-ratio'), 1); |
||
825 | |||
826 | verbose("dpr = $dpr"); |
||
827 | |||
828 | |||
829 | |||
830 | /** |
||
831 | * convolve - image convolution as in http://php.net/manual/en/function.imageconvolution.php |
||
832 | */ |
||
833 | $convolve = get('convolve', null); |
||
834 | $convolutionConstant = getConfig('convolution_constant', array()); |
||
835 | |||
836 | // Check if the convolve is matching an existing constant |
||
837 | if ($convolve && isset($convolutionConstant)) { |
||
838 | $img->addConvolveExpressions($convolutionConstant); |
||
839 | verbose("convolve constant = " . print_r($convolutionConstant, 1)); |
||
840 | } |
||
841 | |||
842 | verbose("convolve = " . print_r($convolve, 1)); |
||
843 | |||
844 | |||
845 | |||
846 | /** |
||
847 | * no-upscale, nu - Do not upscale smaller image to larger dimension. |
||
848 | */ |
||
849 | $upscale = getDefined(array('no-upscale', 'nu'), false, true); |
||
850 | |||
851 | verbose("upscale = $upscale"); |
||
852 | |||
853 | |||
854 | |||
855 | /** |
||
856 | * Get details for post processing |
||
857 | */ |
||
858 | $postProcessing = getConfig('postprocessing', array( |
||
859 | 'png_lossy' => false, |
||
860 | 'png_lossy_cmd' => '/usr/local/bin/pngquant --force --output', |
||
861 | |||
862 | 'png_filter' => false, |
||
863 | 'png_filter_cmd' => '/usr/local/bin/optipng -q', |
||
864 | |||
865 | 'png_deflate' => false, |
||
866 | 'png_deflate_cmd' => '/usr/local/bin/pngout -q', |
||
867 | |||
868 | 'jpeg_optimize' => false, |
||
869 | 'jpeg_optimize_cmd' => '/usr/local/bin/jpegtran -copy none -optimize', |
||
870 | )); |
||
871 | |||
872 | |||
873 | |||
874 | /** |
||
875 | * lossy - Do lossy postprocessing, if available. |
||
876 | */ |
||
877 | $lossy = getDefined(array('lossy'), true, null); |
||
878 | |||
879 | verbose("lossy = $lossy"); |
||
880 | |||
881 | |||
882 | |||
883 | /** |
||
884 | * alias - Save resulting image to another alias name. |
||
885 | * Password always apply, must be defined. |
||
886 | */ |
||
887 | $alias = get('alias', null); |
||
888 | $aliasPath = getConfig('alias_path', null); |
||
889 | $validAliasname = getConfig('valid_aliasname', '#^[a-z0-9A-Z-_]+$#'); |
||
890 | $aliasTarget = null; |
||
891 | |||
892 | if ($alias && $aliasPath && $passwordMatch) { |
||
893 | |||
894 | $aliasTarget = $aliasPath . $alias; |
||
895 | $useCache = false; |
||
896 | |||
897 | is_writable($aliasPath) |
||
898 | or errorPage("Directory for alias is not writable.", 403); |
||
899 | |||
900 | preg_match($validAliasname, $alias) |
||
901 | or errorPage('Filename for alias contains invalid characters. Do not add extension.', 404); |
||
902 | |||
903 | } elseif ($alias) { |
||
904 | errorPage('Alias is not enabled in the config file or password not matching.', 403); |
||
905 | } |
||
906 | |||
907 | verbose("alias = $alias"); |
||
908 | |||
909 | |||
910 | |||
911 | /** |
||
912 | * Add cache control HTTP header. |
||
913 | */ |
||
914 | $cacheControl = getConfig('cache_control', null); |
||
915 | |||
916 | if ($cacheControl) { |
||
917 | verbose("cacheControl = $cacheControl"); |
||
918 | $img->addHTTPHeader("Cache-Control", $cacheControl); |
||
919 | } |
||
920 | |||
921 | |||
922 | |||
923 | /** |
||
924 | * Prepare a dummy image and use it as source image. |
||
925 | */ |
||
926 | if ($dummyImage === true) { |
||
927 | $dummyDir = $cache->getPathToSubdir("dummy"); |
||
928 | |||
929 | $img->setSaveFolder($dummyDir) |
||
930 | ->setSource($dummyFilename, $dummyDir) |
||
931 | ->setOptions( |
||
932 | array( |
||
933 | 'newWidth' => $newWidth, |
||
934 | 'newHeight' => $newHeight, |
||
935 | 'bgColor' => $bgColor, |
||
936 | ) |
||
937 | ) |
||
938 | ->setJpegQuality($quality) |
||
939 | ->setPngCompression($compress) |
||
940 | ->createDummyImage() |
||
941 | ->generateFilename(null, false) |
||
942 | ->save(null, null, false); |
||
943 | |||
944 | $srcImage = $img->getTarget(); |
||
945 | $imagePath = null; |
||
946 | |||
947 | verbose("src (updated) = $srcImage"); |
||
948 | } |
||
949 | |||
950 | |||
951 | |||
952 | /** |
||
953 | * Prepare a sRGB version of the image and use it as source image. |
||
954 | */ |
||
955 | $srgbDefault = getConfig('srgb_default', false); |
||
956 | $srgbColorProfile = getConfig('srgb_colorprofile', __DIR__ . '/../icc/sRGB_IEC61966-2-1_black_scaled.icc'); |
||
957 | $srgb = getDefined('srgb', true, null); |
||
958 | |||
959 | if ($srgb || $srgbDefault) { |
||
960 | |||
961 | $filename = $img->convert2sRGBColorSpace( |
||
962 | $srcImage, |
||
963 | $imagePath, |
||
964 | $cache->getPathToSubdir("srgb"), |
||
965 | $srgbColorProfile, |
||
966 | $useCache |
||
967 | ); |
||
968 | |||
969 | if ($filename) { |
||
970 | $srcImage = $img->getTarget(); |
||
971 | $imagePath = null; |
||
972 | verbose("srgb conversion and saved to cache = $srcImage"); |
||
973 | } else { |
||
974 | verbose("srgb not op"); |
||
975 | } |
||
976 | } |
||
977 | |||
978 | |||
979 | |||
980 | /** |
||
981 | * Display status |
||
982 | */ |
||
983 | if ($status) { |
||
984 | $text = "img.php version = " . CIMAGE_VERSION . "\n"; |
||
985 | $text .= "PHP version = " . PHP_VERSION . "\n"; |
||
986 | $text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n"; |
||
987 | $text .= "Allow remote images = $allowRemote\n"; |
||
988 | |||
989 | $res = $cache->getStatusOfSubdir(""); |
||
990 | $text .= "Cache $res\n"; |
||
991 | |||
992 | $res = $cache->getStatusOfSubdir("remote"); |
||
993 | $text .= "Cache remote $res\n"; |
||
994 | |||
995 | $res = $cache->getStatusOfSubdir("dummy"); |
||
996 | $text .= "Cache dummy $res\n"; |
||
997 | |||
998 | $res = $cache->getStatusOfSubdir("srgb"); |
||
999 | $text .= "Cache srgb $res\n"; |
||
1000 | |||
1001 | $res = $cache->getStatusOfSubdir($fastTrackCache); |
||
1002 | $text .= "Cache fasttrack $res\n"; |
||
1003 | |||
1004 | $text .= "Alias path writable = " . is_writable($aliasPath) . "\n"; |
||
1005 | |||
1006 | $no = extension_loaded('exif') ? null : 'NOT'; |
||
1007 | $text .= "Extension exif is $no loaded.<br>"; |
||
1008 | |||
1009 | $no = extension_loaded('curl') ? null : 'NOT'; |
||
1010 | $text .= "Extension curl is $no loaded.<br>"; |
||
1011 | |||
1012 | $no = extension_loaded('imagick') ? null : 'NOT'; |
||
1013 | $text .= "Extension imagick is $no loaded.<br>"; |
||
1014 | |||
1015 | $no = extension_loaded('gd') ? null : 'NOT'; |
||
1016 | $text .= "Extension gd is $no loaded.<br>"; |
||
1017 | |||
1018 | $text .= checkExternalCommand("PNG LOSSY", $postProcessing["png_lossy"], $postProcessing["png_lossy_cmd"]); |
||
0 ignored issues
–
show
Are you sure the usage of
checkExternalCommand('PN...ssing['png_lossy_cmd']) is correct as it seems to always return null .
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
1019 | $text .= checkExternalCommand("PNG FILTER", $postProcessing["png_filter"], $postProcessing["png_filter_cmd"]); |
||
0 ignored issues
–
show
Are you sure the usage of
checkExternalCommand('PN...sing['png_filter_cmd']) is correct as it seems to always return null .
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
1020 | $text .= checkExternalCommand("PNG DEFLATE", $postProcessing["png_deflate"], $postProcessing["png_deflate_cmd"]); |
||
0 ignored issues
–
show
Are you sure the usage of
checkExternalCommand('PN...ing['png_deflate_cmd']) is correct as it seems to always return null .
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
1021 | $text .= checkExternalCommand("JPEG OPTIMIZE", $postProcessing["jpeg_optimize"], $postProcessing["jpeg_optimize_cmd"]); |
||
0 ignored issues
–
show
Are you sure the usage of
checkExternalCommand('JP...g['jpeg_optimize_cmd']) is correct as it seems to always return null .
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
1022 | |||
1023 | if (!$no) { |
||
1024 | $text .= print_r(gd_info(), 1); |
||
1025 | } |
||
1026 | |||
1027 | echo <<<EOD |
||
1028 | <!doctype html> |
||
1029 | <html lang=en> |
||
1030 | <meta charset=utf-8> |
||
1031 | <title>CImage status</title> |
||
1032 | <pre>$text</pre> |
||
1033 | EOD; |
||
1034 | exit; |
||
1035 | } |
||
1036 | |||
1037 | |||
1038 | |||
1039 | /** |
||
1040 | * Log verbose details to file |
||
1041 | */ |
||
1042 | if ($verboseFile) { |
||
1043 | $img->setVerboseToFile("$cachePath/log.txt"); |
||
1044 | } |
||
1045 | |||
1046 | |||
1047 | |||
1048 | /** |
||
1049 | * Hook after img.php configuration and before processing with CImage |
||
1050 | */ |
||
1051 | $hookBeforeCImage = getConfig('hook_before_CImage', null); |
||
1052 | |||
1053 | if (is_callable($hookBeforeCImage)) { |
||
1054 | verbose("hookBeforeCImage activated"); |
||
1055 | |||
1056 | $allConfig = $hookBeforeCImage($img, array( |
||
1057 | // Options for calculate dimensions |
||
1058 | 'newWidth' => $newWidth, |
||
1059 | 'newHeight' => $newHeight, |
||
1060 | 'aspectRatio' => $aspectRatio, |
||
1061 | 'keepRatio' => $keepRatio, |
||
1062 | 'cropToFit' => $cropToFit, |
||
1063 | 'fillToFit' => $fillToFit, |
||
1064 | 'crop' => $crop, |
||
1065 | 'area' => $area, |
||
1066 | 'upscale' => $upscale, |
||
1067 | |||
1068 | // Pre-processing, before resizing is done |
||
1069 | 'scale' => $scale, |
||
1070 | 'rotateBefore' => $rotateBefore, |
||
1071 | 'autoRotate' => $autoRotate, |
||
1072 | |||
1073 | // General processing options |
||
1074 | 'bgColor' => $bgColor, |
||
1075 | |||
1076 | // Post-processing, after resizing is done |
||
1077 | 'palette' => $palette, |
||
1078 | 'filters' => $filters, |
||
1079 | 'sharpen' => $sharpen, |
||
1080 | 'emboss' => $emboss, |
||
1081 | 'blur' => $blur, |
||
1082 | 'convolve' => $convolve, |
||
1083 | 'rotateAfter' => $rotateAfter, |
||
1084 | |||
1085 | // Output format |
||
1086 | 'outputFormat' => $outputFormat, |
||
1087 | 'dpr' => $dpr, |
||
1088 | |||
1089 | // Other |
||
1090 | 'postProcessing' => $postProcessing, |
||
1091 | 'lossy' => $lossy, |
||
1092 | )); |
||
1093 | verbose(print_r($allConfig, 1)); |
||
1094 | extract($allConfig); |
||
1095 | } |
||
1096 | |||
1097 | |||
1098 | |||
1099 | /** |
||
1100 | * Display image if verbose mode |
||
1101 | */ |
||
1102 | if ($verbose) { |
||
1103 | $query = array(); |
||
1104 | parse_str($_SERVER['QUERY_STRING'], $query); |
||
1105 | unset($query['verbose']); |
||
1106 | unset($query['v']); |
||
1107 | unset($query['nocache']); |
||
1108 | unset($query['nc']); |
||
1109 | unset($query['json']); |
||
1110 | $url1 = '?' . htmlentities(urldecode(http_build_query($query))); |
||
1111 | $url2 = '?' . urldecode(http_build_query($query)); |
||
1112 | echo <<<EOD |
||
1113 | <!doctype html> |
||
1114 | <html lang=en> |
||
1115 | <meta charset=utf-8> |
||
1116 | <title>CImage verbose output</title> |
||
1117 | <style>body{background-color: #ddd}</style> |
||
1118 | <a href=$url1><code>$url1</code></a><br> |
||
1119 | <img src='{$url1}' /> |
||
1120 | <pre id="json"></pre> |
||
1121 | <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> |
||
1122 | <script type="text/javascript"> |
||
1123 | window.getDetails = function (url, id) { |
||
1124 | $.getJSON(url, function(data) { |
||
1125 | element = document.getElementById(id); |
||
1126 | element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio + ( data.pngType ? "\\npng-type: " + data.pngType : ''); |
||
1127 | }); |
||
1128 | } |
||
1129 | </script> |
||
1130 | <script type="text/javascript">window.getDetails("{$url2}&json", "json")</script> |
||
1131 | EOD; |
||
1132 | } |
||
1133 | |||
1134 | |||
1135 | |||
1136 | /** |
||
1137 | * Load, process and output the image |
||
1138 | */ |
||
1139 | $img->log("Incoming arguments: " . print_r(verbose(), 1)) |
||
0 ignored issues
–
show
Are you sure the usage of
verbose() is correct as it seems to always return null .
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
1140 | ->setSaveFolder($cachePath) |
||
1141 | ->useCache($useCache) |
||
1142 | ->setSource($srcImage, $imagePath) |
||
1143 | ->setOptions( |
||
1144 | array( |
||
1145 | // Options for calculate dimensions |
||
1146 | 'newWidth' => $newWidth, |
||
1147 | 'newHeight' => $newHeight, |
||
1148 | 'aspectRatio' => $aspectRatio, |
||
1149 | 'keepRatio' => $keepRatio, |
||
1150 | 'cropToFit' => $cropToFit, |
||
1151 | 'fillToFit' => $fillToFit, |
||
1152 | 'crop' => $crop, |
||
1153 | 'area' => $area, |
||
1154 | 'upscale' => $upscale, |
||
1155 | |||
1156 | // Pre-processing, before resizing is done |
||
1157 | 'scale' => $scale, |
||
1158 | 'rotateBefore' => $rotateBefore, |
||
1159 | 'autoRotate' => $autoRotate, |
||
1160 | |||
1161 | // General processing options |
||
1162 | 'bgColor' => $bgColor, |
||
1163 | |||
1164 | // Post-processing, after resizing is done |
||
1165 | 'palette' => $palette, |
||
1166 | 'filters' => $filters, |
||
1167 | 'sharpen' => $sharpen, |
||
1168 | 'emboss' => $emboss, |
||
1169 | 'blur' => $blur, |
||
1170 | 'convolve' => $convolve, |
||
1171 | 'rotateAfter' => $rotateAfter, |
||
1172 | |||
1173 | // Output format |
||
1174 | 'outputFormat' => $outputFormat, |
||
1175 | 'dpr' => $dpr, |
||
1176 | |||
1177 | // Postprocessing using external tools |
||
1178 | 'lossy' => $lossy, |
||
1179 | ) |
||
1180 | ) |
||
1181 | ->loadImageDetails() |
||
1182 | ->initDimensions() |
||
1183 | ->calculateNewWidthAndHeight() |
||
1184 | ->setSaveAsExtension($saveAs) |
||
1185 | ->setJpegQuality($quality) |
||
1186 | ->setPngCompression($compress) |
||
1187 | ->useOriginalIfPossible($useOriginal) |
||
1188 | ->generateFilename($cachePath) |
||
1189 | ->useCacheIfPossible($useCache) |
||
1190 | ->load() |
||
1191 | ->preResize() |
||
1192 | ->resize() |
||
1193 | ->postResize() |
||
1194 | ->setPostProcessingOptions($postProcessing) |
||
1195 | ->save() |
||
1196 | ->linkToCacheFile($aliasTarget) |
||
1197 | ->output(); |
||
1198 |