phippu Posted March 24, 2015 Share Posted March 24, 2015 Hello everyone! I have the problem that changing quality within picture resizing doesn't work. I'm using PW 2.5.3. The code is the following: <?php $options = array( 'quality' => 10, 'upscaling' => false, 'cropping' => 'southeast' ); $img_1x = $page->bild->first()->width(500, $options); $img_2x = $page->bild->first()->width(1000, $options); $img_3x = $page->bild->first()->width(1500, $options); include("./head.inc"); echo '<h1>'.$page->title.'</h1>'; echo '<img srcset="'.$img_1x->url.' 1x, '.$img_2x->url.' 2x, '.$img_3x->url.' 3x" src="'.$img_1x->url.'"/>'; include("./foot.inc"); To test the behaviour I deleted the resized pictures in /site/assets/ and recalled this script above. I can't see changing the quality when I'm changing the 'quality' option. I also can't see the file size changing. Can anyone lead me to the solution? Am I doing something wrong? Thanks for your kind help Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 24, 2015 Share Posted March 24, 2015 Are you using a jpeg image? Pngs (and maybe gifs, too) can't have it's quality changed. 1 Link to comment Share on other sites More sharing options...
phippu Posted March 24, 2015 Author Share Posted March 24, 2015 Thanks alot! Haven't thought of that... But it's logic that png can't have it's quality changed. I took a look in the "ImageSizer.php". Wouldn't it be great to save every picture as JPG if the Quality is not 100? That would make sense at least for me. Maybe some others also stumbled over this? Would be great to discuss if this could be implemented. Something like this (in line 358): switch($this->imageType && CheckForQuality) { case IMAGETYPE_GIF: // correct gamma from linearized 1.0 back to 2.0 $this->gammaCorrection($thumb, false); $result = imagegif($thumb, $dest); break; case IMAGETYPE_PNG: if(!$this->hasAlphaChannel()) $this->gammaCorrection($thumb, false); // always use highest compression level for PNG (9) per @horst $result = imagepng($thumb, $dest, 9); break; case IMAGETYPE_JPEG: // correct gamma from linearized 1.0 back to 2.0 $this->gammaCorrection($thumb, false); $result = imagejpeg($thumb, $dest, $this->quality); break; } /wire/core/ImageSizer.php Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 24, 2015 Share Posted March 24, 2015 Jpeg can't handle transparency, which is the most prominent reason for not using it in the first place. Therefore a image conversion to jpeg should at least not be a default. Link to comment Share on other sites More sharing options...
phippu Posted March 24, 2015 Author Share Posted March 24, 2015 I agree with you that an image conversion shouldn't be default. On the other hand, it is specified to reduce the image quality and processwire doesn't do it by default (with a png image). To realise that the quality isn't reduced you have to have technical understanding whereas you do not need specific understanding to see that a transparent part of the image is missing. To the default discussion. In my oppinion it is also not very good to have an image sharpening effect as default. Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 24, 2015 Share Posted March 24, 2015 To the default discussion. In my oppinion it is also not very good to have an image sharpening effect as default. I had the same thoughts and even had a pull request on github which was supposed to change that. But the sharpening does not really sharpen the image in terms of oversharpeing, it's more to preserve sharp images from getting blurry from being downsized, which is what happens without it. Link to comment Share on other sites More sharing options...
phippu Posted March 24, 2015 Author Share Posted March 24, 2015 Well thank you for your help! maybe I'll find some time to improve the imSharpen method. I know Photoshop e.g. is also doing some sharpening at the end. The alternative to sharpening would be to use a better low-pass-filter before downsampling to not loose too much "sharpness". Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 24, 2015 Share Posted March 24, 2015 For improving the image processing you'll need to contribute to the gd library not processwire. Alternativly you could use imagemagick, which is more powerful than gd. 1 Link to comment Share on other sites More sharing options...
phippu Posted March 25, 2015 Author Share Posted March 25, 2015 I know what you mean but what at the moment is done by processwire is: Call the imagecopyresampled function. This function does something like (when making an image smaller): Convolution with a specific matrix (gaussian or box-blur) to blur it. This is the anti-aliasing filter to prevent some strange pattern in the picture Take pixels from that blury image and delete those who are not needed. The picture should (in theory) look not blurred because of the downsampling. But to get the best performance, the algorithms make a compromised solution, so a little aliasing patterns appear and it look sharp. Then Processwire does Sharpening. Sharpening is nothing else than doing a deconvolution to that downsampled picture with the (in theory) same matrix as in point 1.1. That means the Anti-Aliasing effect is gone and the picture looks like it never had filtering (which indeed is needed!) So this filtering could be saved and all that very CPU-intensive filtering could be omitted and just a "nearest-pixel-algorithm" be used (well almost ). Here are some pictures to show what i mean: Original Test Pattern can be viewed here. It has the dimensions 2400x1800. First of all I show the same picture resized with Photoshop using the "nearest-pixel-algorithm". It is to show, that without filtering those patterns appear: Processwire with the following options: $options = array( 'quality' => 100, 'upscaling' => false, 'sharpening' => 'none', ); Processwire with the following options: $options = array( 'quality' => 100, 'upscaling' => false, 'sharpening' => 'true', ); In those test patterns we can see that the algorithm imagecopyresampled is using is not the best. But probably a good mix between speed and quality. To show how photoshop in "bicubic auto" has done its work. here it is: 1 Link to comment Share on other sites More sharing options...
horst Posted March 25, 2015 Share Posted March 25, 2015 Hi phippu, interesting post. Maybe I can come back to this later, (im in hurry now), but want to note that you can use different sharpening methods with ImageSizer. It has 3 of those imageconvolution matrixes that only rely on the GD library. The values are: "soft", "medium" and "strong". and it has a USM implementation based on pur PHP-Code what is on by default and also uses those 3 paramnames. You can switch between them per global setting $config->imageSizerOptions["useUSM"] = true | false, or add it to your $options array on a per image base. You also can force the recreation on a per image base with adding "forceNew" = true | false to your $options array. (No need to delete variations manually or in an extra step) Ah, not to forget that the use of "defaultGamma" also affects the result: $options["defaultGamma"] = [0.4-4.0 | -1] (-1 is to disable it) You can add suffixes to image variation names per $options array: $options["suffix"] = [a-z0-9_-] By using suffixes you are able to create variations with different values for the same param avoiding overwriting them each other. A test setup for visual comparision of the possible sharpening outputs could be like that: $options = array('quality' => 100, 'upscaling' => false, 'forceNew' => true); $defaultGamma = array('dg0' => -1, 'dg1' => 2.2); $useUSM = array('usm1' => true, 'usm0' => false); $tests = array('s0' => 'none', 's1' => 'soft', 's2' => 'medium', 's3' => 'strong'); $image = $page->images->first(); foreach($defaultGamma as $k1 => $v1) { $options['defaultGamma'] = $v1; foreach($useUSM as $k2 => $v2) { $options['useUSM'] = $v2; foreach($tests as $k3 => $v3) { $options['sharpening'] = $v3; $options['suffix'] = $k1 . $k2 . $k3; $variation = $image->width(intval($image->width / 2), $options); echo "<p><img src='{$variation->url}' alt='{$variation->name}' /><br />{$variation->name}</p>"; } } } // (written in browser, not tested!) 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now