├── imageoptim.php ├── README.md ├── LICENSE.md └── lib └── Optimizer.php /imageoptim.php: -------------------------------------------------------------------------------- 1 | hook('panel.file.upload', function($file) { 12 | optimize_init($file->root()); 13 | }); 14 | 15 | // A file has been replaced 16 | $kirby->hook('panel.file.replace', function($file) { 17 | optimize_init($file->root()); 18 | }); 19 | 20 | function optimize_init($file) { 21 | try { 22 | $optimizer = new Optimizer($file); 23 | $optimizer->optimize(array( 24 | 'max_width' => c::get('imageoptim.max_width'), 25 | 'quality' => c::get('imageoptim.quality') 26 | )); 27 | } 28 | catch(Exception $e) { 29 | error_log("Kirby - ImageOptim: ". $e->getMessage()); 30 | } 31 | } 32 | 33 | ?> 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kirby Image Optimizer Plugin 2 | Kirby CMS Plugin for automatic image compression and scaling for new or replaced panel uploads. 3 | 4 | ## Requirements 5 | - You need at least Kirby CMS v 2.1. 6 | - Your PHP version has to support PHP's GD and Image Functions. Check via: `var_dump(gd_info())` 7 | 8 | ## Installation 9 | 10 | Copy or clone this repository into your `/site/plugins` directory.
11 | Edit your `config.php` as follows: 12 | 13 | #### Basic setup 14 | ```php 15 | c::set('imageoptim', true); // {true} activate the plugin 16 | ``` 17 | #### Advanced options 18 | ```php 19 | // Quality compression in percentage. (0 = lowest quality, 100 = highest quality) 20 | c::set('imageoptim.quality', 90); // default: 90 21 | 22 | // Downscale the image to a given width. 23 | c::set('imageoptim.max_width', 1920); // default: disabled (no scaling) 24 | ``` 25 | ## Notes 26 | Currently supported Filetypes: `JPG`, `PNG`. 27 | 28 | ## Contribution 29 | Feel free to fork this project or open issues. 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 - 51seven GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/Optimizer.php: -------------------------------------------------------------------------------- 1 | image = $image; 20 | $this->getMimetype(); 21 | 22 | if(!is_writable($this->image)) { 23 | throw new Exception("Image is not writeable: ".$this->image); 24 | } 25 | } 26 | 27 | private function getQuality() { 28 | if($this->mimetype == PNG) { 29 | $quality = ($this->quality - 100) / 11.111111; 30 | $quality = round(abs($quality)); 31 | 32 | return $quality; 33 | } 34 | else { 35 | return $this->quality; 36 | } 37 | } 38 | 39 | private function getMimetype() { 40 | switch (exif_imagetype($this->image)) { 41 | case IMAGETYPE_JPEG: 42 | $this->mimetype = JPEG; 43 | break; 44 | 45 | case IMAGETYPE_PNG: 46 | $this->mimetype = PNG; 47 | break; 48 | 49 | default: 50 | return false; 51 | } 52 | 53 | return $this->mimetype; 54 | } 55 | 56 | // Optimizes a jpeg image and downscales it if necessary 57 | private function optimize_jpeg() { 58 | list($width, $height, $type, $attr) = getimagesize($this->image); 59 | 60 | $img = imageCreateFromJpeg($this->image); 61 | 62 | // check if we need to downscale the image 63 | if($this->max_width && $width > $this->max_width) { 64 | $img = imagescale($img, $this->max_width); 65 | } 66 | 67 | $this->copy = $this->image.".jpg"; // append this affix to avoid access conditions 68 | imagejpeg($img, $this->copy, $this->getQuality()); // Best quality (100) 69 | } 70 | 71 | // Optimizes a png image and downscales it if necessary 72 | private function optimize_png() { 73 | list($width, $height, $type, $attr) = getimagesize($this->image); 74 | 75 | $img = imageCreateFromPng($this->image); 76 | 77 | // check if we need to downscale the image 78 | if($this->max_width && $width > $this->max_width) { 79 | $img = imagescale($img, $this->max_width); 80 | } 81 | 82 | $this->copy = $this->image.".png"; // append this affix to avoid access conditions 83 | imagepng($img, $this->copy, $this->getQuality()); // 0 compression 84 | } 85 | 86 | // validates the integrity of the operations 87 | private function validate() { 88 | $newsize = filesize($this->copy); 89 | $oldsize = filesize($this->image); 90 | 91 | if($newsize < $oldsize) { 92 | unlink($this->image); // Delete the original image 93 | rename($this->copy, $this->image); // Rename the optimized image to the original one 94 | } 95 | else { 96 | unlink($this->copy); 97 | } 98 | } 99 | 100 | public function optimize(array $params) { 101 | $this->quality = (isset($params['quality'])) ? $params['quality'] : $this->quality; 102 | $this->max_width = (isset($params['max_width'])) ? $params['max_width'] : $this->max_width; 103 | 104 | if(!is_int($params['max_width']) || $params['max_width'] < 1) { 105 | throw new Exception("Max width must be of type Integer and at least 1px wide."); 106 | } 107 | 108 | if(!is_int($this->quality) || $this->quality < 0 || $this->quality > 100) { 109 | throw new Exception("Quality must be of type Integer and between 0 and 100."); 110 | } 111 | 112 | if($this->mimetype == JPEG) { 113 | $this->optimize_jpeg(); 114 | } 115 | else if($this->mimetype == PNG) { 116 | $this->optimize_png(); 117 | } 118 | else { 119 | // do nothing due to unsupported mimetype. 120 | return false; 121 | } 122 | 123 | $this->validate(); 124 | } 125 | } 126 | 127 | ?> 128 | --------------------------------------------------------------------------------