Problems with quality/filesize on PNG image resize (default gd toolkit)

I uploaded my picture (a website screenshot) which was a 824x1030 PNG, 154 KB,
My 'preview' size is 640x640 max, and my result was scaled to 512x640.
BUT the filesize ballooned to 210 KB - for a SMALLER image.
My "Image Toolkit" quality setting is still the default 75%
The original image wasn't especially optimized for export, just a 'save as' via Paintshop Pro (Which I always use as it does give me good file sizes)

I repeated the process with a PNG of the same, and got
Original : 183 KB
Preview : 57 KB
... so that's exactly as expected.

Looks like the PNG output settings are dialed up to full quality. I guess this is a gd toolkit issue, and I suppose the imagemagick library also addresses it, but ... I want to use PNGs. I trust them more.

AH! In image.inc, image_gd_close() only uses the quality setting for jpgs.
According to the docs http://nz2.php.net/manual/en/function.imagepng.php
imagepng() - the filetype-specific close_func - is happy to take a 'quality' argument also (although the number is different) !
So why not?
... AH. Bugger. The quality parameter was added in PHP 5.1.2
That will not help some people.
However http://nz2.php.net/manual/en/function.imagepng.php#78787
it seems like adding the parameter anyway will not cause problems in PHP4

I've got 5.1.2, lets' see...
... BUT it doesn't seem to work as advertised.

/**
 * GD helper to write an image resource to a destination file.
 */
function image_gd_close($res, $destination, $extension) {
  $extension = str_replace('jpg', 'jpeg', $extension);
  $close_func = 'image'. $extension;
  if (!function_exists($close_func)) {
    return FALSE;
  }
  if ($extension == 'jpeg') {
    return $close_func($res, $destination, variable_get('image_jpeg_quality', 75));
  }
  else if ($extension == 'png') {
    return $close_func($res, $destination, floor((100 - variable_get('image_jpeg_quality', 75))/10) );
  }
  else {
    return $close_func($res, $destination);
  }
}

- It ran, but I got the same size output.

Bum. Looks like there's no fix there.

Maybe I should forcably cast my derivatives into JPEGs? It's a bit peculiar, but there's no point in me having/embedding reduced-quality previews that are larger than the original!
I was noticing earlier that even my thumbnails were like 17KB each where they should have been like 3. This does slow the bandwidth down heaps more than it should...

Is that a logical configuration option to add?

Comments

dman’s picture

Edit

I repeated the process with a PNG JPG of the same, and got
Original : 183 KB
Preview : 57 KB

dman’s picture

Good grief.
I tried enabling imagemagick instead
and now my 154 KB image is converted to a 244.08 KB preview! (and the quality is worse if anything)
I'm gonna hack in a conversion to jpgs, looks like there is no system-level fix.

dman’s picture

Because I think it's interesting, and a stand-alone task, I've defined and posted this as a GHOP suggestion http://drupal.org/node/200817

I'm happy to see any fix that ends up with decent-sized images - even if it produces picture.png -> picture.thumbnail.jpg results. I'm sure the drupal/filesystem storage can handle the idea. I'm not sure if anyone over here in image.module would have technical/semantic objections to this solution however. I really like consistency, but this idea doesn't irk me as much as the really big file sizes.

Does anyone want to chime in on that thread? Looks like we need a tiny bit of buy-in or support there. :-)

ansorg’s picture

hi,

I stumbled across this issue too #238033: created thumbnail files blurry and larger than original PNG. I switched from DG to imgmagick and the issue remains. After thinking some more about this I think it's not an error in the image toolkit.

It's in the nature of the lossless PNG compression that PNG is good at compressing vector drawings or images with clean structures like screenshots of plain gray user interfaces. But PNG is not good at images with lots of noise, antialiasing, photographic images.

Now, when a clean vector image or screenshot gets scaled down the usually applied antialiasing adds lots of noise (if there was one white and one black pixel next to each other, after the rescale there are now gray levels inbetween). So the original clean image is now more noisy and suddenly it's no longer a good candidate for the PNG file type.

Perhaps Two possible solutions?
1) as mentioned above, create derivate images as JPG
2) scale without interpolation/antialias to keep sharp edges in the pictures for good PNG compression

Could be that results of #2 are too ugly anyway and #1 would be the only possible solution. I'm just a user of drupal, haven't looked at the code (so far) and have no idea whether one of the twos is possible. Has somebody actually taken on the GHOP task?

Jens

dman’s picture

I haven't seen the option in the available toolkits that allows for scaling without antialias, so don't know if that's possible.
I thought that the PNG encoding had an option to use jpeg lossy compression under the hood, but I've not seen that flag ever exposed in any image program or algorithm, so it may have been my imagination.

In other, related news, this week we were building an incredibly graphic intensive site, full of PNGs with full alpha... but they were huge. 300+K each for 400x400 sorta images. Unacceptable. But we really wanted Alpha.

Oddly, there is an (incredibly wrong) work-around by encoding these images into transparent Flash blobs! we can get jpeg-size compression levels (more like 30K for the above images) AND transparency by embedding flash objects everywhere.
It hurts my head... but it seems to be doing the trick. Does slow down the browser response slightly on every page load as it initializes those objects however :-{
I feel dirty.

sun’s picture

Status: Active » Closed (cannot reproduce)

Sorry, without further information this issue can only be closed as not reproducible.

Feel free to re-open this issue if you want to provide further information. Thanks.