Bug 294594 - Gwenview does not preserve JPEG quality when saving images
Summary: Gwenview does not preserve JPEG quality when saving images
Status: RESOLVED DUPLICATE of bug 277996
Alias: None
Product: gwenview
Classification: Applications
Component: general (show other bugs)
Version: 2.8
Platform: Gentoo Packages Linux
: NOR normal
Target Milestone: ---
Assignee: Gwenview Bugs
URL:
Keywords: usability
: 305636 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-02-22 02:25 UTC by Vladimir Brik
Modified: 2019-03-07 20:40 UTC (History)
12 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
Change default jpeg quality to 95 (705 bytes, patch)
2013-05-22 16:20 UTC, tankyuushin
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir Brik 2012-02-22 02:25:35 UTC
Version:           2.8 (using KDE 4.8.0) 
OS:                Linux

Gwenview should preserve original image's JPEG quality level setting when saving modified images.

For example, if I use gwenview to crop a photo with JPEG quality 97, the saved file with have JPEG quality 85.

Instead, gwenview should use the same JPEG quality when saving as what the original had. 

Reproducible: Always

Steps to Reproduce:
Open JPEG image with quality level higher than 85.

Modify the image (e.g. crop)

Save modifications 

Actual Results:  
Saved image has JPEG quality level 85.

Expected Results:  
Saved image should have the same quality level as the original.
Comment 1 Christoph Feck 2012-02-22 11:03:07 UTC
The used quality is not saved in a JPEG file.
Comment 2 Vladimir Brik 2012-02-22 15:23:33 UTC
(In reply to comment #1)
> The used quality is not saved in a JPEG file.

I am not sure what you mean.

If I open an unedited photo in GIMP and choose "save a copy" it will ask for a confirmation that I want to use quality level 97. If I do it for the same photo after it was saved by gwenview, GIMP will ask if I want to use quality level 85. So quality level must be stored in the file.
Comment 3 Christoph Feck 2012-02-23 00:19:53 UTC
If your aim is to preserve the image quality as good as possible, you would have to save with quality 100. Even that value reduces the quality on each save.

What is your aim?
Comment 4 Vladimir Brik 2012-02-23 17:03:42 UTC
(In reply to comment #3)
> If your aim is to preserve the image quality as good as possible, you would
> have to save with quality 100. Even that value reduces the quality on each
> save.
> 
> What is your aim?

The main aim is to consistently preserve quality scale across multiple post-processing transformations (e.g. I use gwenview to make a first pass over hundreds of photos fresh from the camera, deleting obviously bad ones, fixing red eyes, and experimenting with various crops. I then use GIMP to further process a few photos that have the potential of being good).

If the original image's compression quality is 98, it should not become 75  after I use gwenview's red eye reduction. For one of my photos, using gwenview's red eye reduction changed file size five-fold from 3MB to 600KB, which was psychologically disconcerting even though there we no perceivable JPEG artifacts.

By the way, the quality numbers that I got from GIMP in my original post were incorrect. GIMP doesn't seem to preserve quality either: it defaults to lowering 98 to 95 and increasing 75 to 85, but it prompts the user to confirm the change.

While it can be argued that 75 is "good enough" in most cases, this is not a decision gwenview should make behind user's back because in some situations it will result in visually noticeable differences. This is especially relevant for cropping and scaling because they may exaggerate normally minor artifacts.

75 is on the lower end of "medium quality" setting on digital cameras. Effectively, saving images in gwenview turns photos taken at "high quality" into "medium quality" photos :)

I don't know whether compression quality is stored in JPEG files explicitly or needs to be calculated from some other information. Imagemagick's "identify" utility seems to report consistent values though.

Ultimately, this is not a huge deal for many people. However, arbitrary quality reduction will make gwenview less attractive to photography enthusiast.
Comment 5 Shlomi Fish 2012-02-24 21:09:04 UTC
Can reproduce here. I cropped an image with 95% JPEG quality and after saving it, it was saved with 85% quality.

By the way, you can determine what the JPEG quality is from the command-line by using ImageMagick's identify tool:

identify -verbose my.jpg | grep Quality
Comment 6 Benni Hill 2012-12-08 20:56:40 UTC
*** Bug 305636 has been marked as a duplicate of this bug. ***
Comment 7 tankyuushin 2013-05-22 16:18:29 UTC
I am bothered by this problem too. 

Quality is not stored in jpeg. Imagemagick seems to estimate it from quantization tables. I have no idea how that works, but the code is there, maybe this could be picked up for gwenview. I suppose it would be "The Right Thing" to just preserve quality without nagging the user about it.

An easy work around would be adding a setting for a default jpeg quality. 

Unfortunately, my programming skills are just enough for a really quick and dirty fix, which I will add as an attachment: Just default to quality 95 instead of 75. This is still high without driving the filesize through the roof.
Comment 8 tankyuushin 2013-05-22 16:20:17 UTC
Created attachment 80024 [details]
Change default jpeg quality to 95
Comment 9 Benni Hill 2013-05-23 19:25:13 UTC
Thanks for your patch.
I was considering using digikam's save dialog for gwenview as it already supports selecting compression level/quality. At first glance I don't think it's hard to implement, so if you want you could have a look at it. It's in common/filesaveoptions.cpp/h and is used in editor/editorwindow.cpp (EditorWindow::showFileSaveDialog).
Comment 10 emmanuel.manchester314 2013-11-30 14:41:12 UTC
Hi,

I could not remember the command, so it took me time before reposting.
the command identify from imagemagick allows one to know the quality

identify -verbose *.jpg | grep -i quality

Regards
Comment 11 Janet 2014-02-10 02:35:03 UTC
The images here are saved with quality 75 (according to identify) which is a real no-go. The images saved with gwenview as jpg can only be used for web previews and trash :(. Workaround by now is to save as png and afterwards use imagemagick to convert it to jpg...

It would be good if the user could set the jpg quality in gwenview's options - or even better if the user could choose the quality level in the save dialog. It depends on the what you want to do with the picture. When I want to use it as wallpaper I want the wallpaper without jpg artefacts (quality 95-99), if I want to scale it down for web 75 is rather ok (but even in that case I would choose 85).
Comment 12 luc 2014-09-07 08:59:05 UTC
The default of 75 is very poor indeed!  That produces highly noticeable artifacts.  These perhaps are invisible only after serious downsampling, like when viewing on-screen of ultra high resolution images produced by modern cameras (just my theory to explain why the gwenview developers could ever have accepted this). 

A default of 95 would indeed be much better.  If lower quality is needed then its always possible to use batch processing on a whole directory, like with Phatch.  But the reverse is final: you can never restore quality after a file was saved with 75. 

The more professional approach would of course be: by default keep the quality of the original file automatically, but optionally (tickmark) let the user define a different quality.  These settings would preferably be added to the save dialog, as was mentioned by Janet.

I've found a Python code example in the Phatch source of how to detect the quality automatically (in /usr/share/phatch/phatch/lib/imtools.py):


def get_quality(im, size, format, down=0, up=100, delta=1000, options=None):
    """Figure out recursively the quality save parameter to obtain a
    certain image size. This mostly used for ``JPEG`` images.

    :param im: image
    :type im: pil.Image
    :param format: image file format (e.g. ``'JPEG'``)
    :type format: string
    :param down: minimum file size in bytes
    :type down: int
    :param up: maximum file size in bytes
    :type up: int
    :param delta: fault tolerance in bytes
    :type delta: int
    :param options: image save options
    :type options: dict
    :returns: save quality
    :rtype: int

    Example::

        filename = '/home/stani/sync/Desktop/IMGA3345.JPG'
        im = Image.open(filename)
        q = get_quality(im, 300000, "JPEG")
        im.save(filename.replace('.jpg', '_sized.jpg'))
    """
    if options is None:
        options = {}
    q = options['quality'] = (down + up) / 2
    if q == down or q == up:
        return max(q, 1)
    s = get_size(im, format, **options)
    if abs(s - size) < delta:
        return q
    elif s > size:
        return get_quality(im, size, format, down, up=q, options=options)
    else:
        return get_quality(im, size, format, down=q, up=up, options=options)
Comment 13 luc 2014-09-07 10:14:37 UTC
Sorry, I had not looked carefully at that code. It looks like it finds not the quality that was used in a file, but rather what quality should be used to get a certain file size.   
The relation between file size and compression quality is not straightforward and so this algorithm is not useful in this context I'm afraid.
Adapting compression quality to target a file size is usually done on cameras, where this is done to allow prediction of available storage space in number of pictures.  But this approach is a bad idea for setting image quality because it produces a variable image quality, depending on the average amount of detail in the scene.  For example the same bird against the same blue sky will get more artifacts if there is also highly detailed grass elsewhere in the scene.
Comment 14 Christoph Feck 2014-09-07 15:16:36 UTC
> you can never restore quality after a file was saved with 75.

Just to burst this myth: Even if you save with a higher level compared to the previously used level, the quality will be reduced, because JPEG is lossy. This is especially true with today's JPEG implementations that use (faster) integer-based transformations, which accumulate more rounding errors compared to the float-based transformations.

See also comment #3.
Comment 15 luc 2014-09-09 18:14:46 UTC
I'm well aware of that, there was no myth.  I should probably have said: "you can never restore the quality to 95 after the file was saved with a quality of 75".    Saving with 95 is indeed still lossy, but the loss is then small enough to be nearly unnoticeable on the vast majority of photographs, and I guess 95 is probably about as good as the off-camera "fine" setting, so there is little to gain from saving in an uncompressed format. 

BTW any idea when the patched Gwenview (that saves with 95) will be available?
Comment 16 Christoph Feck 2014-09-09 20:20:47 UTC
I haven't seen a commit that changes the quality level. A user changeable setting would be more appropriate actually.
Comment 17 Morgan Leijström 2016-12-19 16:31:41 UTC
Ping?
Comment 18 Nate Graham 2017-09-08 18:35:51 UTC
If anyone wanted to modify that patch to save using the quality setting that the picture is currently using (as roughly determined by imagemagick), I think we could consider that.
Comment 19 Nate Graham 2017-09-09 04:48:50 UTC
*** Bug 333733 has been marked as a duplicate of this bug. ***
Comment 20 DrSlony 2017-09-11 14:11:38 UTC
Gwenview should let the user decide on the compression quality and in the case of JPEG files on the chroma subsampling.

1. Hard-coding any compression level is wrong.
2. Hard-coding any chroma subsampling method is wrong.
3. Forcing images to save using a guesstimate of their original compression quality and chroma-subsampling is wrong.

Regarding compression quality.
What happens when you open an image saved at compression quality 80, crop it, and save it at compression quality 98? The result looks worse than it did at 80%.

1a. This image was saved from lossless to JPEG using compression quality 80 and 4:2:0 chroma subsampling:
https://filebin.net/f6ynfe1acaqtxc68/img_80x1_4_2_0.jpg

1b. This image was saved from lossless to JPEG using compression quality 80 and 4:2:0 chroma subsampling, then the output was used as input and re-saved using quality+1, and so looped all the way up until it reached quality 100:
https://filebin.net/f6ynfe1acaqtxc68/img_80-100_4_2_0.jpg

1c. This image was saved from lossless to JPEG using compression quality 80 and 4:2:0 chroma subsampling, then the output was used as input and re-saved using the exact same quality 80, this was done 21 times:
https://filebin.net/f6ynfe1acaqtxc68/img_80x20_4_2_0.jpg

In order of quality they are 1a, 1c, 1b. Using a low quality is bad enough, but re-saving using a different quality than the original can be worse.

Regarding chroma subsampling, again the user should be able to choose. When saving a screenshot as JPG, even a high quality won't help you if you're not using 4:4:4 chroma subsampling, because screenshots typically have 1 pixel-wide lines and their color will be destroyed unless using 4:4:4. Then again, saving a 24 megapixel photo at its full size using 4:4:4 is just a waste of space as your lens is unlikely to be sharp enough to capture pixel-wide detail, however if you downsize this 24 megapixel image to say 900x900, now the situation is different. Now your small photo can have pixel-wide detail, just as a screenshot. Save a downscaled photo of distant street lights or christmas tree lights without using 4:4:4 and you get garbage

Assuming that the desired output quality and chroma subsampling should be the same as the input is to misunderstand how the whole thing works.

Let the user choose.
Comment 21 Nate Graham 2019-03-07 20:40:19 UTC
Yep, we'll make this user-adjustible.

*** This bug has been marked as a duplicate of bug 277996 ***