Jump to content

Can't change picture quality in downsizing


phippu
 Share

Recommended Posts

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

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

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

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

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

I know what you mean but what at the moment is done by processwire is:

  1. Call the imagecopyresampled function.
    This function does something like (when making an image smaller):
    1. 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
    2. Take pixels from that blury image and delete those who are not needed.
    3. 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.
  2. ​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 :rolleyes:).

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:

star-chart-500-photoshop-nearest.jpg

Processwire with the following options:

$options = array(
  'quality' => 100,
  'upscaling' => false,
  'sharpening' => 'none',
);
star-chart-500-pw-no_sharpen.jpg
 
 

Processwire with the following options:

$options = array(
  'quality' => 100,
  'upscaling' => false,
  'sharpening' => 'true',
);
star-chart-500-pw-with_sharpen.jpg
 
 
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:
star-chart-500-photoshop-bicubicauto.jpg
  • Like 1
Link to comment
Share on other sites

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!)
  • Like 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...